'개발관련/암호화'에 해당되는 글 10건

  1. 2009.12.31 :: 대칭키 암호화 이야기5
  2. 2009.12.31 :: 대칭키 암호화 이야기4
  3. 2009.12.31 :: 대칭키 암호화 이야기3
  4. 2009.12.31 :: 대칭키 암호화 이야기2
  5. 2009.12.31 :: 대칭키 암호화 이야기1
  6. 2009.12.31 :: 해쉬 이야기 4
  7. 2009.12.31 :: 해쉬 이야기 3
  8. 2009.12.31 :: 해쉬 이야기2
  9. 2009.12.31 :: 해쉬 이야기 1
  10. 2009.12.31 :: Base64 활용
개발관련/암호화 2009. 12. 31. 15:45

앞의 글에서 Padding에 대한 내용을 이야기 하면서 Padding을 하지 않을 경우
개발자가 임의로 SEED 알고리즘을 기준으로 할 때 128비트(16바이트)블럭으로
암호화할 데이터를 가공해 주어야 한다고 한 바 있다.

 

암호화 서비스에 대한 활발한 구현이 진행되기 이전에 구현된 어플리케이션을 보면
Padding을 미쳐 구현하지 않아서(초기에 제공된 SEED 소스만 하더라도 Padding은
제공소스에서 제외)개발자가 임의적으로 16바이트 블럭을 만들어서 Padding을
하지 않는 방법으로 암호화를 하곤 하였다.

 

예를들면 패스워드 "abcd1234"를 암호화를 할때 "abcd1234        "처럼 공백으로
16바이트를 만들어서 암호화하곤 했는데 재밌는 사실은 16바이트를 암호화할 때
Padding을 하면 32바이트가 되지만 Padding을 하지 않으면 16바이트가 된다.

 

 

//Padding을 할 경우에는 다음과 같이 선언을 하였을 것이다.

스크랩:http://blog.paran.com/blog/detail/postBoard.kth?blogDataId=35385570&pmcId=javacipher&totalCount=13&preViewPage=0&ajaxPage=1&preFBlogId=35385570&preLBlogId=27788506&pageStyle=null&myCateId=0&yearMonth=null&rDay=null&style=Board&p_eye=

 

...(중략)...
PaddedBufferedBlockCipher blockCipher = new PaddedBufferedBlockCipher(
    new SEEDEngine());
...(중략)...


//Padding을 하지 않을 경우는 다음과 같다.

...(중략)...
BufferedBlockCipher blockCipher = new BufferedBlockCipher(
    new SEEDEngine());
...(중략)...


Paddig을 하지 않았을 때 만약에 암호화할 데이터가 다음과 같이 16바이트 블럭이 아닐 경우

byte[] data = { (byte) 0x00, (byte) 0x11, (byte) 0x22, (byte) 0x33,
  (byte) 0x44, (byte) 0x55, (byte) 0x66, (byte) 0x77,
  (byte) 0x88, (byte) 0x99, (byte) 0xaa, (byte) 0xbb,
  (byte) 0xcc, (byte) 0xdd, (byte) 0xee, (byte) 0xff, (byte) 0x33 };
  
  
DataLengthException이 발생할 것이다.

posted by 제스트
:
개발관련/암호화 2009. 12. 31. 15:44

대칭키 암호화 알고리즘은 비트나 바이트, 워드 단위로 암호화하는 스트림(stream) 암호와 일정한 크기의 블럭을 단위로

암호화하는 블럭 암호 알고리즘으로 구분된다.

 

앞에서 예제로 보인 DES, SEED, AES와 같은 알고리즘은 블럭 단위로 암호화하는 알고리즘이다.

몇블럭씩 암호화할 것인지에 대해서는 알고리즘별로 차이를 보이는데 SEED와 같은 알고리즙은 128비트(16바이트) 단위로 암호화를 하게 된다.

 

