gpt4 book ai didi

java - 每次执行的 AES 加密 key 生成是否一致?

转载 作者:行者123 更新时间:2023-11-30 07:44:00 27 4
gpt4 key购买 nike

我发现了这个关于如何使用 AES 加密的写得很好的示例,我承认一些更高级的方面超出了我的能力范围。只要我使用相同的实例对象,该类就可以正常工作。如果我使用完全相同的密码创建另一个对象 - 该对象无法再正确解码前一个对象创建的任何类型的字符串或数据。我只能得出这样的结论:由于这段代码采用了相当弱的 passPhrase 字符串,混合了 SALT,并构建了一个更强的 128 位 key - 这个 key 构建过程每次都以某种方式随机化。其意义在于:

new AESEncrypter("MyPassword") <> new AESEncrypter("MyPassword")

有人可以帮我修改下面的类以获得所需的行为吗:

AESEncrypter a = new AESEncrypter("MyPassword")
String encoded = a.encrypt("my message")

AESEncrypter b = new AESEncrypter("MyPassword")
b.decrypt(encoded) == "my message"
import java.security.spec.KeySpec;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class AESEncrypter {

private static final byte[] SALT = {
(byte) 0xA9, (byte) 0x9B, (byte) 0xC8, (byte) 0x32,
(byte) 0x56, (byte) 0x35, (byte) 0xE3, (byte) 0x03
};
private static final int ITERATION_COUNT = 65536;
private static final int KEY_LENGTH = 128;
public Cipher ecipher;
public Cipher dcipher;

AESEncrypter(String passPhrase) throws Exception {

SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec spec = new PBEKeySpec(passPhrase.toCharArray(), SALT, ITERATION_COUNT, KEY_LENGTH);
SecretKey tmp = factory.generateSecret(spec);

// I Think the problem is here???

SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");

ecipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
ecipher.init(Cipher.ENCRYPT_MODE, secret);

dcipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] iv = ecipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV();
dcipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
}

public String encrypt(String encrypt) throws Exception {
byte[] bytes = encrypt.getBytes("UTF8");
byte[] encrypted = encrypt(bytes);
return new BASE64Encoder().encode(encrypted);
}

public byte[] encrypt(byte[] plain) throws Exception {
return ecipher.doFinal(plain);
}

public String decrypt(String encrypt) throws Exception {
byte[] bytes = new BASE64Decoder().decodeBuffer(encrypt);
byte[] decrypted = decrypt(bytes);
return new String(decrypted, "UTF8");
}

public byte[] decrypt(byte[] encrypt) throws Exception {
return dcipher.doFinal(encrypt);
}

public static void main(String[] args) throws Exception {

String message = "MESSAGE";
String password = "PASSWORD";

AESEncrypter encrypter1 = new AESEncrypter(password);
AESEncrypter encrypter2 = new AESEncrypter(password);

String encrypted1 = encrypter1.encrypt(message);
String encrypted2 = encrypter2.encrypt(message);

System.out.println("Display Encrypted from object 1 and 2..why do they differ?" );

System.out.println(encrypted1) ;
System.out.println(encrypted2) ;

System.out.println("Display Each object decrypting its own encrypted msg. Works as expected" );

System.out.println(encrypter1.decrypt(encrypted1)) ;
System.out.println(encrypter2.decrypt(encrypted2)) ;

System.out.println("Attempt to decrypt the each others msg.. will fail" );

System.out.println(encrypter1.decrypt(encrypted2)) ;
System.out.println(encrypter2.decrypt(encrypted1)) ;

}

}

显示对象 1 和 2 加密的内容......为什么它们不同?

drGy+BNSHPy34NWkkcNqLQ==9p06VfBgTuh7TizZSbvKjw==

Display Each object decrypting its own encrypted msg. Works as expected

MESSAGEMESSAGE

Attempt to decrypt the each others msg.. will fail

Error:

Exception in thread "main" javax.crypto.BadPaddingException: Given final block not properly padded
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:966)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:824)
at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:436)
at javax.crypto.Cipher.doFinal(Cipher.java:2165)

最佳答案

问题是,当您在 CBC 模式下初始化新的 Cipher 时,它会为您生成一个新的随机 IV。该初始化 vector 不必是 secret 的,但它必须是不可预测的以提供语义安全性。你可以简单地将IV放在密文前面并用它来解密。

public byte[] encrypt(byte[] plain) throws Exception {
byte[] iv = ecipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV();
byte[] ct = ecipher.doFinal(plain);
byte[] result = new byte[ct.length + iv.length];
System.arraycopy(iv, 0, result, 0, iv.length);
System.arraycopy(ct, 0, result, iv.length, ct.length);
return result;
}

public byte[] decrypt(byte[] encrypt) throws Exception {
byte[] iv = new byte[dcipher.getBlockSize()];
byte[] ct = new byte[encrypt.length - dcipher.getBlockSize()];
System.arraycopy(encrypt, 0, iv, 0, dcipher.getBlockSize());
System.arraycopy(encrypt, dcipher.getBlockSize(), ct, 0, ct.length);

dcipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
return dcipher.doFinal(ct);
}

您需要在初始化步骤中将 secret 存储在私有(private)变量中,以便解密工作。

<小时/>

请记住,PBDKF2 的盐也应该是随机的且长度为 16 个字节。您可以将其与 IV 一起存储。

关于java - 每次执行的 AES 加密 key 生成是否一致?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34193514/

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