패스워드 기반 암호화(PBE : Password-Based Encryption)

 

1  설명

   가) 패스워드를 키로 사용하는 방법

   나) 키 스페이스가 TripleDES나 Blowfish보다 훨씬 작아 안전하지 못함

   다) 사전공격에 취약함

   라) 해쉬와 일반적인 대칭 암호화를 사용함

   마) 미리 패스워드 해쉬 목록을 만들어 놓고 복호화 할 수 있음

   바) salting와 iteration counts를 도입하여 보안성 강화

 

2  방법

   가) 패스워를 MD5로 해쉬를 구한 다음 이 값을 암호화 키 값으로 사용한다. 

 

3  Salt

   가) 패스워드를 해쉬하기 전에 랜덤값을 추가하여 키 스페이스를 늘린다.

   나) salt는 암호문과 함께 저장된다.

   다) 복호화할 때는 암호화된 데이터로부터 salt를 분리해야 한다.

   라) salt는 매번 다르게 생성되며 동일한 문장에 대해서도 다른 값이 생성된다.

 

4  Iteration count

   가) 해쉬의 횟수를 의미함

   나) Iteration count가 1000이면 1000번을 해쉬한다는 의미

 

5  암호화/복호화 방법

   가) 패스워드와 salt를 생성하여 보통문서를 암호화하고 생성된salt를 암호문서 앞에 붙인다.

 

   나) 암호화된 데이타를 salt와 암호문서로 나누어 패스워드와 salt로 암호 문서를 복호화 한다.

 

 

6  주요 클래스 사용법

   가) PBEKeySpec : SecretKeyFactory의 인스턴스를 이용해서 패스워드기반 키를 생성한다.

 char[] password = “iloveyou”.toCharArry();

PBEKeySpec keySpec = new PBEKeySpec(password)

 

   나) SecretKeyFactory : PBEKeySpec을 실제 키로 사용하기 위해 generateSecret()를 실행시켜 줘야 한다.

 SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(“PBEWithShAAndTwoFish-CBC”);

SecretKey theKey = keyFactory.generateSecret(keySpec);

 

   다) PBEParameterSpec : salt와 interation count를 위한 레퍼런스

 PBEParameterSpec paramSpec = new PBEParameterSpec(salt, iterations);

Cipher cipher = Cipher.getInstance(“PBEWithShAAndTwoFish-CBC”);

Cipher.init(Cipher.ENCRYPT_MODE, theKey, paramSpec);

 

7  PBE 알고리즘

   가) PBEWithMD5AndDES 

   나) PBEWithSHAAndBlowfish

   다) PBEWithSHAAnd128BitRC4

   라) PBEWithSHAAndDEA-CBC

   마) PBEWithSHAAnd3-KeyTripleDES-CBC

 

8  PBE 예제

 

 import java.util.Random;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;

import com.Ostermiller.util.Base64;

public class PBE {

 private static int ITERATIONS = 1000;
 
 public static void main(String[] args) {
  char[] password = "iloveyou".toCharArray();
  String text = "i love you! but you don't. i sad b.b";
  String output = null;
  
  System.out.println("평문 : " + text);
  try {
   output = encrypt(password, text);
   System.out.println("암호문 : " + output);
   System.out.println("복호문 : " + decrypt(password, output));
  } catch (Exception e) {
   e.printStackTrace();
  }
 }
 
 private static String encrypt(char[] password, String plaintext) throws Exception {
  // 1. salt를 8byte 랜덤 생성
  byte[] salt = new byte[8];
  Random random = new Random();
  random.nextBytes(salt);
  
  // 2. 패스워드를 이용하여 PBEKeySpec 생성
  PBEKeySpec keySpec = new PBEKeySpec(password);
  SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithSHAAndTwoFish-CBC");
  
  // 3. 비밀키 생성
  SecretKey key = keyFactory.generateSecret(keySpec);
  
  // 4. salt, iteration count를 위한 PBEParameterSpec 생성
  PBEParameterSpec paramSpec = new PBEParameterSpec(salt, ITERATIONS);
  
  // 5. Cipher 생성 및 초기화
  Cipher cipher = Cipher.getInstance("PBEWithSHAAndTwoFish-CBC");
  cipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
  
  // 6. 암호문 생성
  byte[] ciphertext = cipher.doFinal(plaintext.getBytes());
  
  // 7. salt와 암호문을 Base64 인코딩 후 결합하여 최종 결과물 생성
  String saltString = Base64.encodeToString(salt);
  String ciphertextString = Base64.encodeToString(ciphertext);
  
  return saltString+ciphertextString;
  
 }
 