다행히 암호화를 할 데이터가 16바이트 단위로 나눠진다면 몰라도 데이터는 항상 15바이트나 17바이트처럼 모자라거나 넘치기 마련이다. 블럭 암호화 알고리즘에서는 이렇게 모자라거나 넘치는 문제를 해결하기 위하여 16바이트 단위로 만들기 위해 임의의 숫자를 암호화할 데이터에 추가하게 되는데 이를 Padding이라고 한다. 따라서 15바이트 데이터는 1바이트를 Padding하여 16바이트 블럭으로 만들것이며, 17바이트처럼 넘치는 데이터는 15바이트를 Padding하여 32바이트를 만들게 된다.

 

앞의 예제에서 PaddedBufferedBlockCipher 라고 선언한 부분은 바로 블럭 암호화 알고리즘이면서 Padding까지 하겠다는 의미이다.
Padding을 하지 않을 경우라면 16바이트 단위로 암호화할 데이터를 인위적으로 가공을 개발을 해주어야 한다.

 

블럭암호화 알고리즘은 Padding이라는 절차의 문제로 평문보다 최대 16바이트 길이가 늘어날 수 있다는 것을 감안해야 한다.

 

스트림사이퍼의 경우는 블럭단위가 아니라 비트 단위 XOR 연산을 수행하기 때문에 별도의 Padding 절차가 필요없으며 따라서 평문이나 이를 암호화한 암호문이나 데이터의 길이가 동일하고 키 길이를 마음대로 지정할 수 있다는 장점이 있다.
아래는 대표적인 스트림 암호화 알고리즘인 RC4에 대한 예제이다.


import org.bouncycastle.crypto.StreamCipher;
import org.bouncycastle.crypto.engines.RC4Engine;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.util.encoders.Base64;


...(중략)...

    //스트림 암호화에서 키길이는 반드시 16바이트를 고집할 필요는 없지만...
   byte[] key = {(byte)0x01,(byte)0x02,(byte)0x03,(byte)0x04,(byte)0x05,(byte)0x06,(byte)0x07,(byte)0x08,
               (byte)0x09,(byte)0x10,(byte)0x11,(byte)0x12,(byte)0x13,(byte)0x14,(byte)0x15,(byte)0x16}; 
 
    
  byte[] data = "12345대한민국asdddddddddddddddddddddddddd".getBytes();

  //스트림 암호화 시작
  StreamCipher cipher = new RC4Engine();
  cipher.init(true, new KeyParameter(key));
 
  byte[] out = new byte[data.length];

   try {
  cipher.processBytes(data, 0, data.length, out, 0);
   } catch (Exception e) {
    throw new Exception("암호화 오류가 발생하였습니다.올바른 키로 암호화하였는지 확인하십시오");
  } 
     
   System.out.println("암호화된 데이터의 길이 ="+out.length);
   System.out.println(new String(Base64.encode(out)));

  //스트림 복호화 시작
  cipher.init(false, new KeyParameter(key));
  byte[] out2 = new byte[out.length];

   try {
 cipher.processBytes(out, 0, out.length, out2, 0);
   } catch (Exception e) {

     throw new Exception("복호화 오류가 발생하였습니다.올바른 키로 복호화하였는지 확인하십시오");
  } 
  
   System.out.println("복호화된 데이터의 길이 ="+out2.length);
   System.out.println(new String(out2));

 

...(중략)...

스크랩:http://blog.paran.com/blog/detail/postBoard.kth?blogDataId=35205253&pmcId=javacipher&totalCount=13&preViewPage=0&ajaxPage=1&preFBlogId=35385570&preLBlogId=27788506&pageStyle=null&myCateId=0&yearMonth=null&rDay=null&style=Board&p_eye=

posted by 제스트
:
개발관련/암호화 2009. 12. 31. 15:42

대칭키 암호화 알고리즘에서 암복호화에 사용되는 KEY가 무엇을 의미하고 각 알고리즘별로

키길이가 다른 것도 확인한 바 있다.

 

지난번 소스에서 KEY를 예를들어 byte[] KEY= {(byte)0x12 ...}이런식으로 사용하였는데 또다른

방법으로 키를 만들 수 있는 방법은 없을까?

