체크개발자's Blog

AES/CBC/PKCS5Padding 본문

프로그래밍/JAVA

AES/CBC/PKCS5Padding

체크개발자 2017. 8. 23. 10:29
package encryption;
import java.security.AlgorithmParameters;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
public class EncryptionDecryption {
    private static String salt;
    private static int iterations = 65536;
    private static int keySize = 256;
    private static byte[] ivBytes;
    private static SecretKey secretKey;
    private static char[] Password = "123456".toCharArray();
    public static void main(String []args) throws Exception {
        salt = getSalt(); 
       char[] message = "PasswordToEncrypt".toCharArray();
        System.out.println("Message: " + String.valueOf(message));
        System.out.println("Encrypted: " + encrypt(message));
        System.out.println("Decrypted: " + decrypt(encrypt(message).toCharArray()));    }
    public static String encrypt(char[] plaintext) throws Exception {
        byte[] saltBytes = salt.getBytes();
        SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
        PBEKeySpec spec = new PBEKeySpec(Password, saltBytes, iterations, keySize);
        secretKey = skf.generateSecret(spec);
        SecretKeySpec secretSpec = new SecretKeySpec(secretKey.getEncoded(), "AES");
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, secretSpec);
        AlgorithmParameters params = cipher.getParameters();
        ivBytes = params.getParameterSpec(IvParameterSpec.class).getIV();
        byte[] encryptedTextBytes = cipher.doFinal(String.valueOf(plaintext).getBytes("UTF-8"));
        return DatatypeConverter.printBase64Binary(encryptedTextBytes);    
       }
    public static String decrypt(char[] encryptedText) throws Exception { 
       System.out.println(encryptedText);
        byte[] encryptedTextBytes = DatatypeConverter.parseBase64Binary(new String(encryptedText));
        SecretKeySpec secretSpec = new SecretKeySpec(secretKey.getEncoded(), "AES");
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, secretSpec, new IvParameterSpec(ivBytes));
        byte[] decryptedTextBytes = null;
        try {
            decryptedTextBytes = cipher.doFinal(encryptedTextBytes);        }
   catch (IllegalBlockSizeException e) {
            e.printStackTrace();        }  
   catch (BadPaddingException e) {
            e.printStackTrace();        }
        return new String(decryptedTextBytes);    }
   public static String getSalt() throws Exception {
        SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
        byte[] salt = new byte[20];
        sr.nextBytes(salt);
        return new String(salt);    }

} 



암호화에 쓰인 암호 설명
AES-256
인코딩: Base64
Key 크기: 256bit
반복: 65536
Padding: AES/CBC/PKCS5Padding
비밀키 방식

아직 암호화에 대해 잘 몰라서 좀 더 기초지식을 쌓고 싶군요.. 이 코드는 비밀키 방식의 암호화를 위해 만든 것이고
사용된 암호들은 미 산업용으로 인정 받은 것들 입니다. 보안 이슈로 256bit 크기로 하였습니다.
아실만한 분들은 아시다 시피 SHA-1은 버리는 걸 미 정부가 적극 권장하고 있기에.. 저도 그리 하는 겁니다.

언젠가 SHA-2도... 버려지겠지만.

Illegal Key Size 문제는 JCE를 다운로드 하시면 됩니다.
이 자료는 최소한을 다운로드와 기본 API만을 사용한 코딩을 찾으시는 분들을 위해서 만든 것이기도 합니다.
외부 라이브러리 의존을 낮추어 안전성이 검증된 것만 쓰자는 취지. 또, 외부 라이브러리를 적게 사용함으로써 누구나 이해하기
쉽게 따라하고 제작할 수 있게 하는데 중점을 두었습니다. 본 소스코드는 인터넷에서 복사하고 일부 수정한 것 입니다.

stackoverflow가 출처.


Comments