 private static String decrypt(char[] password, String text) throws Exception {
  
  // 1. 8byte를 Base64인코딩하면 12byte가 생성된다.
  String salt = text.substring(0, 12);
  String ciphertext = text.substring(12, text.length());
  
  // 2. salt와 암호문을 Base64 디코딩하여 원래 상태로 되돌린다.
  byte[] saltArry = Base64.decodeToBytes(salt);
  byte[] ciphertextArry = Base64.decodeToBytes(ciphertext);
  
  // 3. 패스워드를 이용하여 PBEKeySpec 생성
  PBEKeySpec keySpec = new PBEKeySpec(password);
  SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithSHAAndTwoFish-CBC");
  
  // 4. 비밀 키 생성
  SecretKey key = keyFactory.generateSecret(keySpec);
  
  // 5. salt, iteration count를 위한 PBEParameterSpec 생성
  PBEParameterSpec paramSpec = new PBEParameterSpec(saltArry, ITERATIONS);
  
  // 6. Cipher 생성 및 초기화
  Cipher cipher = Cipher.getInstance("PBEWithSHAAndTwoFish-CBC");
  cipher.init(Cipher.DECRYPT_MODE, key, paramSpec);
  
  // 7. 평문생성
  byte[] plaintextArry = cipher.doFinal(ciphertextArry);
  
  return new String(plaintextArry);
 }

}

 

 

'UP! > Crypto' 카테고리의 다른 글

Session key  (0) 2015.11.05
대칭키 암호화  (0) 2015.11.05
JCA, JCE  (0) 2015.11.05
인증, 전자서명  (0) 2015.11.05
대칭 비대칭 암호화  (0) 2015.11.05
Posted by 으랏차
,

JCA, JCE

UP!/Crypto 2015. 11. 5. 10:52

JCA & JCE

     설명

가)    JCA Runtime enviroment의 일부

나)  JCE JDK에 들어 있지 않은 JCA의 확장팩

나)    JDK JCA에 정의된 특정한 암호 함수만 사용 가능

 

     JCA

가)    전자 서명과 메시지 다이제스트 같은 기능에 대한 일반적인 API 제공

 

나)    주요 클래스들

     MessageDigest

     Signature

     KeyPaireGenerator

     KeyFactory

     CertificateFactory

     KeyStore

     AlgorithmParameters

     AlgorithmParameterGenerator

     SecureRandom

 

다)    암호 서비스 제공자 Sun Provider(Java 2 기준, sun.security.provider.Sun)

     MD5 메시지 다이제스트

     SHA-1 메시지 다이제스트

     DSA 전자 서명 사인과 검증

     DSA 키 쌍 생성

     DSA 키 변환

     X.509 인증서 생성

     Proprietary keystore 구현

     DSA 알고리즘 매개변수

     DSA 알고리즘 매개변수 생성

 

라)    암호 서비스 제공자 RSAJAC provider(com.sun.rsajca.Provider)

     RSA 키 쌍 생성

     RSA 키 변환

     SHA-1 또는 MD5 메시지 다이제스트를 이용한 RSA 서명

 

마)    JCA 접근

 MessageDigest myMessageDigest = MessageDigest.getInstance(“MD5”);

myMessageDigest.update(myData);

byte[] signatureBytes = myMessageDigest.digest();

 

 

     JCE(javax.crypto)

가)    주요 클래스와 인터페이스

     Cipher

     KeyAgreement

     KeyGenerator

     Mac

     SecretKey

     SecretKeyFactory

 

나)    JCE 접근 

KeyGenerator keyGenerator = KeyGenerator.getInstance(“Blowfish”);

Key key = keyGenerator.generatorKey();

Cipher cipher = Cipher.getInstance(“Blowfish/ECB/PKCS5Padding”);

cipher.init(Cipher.ENCRYPT_MODE, key);

byte[] cipherText = cipher.doFinal(myData);

  

다)    JCE 설치

이름

BouncyCastle

URL

http://www.bouncycastle.org

라이선스

오픈소스

참고문서

http://www.bouncycastle.org/docs/docs1.6/index.html

 

 

보통 썬의 JCE를 사용하기를 원하지만 일단 Sun JCE가 설치되고 나면 다른 것을 사용하지 못한다. Sun JCE DES, TripleDEs, Blowfish, Difie-Hellman외에는 사용할 수가 없다. 따라서 Bouncy Castle를 추천한다.

 

