gpt4 book ai didi

java - 从 RSA 编码的 AES key 生成 AES key

转载 作者:行者123 更新时间:2023-12-02 11:51:21 38 4
gpt4 key购买 nike

我想做的是使用 AES 加密字符串,使用 RSA 加密 AES key getEncoded() 值,然后解密 AES getEncoded() 值,以便获得原始字符串。公钥从用户证书加载,私钥从文件加载。代码如下。

public class Main {

public static void main(String[] args) throws Exception {
String myString = "My Message";
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(128);

SecretKey secretKey = keyGenerator.generateKey();

byte[] initializationVector = new byte[128 / 8];//16
SecureRandom prng = new SecureRandom();
prng.nextBytes(initializationVector);

Cipher AESCipherForEncryption = Cipher.getInstance("AES/CBC/PKCS5PADDING");

AESCipherForEncryption.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(initializationVector));

byte[] byteVersionOfMyMessage = myString.getBytes();
byte[] byteVersionOfCipherText = AESCipherForEncryption.doFinal(byteVersionOfMyMessage);
String cipherText = new BASE64Encoder().encode(byteVersionOfCipherText);

InputStream in1 = new FileInputStream("user.crt");
CertificateFactory cf1 = CertificateFactory.getInstance("X509");
Certificate c1 = cf1.generateCertificate(in1);
X509Certificate toSendcert = (X509Certificate) c1;
PublicKey publicKey = toSendcert.getPublicKey();
String cipherTextRSA = encryptRSA(publicKey, new String(secretKey.getEncoded()));

String decypheredRSA = decryptRSA(getPrivateKey("user.pk8", "RSA"), cipherTextRSA);
System.out.println(cipherTextRSA);
System.out.println(decypheredRSA);

SecretKey originalKey = new SecretKeySpec(new String(decypheredRSA.getBytes("UTF-8")).getBytes(), 0, new String(decypheredRSA.getBytes("UTF-8")).getBytes().length, "AES");

Cipher AESCipherForDecryption = Cipher.getInstance("AES/CBC/PKCS5PADDING");
AESCipherForDecryption.init(Cipher.DECRYPT_MODE, originalKey, new IvParameterSpec(initializationVector));
byte[] byteVersionOfDecriptedText = AESCipherForDecryption.doFinal(new BASE64Decoder().decodeBuffer(cipherText));
String decMessage = new String(byteVersionOfDecriptedText);
System.out.println(decMessage);
}
public static String encryptRSA(PublicKey pubKey, String message) throws Exception {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
Base64.Encoder encoder = Base64.getEncoder();
String encryptedString = encoder.encodeToString(cipher.doFinal(message.getBytes("UTF-8")));
return encryptedString;
}

public static PrivateKey getPrivateKey(String filename, String algorithm) throws Exception {
File f = new File(filename);
FileInputStream fis = new FileInputStream(f);
DataInputStream dis = new DataInputStream(fis);
byte[] keyBytes = new byte[(int) f.length()];
dis.readFully(keyBytes);
dis.close();

String temp = new String(keyBytes);
String privKeyPEM = temp.replace("-----BEGIN PRIVATE KEY-----", "");
privKeyPEM = privKeyPEM.replace("-----END PRIVATE KEY-----", "");
privKeyPEM = privKeyPEM.replace("\n", "");

byte[] decoded = Base64.getDecoder().decode(privKeyPEM);

PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(decoded);
KeyFactory kf = KeyFactory.getInstance(algorithm);
return kf.generatePrivate(spec);
}

public static String decryptRSA(PrivateKey prKey, String encrypted) throws Exception {
Base64.Decoder decoder = Base64.getDecoder();
byte[] input = decoder.decode(encrypted);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, prKey);

return new String(cipher.doFinal(input));
}

我不断收到的错误是:

Exception in thread "main" java.security.InvalidKeyException: Invalid AES key length: 28 bytes
at com.sun.crypto.provider.AESCipher.engineGetKeySize(AESCipher.java:509)
at javax.crypto.Cipher.passCryptoPermCheck(Cipher.java:1067)
at javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1038)
at javax.crypto.Cipher.implInit(Cipher.java:805)
at javax.crypto.Cipher.chooseProvider(Cipher.java:864)
at javax.crypto.Cipher.init(Cipher.java:1396)
at javax.crypto.Cipher.init(Cipher.java:1327)
at com.company.Main.main(Main.java:79)

如果我不加密和解密 secretKey.getEncoded() 值,并且仅使用 AES 而无需 RSA,则它可以正常工作。同样使用 RSA,如果我只是用公钥加密一些字符串,并用私钥解密它,它就可以工作。我的问题是:“如何使用 RSA 正确加密和解​​密 secretKey.getEncoded() 值,以便我可以正确加密和解​​密 myString?”。

最佳答案

new String(secretKey.getEncoded())

这不起作用,因为 AES key 包含随机字节,并且并非每个字节都是字符代表。 Java中标准字符串转换的问题在于,它会在编码/解码过程中丢弃未知的字符和字节,而不是生成异常。

RSA 对字节进行操作,您不应将 key 转换为字符串,然后再转换回字节,因为转换可能会出现损耗(例如,删除 32 个字节中的 4 个字节)。

或者 - 甚至可能更好 - 您可能想尝试密码的包装模式。这应该与现有的一些硬件解决方案兼容。在这种情况下,您甚至不必调用 getEncoded

<小时/>

OAEP 加密和经过身份验证的加密模式(例如 GCM)应优先于 PKCS#1 填充(Sun 提供商的默认设置)和 CBC 模式加密。

关于java - 从 RSA 编码的 AES key 生成 AES key ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47866666/

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