BLOG ARTICLE SEED | 2 ARTICLE FOUND

  1. 2008.03.11 SEED 알고리즘 (2) - Java API
  2. 2008.03.11 SEED 알고리즘 (1) - SEED 알고리즘 이란 ?

Dev Note/Java 2008.03.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) 또는 다른 곳에서 자료를 더 찾아보기 바란다.

신고

Dev Note/Java 2008.03.11 17:23



JCE에는 포함되어 있지 않은 SEED 알고리즘에 대해 (1), (2) 부로 하여 간단하게 알아보고 API를 사용하여 테스트 예제도 한번 만들어 본다.

-- SEED 암호화 알고리즘 이란?
SEED 암호화 알고리즘은 민간 부분인 인터넷, 전자상거래, 무선 통신 등에서 공개 시 민감한 영향을 미칠 수 있는 정보의 보호황 개인 프라이버시 등을 보호하기 위하여 1999년 2월 한국정보보호센터(KISA)에 의해 개발 된 블럭암호알고리즘이다.
대칭키 블록 암호알고리즘으로 비밀성을 제공하는 암호시스템의 중요 요소이다. n 비트 블록 암호알고리즘이란 고정 된 n 비트 평문을 같은 길이의 n 비트 암호문으로 바꾸는 함수를 말한다. 이러한 변형 과정에 암/복호키가 작용하여 암호화와 복호화를 수행한다.
Feistel 구조란 각각 n/2 비트인 L0, R0 블록으로 이루어진 n 비트 평문 블록 (L0, R0)이 r 라운드(r ≥ 1)를 거쳐 암호문(Lr, Rr)으로 반환되는 반복 구조이다.

-- SEED 알고리즘 구조
SEED 알고리즘의 전체 구조는 Feistel 구조로 이루어져 있으며, 128비트의 평문 블록과 128비트 키를 입력으로 사용하여 총 16라운드를 거쳐 128비트 암호문 블록을 출력한다.
사용자 삽입 이미지

[ SEED 알고리즘 전체 구조도 ]

F 함수
Feistel 구조를 갖는 블록 암호알고리즘은 F 함수의 특성에 따라 구분될 수 있다. SEED의 F 함수는 수정된 64비트 Feistel 형태로 구성된다. F 함수는 각 32비트 블록 2개 (C, D)를 입력으로 받아, 32 비트 블록 2개(C', D')를 출력한다. 즉, 암호화 과정에서 64비트 블록(C, D)와 64비트 라운드 키 Ki = (Ki,0 : Ki,1)를 F 함수의 입력으로 처리하여 64비트 블록(C', D')을 출력한다. (i : 라운드 수)
사용자 삽입 이미지

[ F-함수 ]

사용자 삽입 이미지

[ F-함수 구조도 ]

G 함수
G 함수는 다음과 같다.
사용자 삽입 이미지
사용자 삽입 이미지

[ G - 함수 ]

S-Box
G 함수의 내부에 사용되는 비선형 S-Box S1, S2는 다음의 식을 이용하여 생성된다. (n1 = 247, n2 = 251, b1 = 159, b2 = 56)
사용자 삽입 이미지

[ S - Box ]

라운드 키 생성과정
SEED의 라운드 키 생성과정은 128비트 암호키를 64비트씩 좌우로 나누어 이들을 교대로 8비트씩 좌/우로 회전이동한 후, 결과의 4워드들에 대한 간단한 산술연산과 G 함수를 적용하여 라운드 키를 생성한다. 라운드 키 생성과정은 기본적으로 하드웨어나(모든 라운드 키를 저장할 수 없는) 제한 된 자원을 갖는 스마트카드와 같은 응용에서의 효율성을 위하여, 암호화나 복호화시 암호화키로부터 필요한 라둔드 키를 간단히 계산할 수 있도록 설계되었다.
주어진 128비트 암호키 K = A || B || C || D를 32비트 레지스터 A, B, C, D로 나눈다. 각 라운드 i에 사용되는 라운드 키 Ki = (Ki,0 : Ki,1)는 다음과 같은 방식으로 생성한다.
사용자 삽입 이미지

[ 라운드 키 생성과정에 사용된 상수 ]

사용자 삽입 이미지

[ 라운드 키 생성과정 구조


지금까지 SEED 암호알고리즘에 대해 알아봤다. 위의 내용은 한국정보보호진흥원(KISA)에서 제공한 정보가 거의 대부분이다. 상단에 KISA에서 제공하는 SEED에 관련 된 문서를 올리니 참조하기 바란다.

KISA의 SEED HomePage : http://www.kisa.or.kr/kisa/seed/jsp/seed.jsp

다음은 KISA에서 제공하는 SEED 알고리즘 Java API를 조금 변형한 것과 사용예를 다룬다.
신고