gpt4 book ai didi

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

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:32:30 25 4
gpt4 key购买 nike

我找到了在 Java 中实现 AES 加密/解密的指南,并在将其放入我自己的解决方案时尝试理解每一行。但是,我并不完全理解它,因此遇到了问题。最终目标是进行基于密码的加密/解密。我已经阅读了关于此的其他文章/stackoverflow 帖子,但大多数都没有提供足够的解释(我对 Java 中的加密非常陌生)

我现在的主要问题是,即使我设置了 byte[] saltBytes = "Hello".getBytes();最后我仍然得到不同的 Base64 结果(char[] password 每次都是随机的,但我读到以 char[] 形式保留密码更安全。我的另一个问题是,当程序到达 decrypt() 时,我在 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 个不同的盐(当使用加密方法时),因此加密/解密的日志是不同的(逻辑上,但解密仍然有效,因为您在加密后直接调用解密)。

第二个错误是 key 错误。您需要在加密时生成 key ,而不是解密。更简单地说,就好像我正在使用密码“encrypt”进行加密,而您正在尝试使用密码“decrypt”对其进行解密。

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

希望我有所帮助:)

问候,

关于java - Java 中基于 AES-256 密码的加密/解密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28622438/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com