第二个错误是密钥错误.加密时需要生成密钥,但不解密时需要生成密钥.更简单地说,就好像我用密码encrypt"加密,而你试图用密码decrypt"解密.我建议您在启动时生成所有随机内容(例如私钥、盐等).但请注意,当您停止应用时,除非获得完全相同的随机内容,否则您将无法解密旧内容.希望我有所帮助:)问候,I found a guide for implementing AES encryption/decryption in Java and tried to understand each line as I put it into my own solution. However, I don't fully understand it and am having issues as a result. The end goal is to have passphrase based encryption/decryption. I've read other articles/stackoverflow posts about this, but most do not provide enough explanation (I am very new to crypto in Java)My main issues right now are that even when I set byte[] saltBytes = "Hello".getBytes();I still get a different Base64 result in the end (char[] password is random each time, but I read that it is safer to leave passwords in char[] form. My other problem is that when the program gets to decrypt(), I get a NullPointerException at byte[] saltBytes = salt.getBytes("UTF-8");Thank you in advance for any help/advice you can give me.The code in question: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; public static void main(String []args) throws Exception { char[] message = "PasswordToEncrypt".toCharArray(); System.out.println("Message: " + message.toString()); System.out.println("Encrypted: " + encrypt(message)); System.out.println("Decrypted: " + decrypt(encrypt(message).toCharArray())); } public static String encrypt(char[] plaintext) throws Exception { salt = getSalt(); byte[] saltBytes = salt.getBytes(); SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); PBEKeySpec spec = new PBEKeySpec(plaintext, 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(); ivBytes = params.getParameterSpec(IvParameterSpec.class).getIV(); byte[] encryptedTextBytes = cipher.doFinal(plaintext.toString().getBytes("UTF-8")); return DatatypeConverter.printBase64Binary(encryptedTextBytes); } public static String decrypt(char[] encryptedText) throws Exception { byte[] saltBytes = salt.getBytes("UTF-8"); byte[] encryptedTextBytes = DatatypeConverter.parseBase64Binary(encryptedText.toString()); SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); PBEKeySpec spec = new PBEKeySpec(encryptedText, 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.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 decryptedTextBytes.toString(); } public static String getSalt() throws Exception { SecureRandom sr = SecureRandom.getInstance("SHA1PRNG"); byte[] salt = new byte[20]; sr.nextBytes(salt); return salt.toString(); }} 解决方案 I think that you are making two mistakes :)I've corrected your sample code to make it work :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; 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("PBKDF2WithHmacSHA1"); PBEKeySpec spec = new PBEKeySpec(plaintext, 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); }}The first mistake is that you generate 2 different salts (when using the encrypt method), so encrypted/decrypted logs were differents (logical, but the decryption would still work because you are calling the decryption directly after encryption).The second mistake was for the secret key. You need to generate a secret key when you are encrypting, but not decrypting. To put it more simply, it is as if i was encrypting with the password "encrypt" and that you are trying to decrypt it with the password "decrypt".I would advise you to generate every random stuff (such as private key, salt etc on startup). But beware that when you'll stop your app, you won't be able to decrypt old stuff unless getting the exact same random stuff.Hope I helped :)Regards, 这篇关于Java 中基于 AES-256 密码的加密/解密的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云!
07-31 09:24