Dev Note/Java2008. 3. 11. 20:29


SEED 알고리즘에 대해 간략하게 알아봤으니 이제 SEED 알고리즘 Java API를 알아본다.
밑의 소스는 KISA에서 제공하는 Java API를 조금 변경 및 추가하여 사용할 수 있게 만든 소스이다. 상단의 첨부 파일은 API와 Padding, 사용 예제가 압축되어 있다.

-- SEED API (KISA에서 제공한 API를 조금 변경 및 추가 한것)
해당 소스는 좀 많은 관계로 모든 소스를 다루지 않고, 추가 된 부분만을 다룬다. 여기서 다루지 않은 부분은 KISA에서 제공한 API 그대로라고 생각해도 무방하다.

   /**
      * 한국정보보호진흥원 소스에 없는 추가 된 함수로 입력 받은 바이트 데이터를 암호화 하여 리턴한다.
      *
      * @param inData String 평문
      * @param szKey byte[] key
      * @return byte[] 암호화 된 데이터
      */
   public byte[] encrypt(byte[] sbuffer, byte szKey[]) {
      int sRoundKey[] = new int[32];
      SeedEncRoundKey(sRoundKey, szKey);
     
      byte[] inDataBuffer = padding.addPadding(sbuffer, SeedBlockSize);
      byte[] encryptBytes = new byte[inDataBuffer.length];

      int rt = inDataBuffer.length / SeedBlockSize;
      for (int j = 0; j < rt; j++) {
         byte sSource[] = new byte[SeedBlockSize];
         byte sTarget[] = new byte[SeedBlockSize];
         System.arraycopy(inDataBuffer, (j * SeedBlockSize), sSource, 0, SeedBlockSize);
         
         SeedEncrypt(sSource, sRoundKey, sTarget);
         
System.arraycopy(sTarget, 0, encryptBytes, (j * SeedBlockSize), sTarget.length);
      }

      return encryptBytes;
   }

   /**
      * 한국정보보호진흥원 소스에 없는 추가 된 함수로 입력 받은 문자열을 암호화 하여 리턴한다.
      *
      * @param inData String 평문
      * @param szKey byte[] key
      * @return byte[] 암호화 된 데이터
      */
   public byte[] encrypt(String inData, byte szKey[]) {
      return encrypt(inData.getBytes(), szKey);
   }

   /**
      * 한국정보보호진흥원 소스에 없는 추가 된 함수로 입력 받은 문자열을 특정 Charset으로 변환하여
      * 암호화 하여 리턴한다.
      *
      * @param inData String 평문
      * @param szKey byte[] key
      * @param charset String String을 byte 데이터로 변환할때 사용할 charset
      * @return byte[] 암호화 된 데이터
      */
   public byte[] encrypt(String inData, byte szKey[], String charset) throws UnsupportedEncodingException {
      return encrypt(inData.getBytes(charset), szKey);
   }

   /**
      * 한국정보보호진흥원 소스에 없는 추가 된 함수로 암호화 된 바이트 데이터를 받아서 복호화한다.
      *
      * @param encryptBytesbyte[] 암호화 된 바이트 데이터
      * @param szKey byte[] key
      * @return byte[] 복호화 된 바이트 데이터
      */
   public byte[] decrypt(byte[] encryptBytes, byte[] szKey) {
      int sRoundKey[] = new int[32];
      byte[] decryptBytes = new byte[encryptBytes.length];
      SeedEncRoundKey(sRoundKey, szKey);
      int rt = encryptBytes.length / SeedBlockSize;

      byte sSource[] = new byte[SeedBlockSize];
      byte sTarget[] = new byte[SeedBlockSize];
      for (int j = 0; j < rt; j++) {
         System.arraycopy(encryptBytes, (j * SeedBlockSize), sSource, 0, SeedBlockSize);
         SeedDecrypt(sSource, sRoundKey, sTarget);
         
         System.arraycopy(sTarget, 0, decryptBytes, (j * SeedBlockSize), SeedBlockSize);
      }
     
      return padding.removePadding(decryptBytes, SeedBlockSize);
   }

   /**
      * 한국정보보호진흥원 소스에 없는 추가 된 함수로 암호화 된 바이트 데이터를 받아서 복호화하여
      * 문자열로 반환한다.
      * @param encryptBytes byte[] 암호화 된 바이트 데이터
      * @param szKey byte[] key
      * @return byte[] 복호화 된 바이트 데이터
      */
   public String decryptAsString(byte[] encryptBytes, byte[] szKey) {
      return new String(decrypt(encryptBytes, szKey));
   }

   /**
      * 한국정보보호진흥원 소스에 없는 추가 된 함수로 암호화 된 바이트 데이터를 받아서
      * 복호화하여 지정한 charset으로 문자열로 반환한다.
      *
      * @param encryptBytes byte[] 암호화 된 바이트 데이터
      * @param szKey byte[] key
      * @param String charset 복호화 된 바이트 데이터를 문자열로 변환할 때 사용할 Charset
      * @return byte[] 복호화 된 바이트 데이터
      */
   public String decryptAsString(byte[] encryptBytes, byte[] szKey, String charset)
         throws UnsupportedEncodingException {
      return new String(decrypt(encryptBytes, szKey), charset);
   }

