CBC, PKCS5Padding 및 IV를 사용하여 Java AES 암호화를위한 아래 코드 스 니펫의 유효성을 검사하는 데 도움이 필요합니다.비밀번호 기반 암호화를 사용하는이 AES-128 CBC 예제 검토
코드를 테스트하여 암호화하고 해독 할 수있었습니다. 아래에 설명 된대로 몇 가지 쿼리가 있습니다.
- 어디에서 암호를 규칙으로 저장해야합니까?
- 소금과 IV 바이트를 ciphetext에 잘 추가/검색하는 방법이 있습니까?
- 기타 의견은 높이 평가되었습니다. 감사합니다.
public class Encryption {
private static int iterations = 65536;
private static int keySize = 128;
private static char[] password = "password".toCharArray();
private static String algorithm= "PBKDF2WithHmacSHA1";
private static final String SEPARATOR = "~";
public static void main(String []args) throws Exception {
String filePath = "test.xml";
String fileContent = new String(Files.readAllBytes(Paths.get(filePath)));
String encrMesg = encrypt(fileContent);
System.out.println("Encrypted: " + encrypt(encrMesg));
System.out.println("Decrypted: " + decrypt(encrMesg));
}
public static String encrypt(String plaintext) throws Exception {
byte[] saltBytes = getSalt().getBytes();
SecretKeyFactory skf = SecretKeyFactory.getInstance(algorithm);
PBEKeySpec spec = new PBEKeySpec(password, saltBytes, iterations, keySize);
SecretKey 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();
byte[] ivBytes = params.getParameterSpec(IvParameterSpec.class).getIV();
byte[] cipherText = cipher.doFinal(String.valueOf(plaintext).getBytes("UTF-8"));
return DatatypeConverter.printBase64Binary(ivBytes)+SEPARATOR+DatatypeConverter.printBase64Binary(saltBytes)
+SEPARATOR+DatatypeConverter.printBase64Binary(cipherText);
}
public static String decrypt(String encryptedText) throws Exception {
System.out.println(encryptedText);
String[] encryptedArr = encryptedText.split(SEPARATOR);
byte[] ivBytes = DatatypeConverter.parseBase64Binary(new String(encryptedArr[0]));
byte[] salt = DatatypeConverter.parseBase64Binary(new String(encryptedArr[1]));
byte[] encryptedTextBytes = DatatypeConverter.parseBase64Binary(new String(encryptedArr[2]));
SecretKeyFactory skf = SecretKeyFactory.getInstance(algorithm);
PBEKeySpec spec = new PBEKeySpec(password, salt, iterations, keySize);
SecretKey secretKey = skf.generateSecret(spec);
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);
}
}
암호를 저장하는 가장 좋은 장소는 사람의 뇌입니다. 그것은 처음부터 암호를 사용하는 요지입니다. 머신에 저장하는 경우 이진 키를 안전한 방법으로 저장하는 것이 좋습니다. – Henry
이 작업을 잘 수행하는 라이브러리 중 하나를 사용하지 않는 이유는 무엇입니까? [RNCryptor] (https://github.com/RNCryptor/JNCryptor)와 [this one] (https://github.com/tozny/java-aes-crypto)이 떠오른다. –