즉 개발자나 사용자가 이해하고 기억하기 쉬운 예를들면 '123456' 같은 숫자나 문자를 KEY로

암호화에 사용할 수는 없는걸까?

 

이렇게 사용자나 개발자가 쉽게 사용할 수 있는 문숫자로 KEY를 만들어 사용하는 방법을

패스워드기반암호화(PBE: Password based Encrytion)라고 한다.

 

내부적인 프로세스는 KEY로 사용될 문자를 받아서 해쉬알고리즘을 통해서 필요한 KEY를 얻게 되는데 

특정 문자가 항상 동일한 결과가 나오는 것을 방지하기 위하여 개발자가 이과정에서 인위적으로

특정값을 입력하여 데이터를 혼탁(scrambling)하게 만드는 과정이 추가된다. 이 인위적인 특정값을

salt로 하고 몇번 혼탁하게 만들지도 개발자가 결정하게 된다.

 

자 그러면 이게부터 "abcd1234"라는 특정 문자가 어떻게 대칭키 알고리즘의 KEY로 사용되는지

소스에서 확인해 보자.

 

import org.bouncycastle.crypto.PBEParametersGenerator;
import org.bouncycastle.crypto.digests.SHA1Digest;

import org.bouncycastle.crypto.generators.PKCS12ParametersGenerator;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;

 

//KEY로 만들 문숫자열

String password = "abcd1234"

 

//8바이트 salt

byte[] SALT = {(byte)0xa1,(byte)0xa2,(byte)0xa3,(byte)0xa4,(byte)0xa5,(byte)0xa6,(byte)0xa7,(byte)0xa8}; 

 

//회전수

int COUNT=2000;

 

//PBE Generator와 해쉬알고리즘, 그리고 PKCS#12에서 정의한 프로세스로 키를 만들겠다고 선언

PBEParametersGenerator peg = new PKCS12ParametersGenerator(new SHA1Digest());

byte[] pass = PBEParametersGenerator.PKCS12PasswordToBytes(password.toCharArray());

 

//혼탁하게 만들고

peg.init(pass, SALT, COUNT);
//128비트 즉 16바이트 키를 만든다.

ParametersWithIV params =  (ParametersWithIV) peg.generateDerivedParameters(128, 128);
KeyParameter kParms = (KeyParameter) params.getParameters();
byte[] KEY =kParms.getKey();

 

이렇게 나온 KEY를 대칭키암호화에 사용한다.

 

BufferedBlockCipher blockcipher = new PaddedBufferedBlockCipher(new SEEDEngine());
blockcipher.init(true, new KeyParameter(KEY));

...

 

나머지 소스는 이전 편을 참조하라.

스크랩:http://blog.paran.com/blog/detail/postBoard.kth?blogDataId=31553399&pmcId=javacipher&totalCount=13&preViewPage=0&ajaxPage=1&preFBlogId=35385570&preLBlogId=27788506&pageStyle=null&myCateId=0&yearMonth=null&rDay=null&style=Board&p_eye=

posted by 제스트
:
개발관련/암호화 2009. 12. 31. 15:42

지금부터는 대칭키 암호화에 관련하여 지난번에 소개한 소스에 대한 설명을 하도록 하겠다.
SEED 알고리즘으로 암호화한 샘플에서 맨 먼저 주목해야 할 부분은 키(KEY)부분이다.

 

byte[] key = {(byte)0x01,(byte)0x02,(byte)0x03,(byte)0x04,(byte)0x05,(byte)0x06,(byte)0x07,(byte)0x08,
             (byte)0x09,(byte)0x10,(byte)0x11,(byte)0x12,(byte)0x13,(byte)0x14,(byte)0x15,(byte)0x16}; 
      
대칭키 암호화 알고리즘은 암호화에 사용한 키와 복호화에도 동일하게 사용하게 되는데 중요한 것은
키의 길이다.

 

SEED 알고리즘은 키의 길이를 128비트(16바이트)를 사용한다. 키의 길이가 128비트라는 이야기는 암호화된
키를 찾아내기 위해서는 2의 128승의 키 중에서 하나를 찾는 작업인데 불가능하지는 않지만 오랜 노력과
시간이 필요하다는 것을 의미한다.

 