여기서 Padding Object는 블록 암호화의 특징은 정해진 블록 사이즈를 맞추기 위해 모자란 부분에 대한 Padding을 의미하는데, KISA에서 제공하는 API에는 Padding이 구현되어 있지 않아 ANSI X.923 Padding을 구현하여 사용하였다.

-- ANSI X.923 Padding
모자란 부분에 대해 일정한 규칙으로 채우는 것을 Padding이라 하는데, 많은 규칙 중의 하나이다. 규칙은 간단하다 모자란 byte 수에 대해 패딩되는 가장 마지막 byte는 패딩 된 byte 수를 의미하고 나머지는 "0x00"으로 채운다.
16 byte 블록에서 10 byte에 대한 값을 Padding 한다면
   0xDD 0xDD 0xDD 0xDD 0xDD 0xDD 0xDD 0xDD 0xDD 0xDD 0x00 0x00 0x00 0x00 0x00 0x06
이 된다.

-- 사용 예제 소스
   public static void main(String[] args) throws Exception {
      String text = "Seed 암호화 Test \t 잘되겠지. HaHa~~";
      String key = "junducki_goormaa";
      StringBuilder trace = new StringBuilder();
 
      trace.append("Plain Text :: [").append(text).append("]");
      System.out.println(trace.toString());
 
      SeedCipher seed = new SeedCipher();
      String encryptText = Base64.encode(seed.encrypt(text, key.getBytes(), "UTF-8"));

      trace = new StringBuilder();
      trace.append("Encrypt Text (Base64 Encoding) :: [").append(encryptText).append("]");
      System.out.println(trace.toString());
 
      byte[] encryptbytes = Base64.decode(encryptText);
      String decryptText = seed.decryptAsString(encryptbytes, key.getBytes(), "UTF-8");
 
      trace = new StringBuilder();
      trace.append("Decrypt Text :: [").append(decryptText).append("]");
      System.out.println(trace.toString());
   }

위 예제는 첨부파일에 들어있으며, SeedCipher를 이용하여 문자열을 암호화, 복호화 하여 원문이 다시 나오는지 여부를 확인 할 수 있는 소스이다. 여기서 암호화 후 생성 된 bytes는 랜덤한 값이 나오기 때문에 Base64를 이용하여 Encoding 하였고, 복호화 할때는 Decoding 하여 처리한다.

이것으로 SEED에 대해 (1), (2)에 걸쳐 알아보왔다. 여기서 소개한 SEED에 대한 부분은 극히 일부이므로, 좀더 자세히 알고자 한다면 한국정보보호진흥원(KISA) 또는 다른 곳에서 자료를 더 찾아보기 바란다.

Posted by as.wind.914