반응형

암호화 알고리즘을 선택하는 것은 정부 기관 KISA 인터넷진흥원에서 제공하는 표준 안내서를 참고하였다.

데이터 암호화에 대한 가이드는 다른 출처에서도 찾아볼 수 있다. 하지만 KISA의 안내서를 선택한 이유는 KISA가 공신력이 있는 기관이고, 우리나라 법률을 반영한 안내서를 제공하고 있을 것이라는 생각이어서다. 참고로 개인정보에 대한 법률 조항은 기관마다 조금씩 다른데, 이 때는 모두 충족하는 것을 원칙으로 한다.


어떤 알고리즘을 선택해야할까?

데이터의 성격에 따라 암복호화 알고리즘 유형이 다르며, 유형 내에서도 다양한 암복호화 알고리즘이 존재한다.

패스워드는 일방향(해쉬함수) 암호화, 바이오 정보는 블록암호 알고리즘을 선택하기를 권고하고 있다.

KISA에서 2017년에 개정한 개인정보 암호화 안내서를 참고하여 알고리즘을 선택했다.

개인정보의 암호화 조치 안내서(개정) : https://www.privacy.go.kr/inf/rfr/selectBoardArticle.do;?nttId=7635&bbsId=BBSMSTR_000000000044

 

SEED를 선택한 이유

  1. 블록암호 대칭키 알고리즘이다.
  2. KISA에서 권고한 안전한 알고리즘 (p.16 안전한 암호 알고리즘 참고)
  3. 국가정보원 검증 대상 알고리즘 (p80. [참고 2] 국가정보원 검증대상 암호 알고리즘 목록을 참고)

KISA SEED_CBC 알고리즘 적용 예제

SEED 알고리즘 내에서도 운영모드에 따라 알고리즘이 조금씩 달라진다. 일반적으로 많이 사용되는 CBC 운영모드를 선택하였다. KISA 인터넷진흥원 자료실에서 SEED 암복호화 알고리즘을 언어별로 다운로드할 수 있다.

다운로드 링크 : https://seed.kisa.or.kr/kisa/Board/17/detailView.do

압축 해제 후 아래 디렉토리에 위치한 java 파일을 프로젝트로 옮겨서 사용했다.

.../KISA_SEED_ECB_CBC_CTR_CCM_GCM_CMAC/[02] JAVA/[02] CBC

public class KISA_SEED_CBC {
	...
}

 

테스트 코드를 작성하여 암복호화가 정상적으로 이루어지는 지 확인해보자.

@Slf4j
public class SeedTest {

    private final byte[] pbszUserKey = "testCrypt2020!@#".getBytes();
    private final byte[] pbszIV = "1234567890123456".getBytes();

    @Test
    public void 암복호화_테스트() {
        // given
        String rawMessage = "테스트 데이터";
        log.info("원본 데이터 =>" + rawMessage);

        // when
        byte[] encryptedMessage = KISA_SEED_CBC.SEED_CBC_Encrypt(pbszUserKey, pbszIV, rawMessage.getBytes(), 0, rawMessage.getBytes().length);
        log.info("암호화된 데이터1 => " + new String(encryptedMessage));
        log.info("암호화된 데이터2 => " + encryptedMessage.toString());

        byte[] decryptedMessage = KISA_SEED_CBC.SEED_CBC_Decrypt(pbszUserKey, pbszIV, encryptedMessage, 0, encryptedMessage.length);
        log.info("복호화된 데이터 => " + new String(decryptedMessage));

        // then
        assertThat(rawMessage).isEqualTo(new String(decryptedMessage));
        assertThat(rawMessage).isNotEqualTo(encryptedMessage);
    }
}

테스트코드가 정상적으로 통과되었다.

[중요]

  1. 위 코드에서는 바이너리를 인코딩하는 부분이 생략되어있다. 암복호화는 정상적으로 되지만 로그를 통해 암호화된 값을 확인할 수는 없는 상태이다. (다음 포스팅에서 인코딩에 대해 다룬다.)
  2. pbszUserKey는 암복호화하는 데 사용하는 비밀키이다. 현재 테스트를 위해서 같은 코드라인 내에 두었지만 마지막 포스팅에서 비밀키를 별도로 관리하는 방법에 대해 다루겠다.
  3.  pbszIV는 초기화 벡터키로, 비밀키와 마찬가지로 16비트로 구성해야한다.

이제 SEED 알고리즘을 암복호화를 사용하기 쉽게 별도의 클래스를 작성한다.

public class Seed {
    private static final byte[] pbszUserKey = "testCrypt2020!@#".getBytes();
    private static final byte[] pbszIV = "1234567890123456".getBytes();

    public static byte[] encrypt(String rawMessage) {
        byte[] message = rawMessage.getBytes(StandardCharsets.UTF_8);
        byte[] encryptedMessage = KISA_SEED_CBC.SEED_CBC_Encrypt(pbszUserKey, pbszIV, message, 0, message.length);
        return encryptedMessage;
    }

    public static String decrypt(byte[] encryptedMessage) {
        byte[] decryptedMessage = KISA_SEED_CBC.SEED_CBC_Decrypt(pbszUserKey, pbszIV, encryptedMessage, 0, encryptedMessage.length);
        return new String(decryptedMessage, StandardCharsets.UTF_8);
    }
}

SEED 알고리즘 메소드로 데이터를 암복호화할 경우 데이터 타입은 byte[]이다. 하지만 DB에 저장하려면 String으로 형변환을 해야할 것 같다. 그리고 테이블의 컬럼 타입 또한 암호화된 데이터에 맞게 varchar(24) 등으로 모델링을 변경하면 되겠지?

자^^... 바이너리 인코딩에 아무 생각이 없었기 때문에 쉽게 늪에 빠지기 쉽다.

다음 포스팅을 통해 Seed 클래스를 어떻게 바꾸었고, 암호화된 데이터를 DB에 넣기 위해 어떻게 변환하였는 지 자세히 알아보자.

 

 

반응형