과거에 만들어진 DES 알고리즘의 경우 키의 길이가 64비트(8바이트)였다. 전산 환경의 발달은 2의 64승의
연산은 굳이 슈퍼 컴퓨터를 통하지 않더라고 키를 알아내는데 그다지 긴 기간이 필요하지 않기 때문에 현대에
만들어진 대칭키 알고리즘은 128비트 256비트 등 긴 키 길이를 지원한다.

 

키길이가 길면 길수록 암호화의 속도는 떨어지기 때문에 128비트의 키길이가 현재 수준에서 가장 적정하다고
받아들여지고 있다.

 

중요 알고리즘별 키길이는 다음과 같다.

- SEED: 128비트
- DES: 64비트
- Blowfish:64비트
- TripleDES(DESede): 192비트
- AES: 128, 192. 256 비트

 

국내간에는 SEED가 보편적으로 사용되지만 외국기관간 암호화 통신에는 아직도 DES와 TripleDES을 많이 사용하기
때문에 우선 암호화할 알고리즘이 결정되면 거기에 맞는 키길이로 키를 만들어 주어야 한다.

즉 SEED 알고리즘에서는 128비트 이지만 만약 다른 알고리즘으로 암호화한다고 했을 때
위에 정의한 키의 길이는 8바이트로 만들어 주고 다음과 같이 알고리즘을 호출해 주어야 한다.


//DES시 8바이트 키설정 및 알고리즘 선언
byte[] key = {(byte)0x01,..};
...
PaddedBufferedBlockCipher blockcipher = new PaddedBufferedBlockCipher(new DESEngine());


//TripleDES시 24바이트 키설정 및 알고리즘 선언
byte[] key = {(byte)0x01,..};
...
PaddedBufferedBlockCipher blockcipher = new PaddedBufferedBlockCipher(new DESedeEngine());

//AES시 16 또는 24 또는 32 바이트 키설정 및 알고리즘 선언
byte[] key = {(byte)0x01,..};
...
PaddedBufferedBlockCipher blockcipher = new PaddedBufferedBlockCipher(new AESEngine());

 

그 이후에 나머지 소스는 동일하다.

스크랩:http://blog.paran.com/blog/detail/postBoard.kth?blogDataId=28779104&pmcId=javacipher&totalCount=13&preViewPage=0&ajaxPage=1&preFBlogId=35385570&preLBlogId=27788506&pageStyle=null&myCateId=0&yearMonth=null&rDay=null&style=Board&p_eye=

posted by 제스트
:
개발관련/암호화 2009. 12. 31. 15:41

그동안 base64, 해쉬 알고리즘 및 활용에 대해서 알아 보았다.

지금부터 본격적으로 암호화에 대한 이야기를 하고자 한다.

 

암호화는 크게

1) KEY 없는 암호화:  단 이 경우 암호화만 가능하고 복호화는 불가능하다.

2) 하나의 KEY로 암호화 : 하나의 KEY로 암호화된 데이터는 바로 그 키로 복호화된다.

3) 두개의 KEY로 암호화 : KEY가 두개다. 즉 KEY1으로 암호화된 데이터는 KEY2로만 복호화된다.

 

대칭키 암호화는 2)에 해당된다. 즉 하나의 KEY로만 암복호화가 가능하다.

대칭키 암호화 알고리즘은 보안의 세계에서 가장 보편적으로 사용하는 기법이다.

대칭키 암호화 알고리즘으로 잘 알려진 것들은 DES(Triple DES), AES, Blowfish, RC4 등이 있고

국내에서는 SEED를 민간기관 표준 알고리즘으로 사용하고 있다. 특수한 경우를 제외하고는 각 암호화 알고리즘은

공개되어 있으며 누구나 표준에 따라 구현할 수 있다.

 

그 동안 자바로 암호화를 구현할 경우 국내 표준 알고리즘이 제외되었기 때문에 구현에 어려움이 있었으나

최근에 SEED가 국제표준화되면서 OPEN 소스에서도 이를 지원하고 있다.

 