라)    Bouncy Castle 설치 (http://id0min.tistory.com/125 참조함)

     http://www.bouncycastle.org/latest_releases.html에서 자신의 JDK 버전에 해당되는 최신 버전을 다운로드 받는다. 다운받은 파일을 JDK JRE가 설치된 폴더에서 jre/lib/ext에 저장한다.

     양쪽 폴더에서 jre/lib/security 폴더에 있는 java.security 파일을 다음과 같이 수정한다. 숫자 10 provider 순서에 따라 수정한다.

security.provider.10=org.bouncycastle.jce.provider.BouncyCastleProvider

     unrestricted policy 파일들을 다운로드 받아  양쪽 폴더에서 jre/lib/security 폴더에 local_policy.jar US_export_policy.jar 파일을 교체한다. 아래 URL에서 파일을 다운로드 받아서 풀어보면 위의 2개 파일 있다. 덮어 씌우면 된다.

     설치한 후에 동작하는지 검증한다.

 

       마)    테스트 소스

 public static void main(String[] args) {

String providerName = "BC";

KeyGenerator keyGenerator = null;

if(Security.getProvider(providerName) == null)

System.out.println(providerName + " provider not installed");

else

       System.out.println(providerName + " is installed");

// Blowfish 블록 암호화 방식

System.out.println("Attepting to get a Blowfish key...");

try {

keyGenerator = KeyGenerator.getInstance("Blowfish");

} catch (NoSuchAlgorithmException e) {

}

keyGenerator.init(128);

SecretKey key = keyGenerator.generateKey();

System.out.println("OK");

//암호화 한다

            

System.out.println("Attempting to get a Cipher and encrypt...");

Cipher cipher = null;

byte[] ciphertext = null;

try {

       cipher = Cipher.getInstance("Blowfish/ECB/PKCS5Padding");

} catch (NoSuchAlgorithmException e) {}

catch (NoSuchPaddingException e) {}

try {

       cipher.init(Cipher.ENCRYPT_MODE, key);

} catch (InvalidKeyException e) {}

try {

       ciphertext = cipher.doFinal("This is a test".getBytes("UTF8"));

} catch (IllegalBlockSizeException e) {}

catch (BadPaddingException e) {}

catch (UnsupportedEncodingException e) {}

System.out.println("OK");

System.out.println("Test completed successfully : " + ciphertext);

}

 

'UP! > Crypto' 카테고리의 다른 글

대칭키 암호화  (0) 2015.11.05
패스워드 기반 암호화  (0) 2015.11.05
인증, 전자서명  (0) 2015.11.05
대칭 비대칭 암호화  (0) 2015.11.05
블록 Padding  (0) 2015.11.05
Posted by 으랏차
,

인증, 전자서명

UP!/Crypto 2015. 11. 5. 10:51

인증(Authentication)

 

메시지 다이제스트(Message Digest)

     기능

가)    해쉬 라고도 함

나)    메시지가 부당하게 변경되지 않았다는 것을 증명

다)    한 방향 함수

라)    패스워드 인증에도 사용됨

     방법

가)    파일과 다이제스트를 받음

나)    파일에 대해 메시지 다이제스트를 적용한 결과를 다이제스트와 비교함

     종류

가)    MD5

     RSA에서 개발

     128bit

나)    SHA, SHA-1

     Secure Hash Algorithm

     일반적으로 SHA SHA-1을 말함

     160bit

 

메시지 인증 코드(MAC:Message Authentication codes)

     기능

가)    키와 함께 생성된 메시지 다이제스트

나)    ·수신 측 모두 비밀 키가 있어야 함

다)    동일한 메시지와 키는 언제나 동일한 메시지 인증 코드를 가짐

     사용

가)    보안 연결이 이미 설치된 곳에 보통 사용됨

나)    SSL은 받은 데이터를 검사하기 위해 세션을 시작할 때 교환한 비밀 키를 가지고 MAC을 사용함.

     종류

가)    HMAC(Hasing Message Authentication Codes)

     MD5 SHA-1과 같은 해시 알고리즘을 사용함

나)    HmacMD5

     키와 함께 MD5 다이제트스 알고리즘 사용

다)    HmacSHA1

     SHA-1 알고리즘 사용

 

전자서명

     기능

가)    데이터 원형에 대한 보증

나)    데이터가 변조 방지 보증

     방법

가)    서명해야 할 메시지에 대해 메시지 다이제스트 생성

나)    생성된 메시지 다이제스트를 송신자의 개인키로 암호화

다)    수신자는 전달받은 메시지에 대해 메시지 다이제스트 생성

라)    전자서명을 송신자의 공개키로 복호화한 후 다)에서 생성한 다이제스트와 비교

 

전자 인증서(Digital Certificates)

     문제점

가)    인증에 공개 키를 사용하는 것이 문제

나)    공개 키가 어떤 사람의 것인지 알 수가 없음

다)    전자서명은 수진자의 공개 키를 이용해서 서명해야 함

     기능

가)    승인된 기관의 개인 키로 서명된 개인의 공개 키와 신원을 확인하는 정보가 포함

나)    승인된 기관의 공개 키로 검증

다)    SSL 인증서는 URL을 포함하고 있어 접속 시 URL이 틀릴 경우 에러 메시지 발생

 

'UP! > Crypto' 카테고리의 다른 글

패스워드 기반 암호화  (0) 2015.11.05
JCA, JCE  (0) 2015.11.05
대칭 비대칭 암호화  (0) 2015.11.05
블록 Padding  (0) 2015.11.05
base64 인코딩, 디코딩의 원리  (0) 2015.11.05
Posted by 으랏차
,