Ho un'applicazione che deve memorizzare alcune password segrete in un file di configurazione come database e password/dettagli ftp. Mi sono guardato intorno e ho trovato molte soluzioni di crittografia/decrittografia usando AES, ma non riesco a capire come farlo funzionare senza cambiare la chiave. Ciò significa che posso crittografare e decifrare (usando la stessa SecretKey), ma per mantenere la persistenza attraverso i riavvii ecc. Non riesco a far sembrare la SecretKey uguale. L'esempio seguente mostra i miei metodi operativi:Codifica e decrittografia Java AES con segreto statico
String secret = Encryptor.encrpytString("This is secret");
String test = Encryptor.decrpytString(secret);
System.out.println(test); //This is secret is printed
Fin qui tutto bene. Comunque se lo eseguo una volta potrei ottenere il valore di '2Vhht/L80UlQ184S3rlAWw ==' come mio segreto, la prossima volta che è 'MeC4zCf9S5wUUKAu8rvpCQ ==', presumibilmente la chiave sta cambiando. Suppongo di applicare una logica controintuitiva al problema e apprezzerei se qualcuno potesse far luce su a) cosa sto facendo male, o b) una soluzione che mi permettesse di memorizzare le informazioni della password crittografate e recuperabile con le informazioni fornite.
I miei metodi sono i seguenti:
private static final String salt = "SaltySalt";
private static byte [] ivBytes = null;
private static byte[] getSaltBytes() throws Exception {
return salt.getBytes("UTF-8");
}
private static char[] getMasterPassword() {
return "SuperSecretPassword".toCharArray();
}
private static byte[] getIvBytes() throws Exception {
if (ivBytes == null) {
//I don't have the parameters, so I'll generate a dummy encryption to create them
encrpytString("test");
}
return ivBytes;
}
public static String encrpytString (String input) throws Exception {
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
PBEKeySpec spec = new PBEKeySpec(getMasterPassword(), getSaltBytes(), 65536,256);
SecretKey secretKey = factory.generateSecret(spec);
SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret);
ivBytes = cipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV();
byte[] encryptedTextBytes = cipher.doFinal(input.getBytes("UTF-8"));
return DatatypeConverter.printBase64Binary(encryptedTextBytes);
}
public static String decrpytString (String input) throws Exception {
byte[] encryptedTextBytes = DatatypeConverter.parseBase64Binary(input);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
PBEKeySpec spec = new PBEKeySpec(getMasterPassword(), getSaltBytes(), 65536, 256);
SecretKey secretKey = factory.generateSecret(spec);
SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(getIvBytes()));
byte[] decryptedTextBytes = cipher.doFinal(encryptedTextBytes);
return new String(decryptedTextBytes);
}
Grazie per l'aiuto!
Questo è esattamente quello che ho in un'interfaccia di integrazione di terze parti. Campo dati di input XML Base64toBytes, byte 0..15 sono valore IV, decrittografano byte 16..n con una chiave segreta. – Whome
Per AES/CBC/PKCS7Padding, la maggior parte delle persone sceglie anteporre IV al testo cifrato. Quindi, su decifratura, taglia i primi 16 byte dal testo cifrato, sono IV, inizia il cifrario e poi doFinal con il resto. Questo ha alcune proprietà interessanti, in particolare le implementazioni che non seguono questa convenzione, ma iniziano solo con un IV e scartano il primo blocco ancora in grado di decifrare il testo. – wallenborn
Grazie per la conferma ragazzi! – Aaron