일단 기본적인 암호화 지식을 무시고하고 아래의 소스부터 보자

 

import org.bouncycastle.crypto.engines.SEEDEngine;
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.util.encoders.Base64;

 

(중략)

//암호화에 사용될 키

 byte[] key = {(byte)0x01,(byte)0x02,(byte)0x03,(byte)0x04,(byte)0x05,(byte)0x06,(byte)0x07,(byte)0x08,
                         (byte)0x09,(byte)0x10,(byte)0x11,(byte)0x12,(byte)0x13,(byte)0x14,(byte)0x15,(byte)0x16}; 
   

  //암호화할 데이터 
   byte[] data = "12345대한민국".getBytes();

  //SEED로 암호화할 것을 선언  

  PaddedBufferedBlockCipher blockcipher = new PaddedBufferedBlockCipher(new SEEDEngine());
  

  //초기화 및 키 파라메터 생성 true는 암호화한다는 의미 false인 경우 복호화

  blockcipher.init(true, new KeyParameter(key));

//암호화 프로세스 추가 
  int len =0;
  byte[] tmp = new byte[blockcipher.getOutputSize(data.length)];
  len =blockcipher.processBytes(data, 0, data.length, tmp, 0);
 
    try {
      len+=blockcipher.doFinal(tmp, len);
     } catch (Exception e) {
    
     throw new Exception("암호화 오류가 발생하였습니다.올바른 키로 암호화하였는지 확인하십시오");
    } 
  

   //암호화된 결과를 담을 버퍼
    byte[]  out = new byte[len];
    System.arraycopy(tmp, 0, out, 0, len);
  
    System.out.println("암호화된 데이터의 길이 ="+out.length);
    System.out.println(new String(Base64.encode(out)));
 }

 

 

   //복호화 프로세스 시작

   blockcipher.init(false, new KeyParameter(key));
 
    int len2 =0;
    byte[] tmp2 = new byte[blockcipher.getOutputSize(out.length)];
    len =blockcipher.processBytes(out, 0, out.length, tmp2, 0);
 
     try {
       len2+=blockcipher.doFinal(tmp2, len2);
      } catch (Exception e) {
    
       throw new Exception("복호화 오류가 발생하였습니다.올바른 키로 복호화하였는지 확인하십시오");
     } 
    //복호화된 데이터를 담을 버퍼
     byte[]  out2= new byte[len2];
     System.arraycopy(tmp2, 0, out2, 0, len2);
  
     System.out.println("복호화된 데이터의 길이 ="+out2.length);
     System.out.println(new String(out2));

 

 

 

이상의 소스를 잘 정리하면 SEED 알고리즘을 이용한 암복호화 함수가 완성될 것이다.

이에 대한 부가 설명은 다음편에 계속하겠다. 

스크랩:http://blog.paran.com/blog/detail/postBoard.kth?blogDataId=28578038&pmcId=javacipher&totalCount=13&preViewPage=0&ajaxPage=1&preFBlogId=35385570&preLBlogId=27788506&pageStyle=null&myCateId=0&yearMonth=null&rDay=null&style=Board&p_eye=

posted by 제스트
:
개발관련/암호화 2009. 12. 31. 15:39

해쉬와 같은 단방향 암호화 알고리즘은 다양한 보안영역에 활용된다.
그 활용의 하나로 해쉬 알고리즘을  이용한 패스워드 암호화 방법에 대해서
설명하고자 한다.
최근 개인정보보호에 대한 이슈가 더욱 즁요하게 제기되면서 사용자패스워드와 같은
정보를 암호화하여 정보상에 유통하고 이를 안전하게 보관해야하는 것이 필수 조건이다.
개인의 패스워드를 입력받아 서버를 통하여 데이터베이스까지 안전하게 전송하기 위해서는
데이터 구간의 암호화가 필수이지만 해쉬 알고리즘을 잘 이용하면 구간 암호화를 굳이 사용하지
않고도 이러한 효과를 얻을 수 있다.

다음의 시나리오는 실제 구현한 프로세스이다.

 

