Java中基于AES-256密码的加密/解密

我找到了用Java实施AES加密/解密的指南,并试图理解每一行并将其放入自己的解决方案中。但是,我没有完全理解它,因此出现了问题。最终目标是拥有基于密码的加密/解密。我已经阅读了有关此的其他文章/

stackoverflow帖子,但是大多数文章没有提供足够的解释(我对Java加密非常陌生)

我现在的主要问题是,即使设置了byte[] saltBytes = "Hello".getBytes();

I,最后还是会得到不同的Base64结果(char[]

password每次都是随机的,但是我读到将密码保留在char[]窗体中是更安全的。我的另一个问题是,当程序进入decrypt(),我得到一个NullPointerException

byte[] saltBytes = salt.getBytes("UTF-8");

预先感谢您可以给我的任何帮助/建议。

有问题的代码:

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();

}

}

回答:

我认为您犯了两个错误:)

我已更正您的示例代码以使其正常工作:

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);

}

}

第一个错误是您生成2种不同的盐(使用加密方法时),因此加密/解密的日志是不同的(逻辑上,但是解密仍然有效,因为您在加密后立即调用解密)。

第二个错误是密钥。在加密而不是解密时,需要生成一个秘密密钥。简而言之,好像我正在使用密码“ encrypt”进行加密一样,而您正在尝试使用密码“

decrypt”对其进行解密。

我建议您在启动时生成所有随机的东西(例如私钥,盐等)。但要注意,当您停止应用程序时,除非获得完全相同的随机内容,否则您将无法解密旧内容。

希望我能帮到:)

问候,

以上是 Java中基于AES-256密码的加密/解密 的全部内容, 来源链接: utcz.com/qa/414670.html

回到顶部