티스토리 뷰

 

암호화를 하자! 암호화를 하자!

 

 

회원제 서비스를 구현하게 될 때 무심코 모든 회원의 정보를 하나의 테이블에 넣는 경우가 있습니다.

(물론 취향의 차이로 존중해줄 수 있습니다.ㅎㅎ)

 

이 상태에서 만약 DB가 해킹된다면?

회원 정보를 담은 테이블을 읽으면 김명준의 본명과 주소지를 알아낼 수도 있습니다.

이를 예방하기 위해서 DB에 넣을 때 소중한 정보를 암호화하여 넣어줄 수 있습니다.

그렇게 암호화된 정보를 DB에 저장할 시 ,

DB 를 해킹하더라도 암호키를 알지 못한다면, DB에서는 알 수 없는 값이 보여지기 때문에 개인정보를 알아내기 어렵습니다.

 

 


 

그럼 다시, 회원의 모든 정보를 암호화해서 넣어줘야 할까?

 

 

물론 모든 정보에 대해 암호화하여 관리하면 더 안전할 겁니다.

그러나 자주 사용되고 중요하지 않은 공개될 수 있는 (공개 게시물 제목, 내용과 같은)데이터라면, 빠르게 넣고 뺄 수 있도록 본래 값을 DB에 넣고 민감한 정보는 암호화해서 넣는 것이 더 좋다고 생각합니다.

 

 

그렇기에 암호화해야 할 데이터와 암호화 하지 않아도 되는 데이터를 분리해서 DB에 넣고 빼면 좋지 않을까요?

예시로 Member에 대한 Entity 를 아래와 같이 분리할 수 있다고 생각합니다.

 

@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@Entity
public class Member extends BaseEntity {
    @Column(name = "login_id", nullable = false)
    private String loginId;

    @Column(name = "password", nullable = false)
    private String password;

    @Getter
    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "member_info_id", referencedColumnName = "id", nullable = false)
    private MemberInfo memberInfo;

		// ... 
}

 

 

OneToOne으로 연결된 MemberInfo

@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@ToString
@Entity
public class MemberInfo extends BaseEntity {

    @Column(name = "name", nullable = false)
    private String name;

    @Enumerated(EnumType.STRING)
    @Column(name = "role", nullable = false)
    private Role role;

    @Enumerated(EnumType.STRING)
    @Column(name = "gender", nullable = false)
    private Gender gender;

 

 

위의 두 Entity 를 참고로, 로그인을 위한 Member 정보와 (비밀번호는 암호화한다.)

회원의 개인정보를 분리해서 암호화하여 관리한다면

데이터베이스에 값을 넣고 뺄 때,

암호화가 필요한 필드에 대한 팀원 간의 이해 비용을 낮출 수 있고

본인이 다시 코드를 보았을 다시 이해하기도 좋다고 생각합니다.

 

 

암호화를 위해서, 애플리케이션 단에서는 대칭키로 데이터에 접근할 수 있도록 합니다. 

 

@Component
public class SymmetricKeyEncoder {

    private static SymmetricEncoderProperties symmetricEncoderProperties;

    private SymmetricKeyEncoder(SymmetricEncoderProperties symmetricEncoderProperties) {
        SymmetricKeyEncoder.symmetricEncoderProperties = symmetricEncoderProperties;
    }

    public static String encrypt(String plaintext) {
        try {
            Cipher cipher = Cipher.getInstance(symmetricEncoderProperties.getChipper());
            cipher.init(Cipher.ENCRYPT_MODE, symmetricEncoderProperties.getEncodeKey());
            byte[] encryptedBytes = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));
            return Base64.getEncoder().encodeToString(encryptedBytes);
        } catch (Exception e) {
            throw new RestApiException(CommonError.ENCODE_ERROR);
        }
    }

    public static String decrypt(String ciphertext) {
        try {
            Cipher cipher = Cipher.getInstance(symmetricEncoderProperties.getChipper());
            cipher.init(Cipher.DECRYPT_MODE, symmetricEncoderProperties.getEncodeKey());
            byte[] decodedBytes = Base64.getDecoder().decode(ciphertext);
            byte[] decryptedBytes = cipher.doFinal(decodedBytes);
            return new String(decryptedBytes, StandardCharsets.UTF_8);
        } catch (Exception e) {
            throw new RestApiException(CommonError. DECODE_ERROR);
        }
    }
}

 


결론

암호화하는 방식과 테이블의 관리 방식은 취향에 따라 충분히 다를 수 있다고 생각합니다. 그러나, 노출이 되어서는 안되는 중요한 정보일 경우 DB에 넣을 때 암호화하여 넣는 것이 좋다고 생각합니다. 더불어 암호화된 테이블과 암호화되지 않은 테이블에 대한 분리가 되어 있다면 암호화와 복호화 작업에 대한 코드를 보다 더 쉽게 반복된 코드를 줄여 작성할 수 있고 협업 시에 이해 비용을 낮출 수 있다고 생각합니다.

 

 

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함