<해쉬알고리즘을 이용한 패스워드 암호화 시나리오>

 

1. A라는 쇼핑몰 홈페이지에서 입력받은 패스워드를 해쉬한다

HTML>
<HEAD>
<script language=javascript src="sha1.js"></script>
<SCRIPT LANGUAGE="JavaScript">
<!--

function AS(s){
   //var s = form.A.value;
   alert(s);
   s =b64_sha1(s);
   alert(s);
}
</SCRIPT>
</HEAD>

<BODY>
<FORM Action="biz.xxx">
<INPUT TYPE="password" NAME="A">
<input type=button value="전송" onClick=AS(this.form.A.value)></P>
</FORM>
</BODY>
</HTML>

이 홈페이지소스에는 sha-1 알고리즘이 구현된 자바스크립트를 포함하였다.


2. 사용자가 A쇼핑몰에 회원으로 신규가입하였다면 해쉬된 패스워드를 DB에 저장하고
   정당한 회원인지 확인하는 로직을 다음과 같이 구현한다.

 

//클라이언트에서 전송된 해쉬된 패스워드
String passwordFromClient = "2yXy/BTNLSseevMHJB9Uj7A8MSo=";

 

//DB에 저장된 패스워드
String passwordFromDB= "2yXy/BTNLSseevMHJB9Uj7A8MSo=";

 

//물론 String 값이 동일한지 비교해도 무방하지만 다음의 비교 로직으로 수행하는것이 보다 안전

byte[] bytePasswordFromClient =  Base64.decodepasswordFromClient);
byte[] bytePasswordFromDB =  Base64.decodepasswordFromDB);

boolean flag = true;

for(int i=0; i < bytePasswordFromClient.length; i++){

    if(bytePasswordFromClient.length!=bytePasswordFromDB.length){
 
        flag = false;
 break;
    }
  
     if(bytePasswordFromClient[i]!=bytePasswordFromDB[i]){

        flag = false;
 break;

     }
}

 

해쉬 알고리즘을 이용하여 패스워드를 암호화를 하게되면 사용자 이외의 누구도 실제 패스워드를
알 수 없다는 것이 보안상의 큰 장점이 된다.
단, 패스워드를 사용자만 알 수 있기 때문에 사용자가 패스워드를 잃어버렸을 경우 본인확인
과정을 거쳐 패스워드를 초기화(재등록)해주는 프로세스를 만들어 주는 친절이 필요하다.


스크랩:http://blog.paran.com/blog/detail/postBoard.kth?blogDataId=28216007&pmcId=javacipher&totalCount=13&preViewPage=0&ajaxPage=1&preFBlogId=35385570&preLBlogId=27788506&pageStyle=null&myCateId=0&yearMonth=null&rDay=null&style=Board&p_eye=

posted by 제스트
:
개발관련/암호화 2009. 12. 31. 15:35

해쉬의 기능이 메시지의 변조 유무룰 확인할 수 있다고 이야기한 바 있다.
문제는 어떤 경로된 원본 데이터와 알고리즘을 알게되면 해쉬값을 만들어 낼 수 있다는
단점이 있다. 그래서 특정 KEY를 해쉬를 과정에서 사용하여 원본을 안다고 하더라도
해쉬값을 유추할 수 없도록 하는 기법을 메시지 인증 코드(MAC, Message Authentication Code)라고 한다.
MAC은 해쉬 알고리즘을 이용할 수 도 있고 암호화 알고리즘을 이용하여 만들 수 있지만 원본 데이터의
무결성을 확인할 수 있는 메시지 축약값이 나온다는 점에서는 해쉬와 동일한다.
특별히 해쉬알고리즘을 이용한 MAC을 HMAC이라고 부른다. HMAC은 매우 자바에서 제공하는 API를 이용하여
매우 쉽게 만들 수 있다.

 

package myBlog;

import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.util.encoders.Base64;

...
//HMAC에 사용할 KEY 
String key = "ABCDEFG";

//해쉬할 데이터
 String data = "12345678901234567890123456789012345678901234567890";
   
//키를 세팅하고 MD5 해쉬알고리즘을 이용한 HMAC을 사용할 것임을 정한다.
SecretKeySpec spec = new SecretKeySpec(key.getBytes(), "hmacMd5");
Mac mac = Mac.getInstance("hmacMd5");
mac.init(spec);
  
byte[] res =mac.doFinal(data.getBytes());

System.out.println(res.length);
System.out.println(new String(Base64.encode(res)));

 

HMAC은 기본적으로 해쉬알고리즘을 사용하기 때문에 결과의 길이는 MD5의 결과값 즉 16바이트가 출력된다.

 

이를 OPENJCE API로 구현하면 다음과 같다.

 

import org.bouncycastle.crypto.digests.MD5Digest;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.params.KeyParameter;

 

...

 

 

HMac hmac = new HMac(new MD5Digest());
byte[] res2 =new byte[new MD5Digest().getDigestSize()];
hmac.init(new KeyParameter(key.getBytes()));
hmac.update(data.getBytes(), 0, data.getBytes().length);
 
hmac.doFinal(res2,0);
System.out.println(new String(Base64.encode(res2)));

스크랩:
http://blog.paran.com/blog/detail/postBoard.kth?blogDataId=27934278&pmcId=javacipher&totalCount=13&preViewPage=0&ajaxPage=1&preFBlogId=35385570&preLBlogId=27788506&pageStyle=null&myCateId=0&yearMonth=null&rDay=null&style=Board&p_eye=

posted by 제스트
:
개발관련/암호화 2009. 12. 31. 15:34

해쉬 알고리즘으로 가장 많이 사용하는 SHA-1 알고리즘을 중심으로 살펴보면 보면

 

먼저 JDK에서 제공하는 MessageDigest Class를 이용하면 아래와 같이 매우 간단하게 구현할 수 있다. 

 

import java.security.MessageDigest;

import org.bouncycastle.util.encoders.Base64;

...

 

String s1 = "ABCDEFG";
String s2 = "12345678901234567890123456789012345678901234567890";

 

MessageDigest digest = MessageDigest.getInstance("Sha1");
byte[] res1 = digest.digest(s1.getBytes());
byte[] res2 = digest.digest(s2.getBytes());
    
    
System.out.println("결과값크기= "+res1.length+" 결과값= "+new String(Base64.encode(res1));
System.out.println("결과값크기= "+res2.length+" 결과값= "+new String(Base64.encode(res2));

 

7바이트 s1과 50바이트 s2를 각각 해쉬 하였을 때 출력되는 값은 다르지만 그 길이는 SHA-1 알고리즘의 경우

항상 20바이트가 된다.

 

JDK에서 제공하는 해쉬 알고리즘은 SHA1과 MD5과 같은 제한된 알고리즘인데 반하여 OPENCJCE에서는

보다 다양하고 안전한 알고리즘을 제공한다. 이를 이용한 SHA-1 구현은 다음과 같다.

 

import org.bouncycastle.crypto.digests.GeneralDigest;
import org.bouncycastle.crypto.digests.SHA1Digest;
import org.bouncycastle.util.encoders.Base64;

 

...

 

GeneralDigest sha1digest = new SHA1Digest();

//다이제스트 결과로 얻어질 버퍼

byte[] res3 = new byte[sha1digest.getByteLength()];
   
sha1digest.update(s1.getBytes(), 0, s1.getBytes().length);
sha1digest.update(s2.getBytes(), 0, s2.getBytes().length);  
  
sha1digest.doFinal(re3,0);
System.out.println(new String(Base64.encode(res3)));

스크랩 :
http://blog.paran.com/blog/detail/postBoard.kth?blogDataId=27859061&pmcId=javacipher&totalCount=13&preViewPage=0&ajaxPage=1&preFBlogId=35385570&preLBlogId=27788506&pageStyle=null&myCateId=0&yearMonth=null&rDay=null&style=Board&p_eye=


posted by 제스트
:
개발관련/암호화 2009. 12. 31. 15:31

일반적인 암호화 알고리즘은 암호화된 데이터는 동일한 KEY로 복호화가 가능하도록 설계되어 있다.

해쉬(Hash)알고리즘은 암호화된 데이터를 복호화를 하지 못하게 하기 위하여 만들어졌다. 암복호화라는 양방향 아니라 암호화만 가능하기 때문에 단방향 암호화 알고리즘이라고 부르기도 한다.

해쉬 알고리즘은 용도는 주로 데이터의 무결성을 검증하는데 유용하게 사용되는데 데이터의 무결성이란 데이터가 정보 유통과정에서 위변조가 없었다는 것을 증명하는 것이다.

일상 생활에서 A B과 중요한 거래가 있을 경우 서명을 비록한 갖은 방법으로 그 계약서의 내용을 바꿀 수 없도록 하는데 해쉬의 특성은 데이터가 단 1byte가 바뀌더라고 그 값이 달리 나타나기 때문에 온라인상의 문서일 경우 이 문서가 바꾸지 않았다는 것을 증명하는데 그 문서 전체를 해쉬한 값을 AB가 서로 보관만 하고 있으면 계약서 사본을 별도로 카피아여 보관하지 않아도 된다.

또한 복호화할 필요가 없는 데이터의 암호화에 활용되기도 하는데 예를 들면 고객비밀번호와 같은 중요 정보는 그 고객만 알고 있으면 되고 설사 고객이 그 정보를 잊어버렸다고 하더라고 본인 확인 과정을 거쳐 다시 만들면 되기 때문에 복호화가 필요 없는 해쉬 알고리즘을 이용하여 안전하게 보관하여 활용하게 된다.

해쉬 알고리즘은 메시지 축약(Message Digest)이라고 불리기도 하는데 1바이트를 암호화하나 수백 수천 바이트를 암호화하는 항상 알고리즘이 지정한 크기로 출력된다. 일반적으로 많이 사용하는 SHA-1 알고리즘은 160비트(20바이트) 그리고 MD5128비트(16바이트)로 출력된다.


posted by 제스트
:
개발관련/암호화 2009. 12. 31. 15:29
openjce에서 제공하는 함수를 사용하여 구현

. 다음의 클래스를 import를 하고

import java.security.SecureRandom;
import org.bouncycastle.util.encoders.Base64;
import org.bouncycastle.util.encoders.Hex;

 

  

2. 랜덤한 20bytes를 생성하고

   byte[] randomBytes = new byte[20];
   SecureRandom random = new SecureRandom();
   random.nextBytes(randomBytes);

3. 랜덤한 바이러리를 System출력으로 볼 수 없기 때문에 바이러리를 hexa값으로 출력해보면 40bytes로 출력된다.

   String hexaed = new String(Hex.encode(randomBytes));
   System.out.println(hexaed+" hexaed length="+hexaed.length());
   (출력의예=>  2f8b2d2b99a687feec19ea20235f560d233aaaea hexaed length=40)

 

4. 랜덤한 바이러리를 Base64로 인코딩하여 출력해보면 28bytes로 출력된다.

   String base64ed = new String( Base64.encode(randomBytes));
   System.out.println(base64ed+" base64 length="+base64ed.length());

  (출력의 예=> L4stK5mmh/7sGeogI19WDSM6quo= base64 length=28)

 

 

5. hexa나 base64로 표시된 데이터를 반대의 원본으로 바꾸려면 디코딩을 하면 된다.

   byte[] base64decoded = Base64.decode(base64ed.getBytes());
   byte [] hexadecoded = Hex.decode( hexaed.getBytes());

 

 

openjce에서 제공하는 함수를 이용하여 간단하게 바이러리 데이터의 hexa 및 base64 스트링 구현을 알아보았다.

스크랩 :http://blog.paran.com/blog/detail/postBoard.kth?blogDataId=27788506&pmcId=javacipher&totalCount=13&preViewPage=0&ajaxPage=1&preFBlogId=35385570&preLBlogId=27788506&pageStyle=null&myCateId=0&yearMonth=null&rDay=null&style=Board&p_eye=
posted by 제스트
: