加密的 AES 密钥太大,无法使用 RSA 解密 (Java)
我正在尝试制作一个程序,使用 AES 加密数据,然后使用 RSA 加密 AES 密钥,然后解密。然而,一旦我加密 AES 密钥,它就会变成 128 字节。 RSA 只允许我解密 117 字节或更少,所以当我去解密 AES 密钥时,它会抛出错误。
相关代码:
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(1024);
KeyPair kpa = kpg.genKeyPair();
pubKey = kpa.getPublic();
privKey = kpa.getPrivate();
updateText("Private Key: " +privKey +"\n\nPublic Key: " +pubKey);
updateText("Encrypting " +infile);
//Genereate aes key
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128); // 192/256
SecretKey aeskey = kgen.generateKey();
byte[] raw = aeskey.getEncoded();
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
updateText("Encrypting data with AES");
//encrypt data with AES key
Cipher aesCipher = Cipher.getInstance("AES");
aesCipher.init(Cipher.ENCRYPT_MODE, skeySpec);
SealedObject aesEncryptedData = new SealedObject(infile, aesCipher);
updateText("Encrypting AES key with RSA");
//encrypt AES key with RSA
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
byte[] encryptedAesKey = cipher.doFinal(raw);
updateText("Decrypting AES key with RSA. Encrypted AES key length: " +encryptedAesKey.length);
//decrypt AES key with RSA
Cipher decipher = Cipher.getInstance("RSA");
decipher.init(Cipher.DECRYPT_MODE, privKey);
byte[] decryptedRaw = decipher.doFinal(encryptedAesKey); //error thrown here because encryptedAesKey is 128 bytes
SecretKeySpec decryptedSecKey = new SecretKeySpec(decryptedRaw, "AES");
updateText("Decrypting data with AES");
//decrypt data with AES key
Cipher decipherAES = Cipher.getInstance("AES");
decipherAES.init(Cipher.DECRYPT_MODE, decryptedSecKey);
String decryptedText = (String) aesEncryptedData.getObject(decipherAES);
updateText("Decrypted Text: " +decryptedText);
知道如何解决这个问题吗?
I am trying to make a program that Encrypts data using AES, then encrypts the AES key with RSA, and then decrypt. However, once i encrypt the AES key it comes out to 128 bytes. RSA will only allow me to decrypt 117 bytes or less, so when i go to decrypt the AES key it throws an error.
Relavent code:
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(1024);
KeyPair kpa = kpg.genKeyPair();
pubKey = kpa.getPublic();
privKey = kpa.getPrivate();
updateText("Private Key: " +privKey +"\n\nPublic Key: " +pubKey);
updateText("Encrypting " +infile);
//Genereate aes key
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128); // 192/256
SecretKey aeskey = kgen.generateKey();
byte[] raw = aeskey.getEncoded();
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
updateText("Encrypting data with AES");
//encrypt data with AES key
Cipher aesCipher = Cipher.getInstance("AES");
aesCipher.init(Cipher.ENCRYPT_MODE, skeySpec);
SealedObject aesEncryptedData = new SealedObject(infile, aesCipher);
updateText("Encrypting AES key with RSA");
//encrypt AES key with RSA
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
byte[] encryptedAesKey = cipher.doFinal(raw);
updateText("Decrypting AES key with RSA. Encrypted AES key length: " +encryptedAesKey.length);
//decrypt AES key with RSA
Cipher decipher = Cipher.getInstance("RSA");
decipher.init(Cipher.DECRYPT_MODE, privKey);
byte[] decryptedRaw = decipher.doFinal(encryptedAesKey); //error thrown here because encryptedAesKey is 128 bytes
SecretKeySpec decryptedSecKey = new SecretKeySpec(decryptedRaw, "AES");
updateText("Decrypting data with AES");
//decrypt data with AES key
Cipher decipherAES = Cipher.getInstance("AES");
decipherAES.init(Cipher.DECRYPT_MODE, decryptedSecKey);
String decryptedText = (String) aesEncryptedData.getObject(decipherAES);
updateText("Decrypted Text: " +decryptedText);
Any idea on how to get around this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
当您使用加密时,请始终指定填充。否则,您的明文将被填充到块大小。例如,
128 位的 AES 密钥只有 16 个字节。所以它应该很好地适合任何 RSA 块。
When you use encryption, always specifying padding. Otherwise, your clear-text will be padded to the block size. For example,
The AES key is only 16 bytes for 128-bit. So it should fit in any RSA block nicely.
编辑:我误解了这个问题。您应该使用更大的 RSA 密钥,例如 RSA 4096 允许您加密 501 字节。
您可以尝试在 OFB 模式下使用 AES,这将允许您加密任意大小的消息。或者,您可以使用像 RC4 这样的流密码,它也允许您加密任意大小的消息。如果您使用 RC4,请确保使用 RC4-drop1024,这意味着您将丢弃密文的前 1024 个字节。 rc4 的前 1024 位是可预测的,这个问题以及许多其他问题导致了用于保护 WIFI 安全的 WEP 的失败。 RC4 的另一个问题是您无法重用 PRNG 流,基本上您必须为每个消息使用不同的密钥,否则攻击者只需使用 XOR 即可轻松破坏系统。我会在 OFB 模式下使用 AES,但 RC4 可以安全地使用。
所有其他分组密码模式将始终生成可被其分组大小整除的消息。例如,CBC 模式下的 AES 128 将始终生成可被 128 位整除的消息。如果消息小于 128 位,则通常用空值填充。如果这是一个字符串,那么它应该以空结尾,您不必担心。
另一方面,请确保您没有使用 ECB 模式。另一个问题是我没有看到您正在使用旋转或随机初始化向量(IV),这会显着削弱任何分组密码。未能正确实现 IV 是 CWE-329 认可的漏洞。
Edit: I misunderstood the problem. You should use a larger RSA key, for instance RSA 4096 allows you to encrypt 501 bytes.
You can try using AES in OFB mode which will allow you to encrypt a message of an arbitrary size. Alternately you could use a stream cipher like RC4 which will also allow you to encrypt an arbitrary sized message. If you go with RC4 make sure to use RC4-drop1024 which just means you throw away the first 1024 bytes of cipher text. The first 1024 bits of rc4 are predictable and this as well as many other issues led to the downfall of WEP used to secure WIFI. Another problem with RC4 is that you cannot reuse the PRNG stream, Basically you must use a different key for each message or an attacker can break the system pretty easily using nothing more than XOR. I'd go with AES in OFB mode, but RC4 can be used securely.
All other block cipher modes will always produce a message divisible by their block size. For instance AES 128 in CBC mode will always produce a message divisible by 128 bits. If the message is smaller than 128 bits its often padded with nulls. If this a string, then it should be null terminated and you don't have to worry.
On a Side not make sure you don't use ECB mode. Another problem is I don't see that you are using a rotating or randomized Initialization Vector (IV), which significantly weakens any block cipher. Failure to properly implement a IV is a recognized vulnerability by CWE-329.
只需使用 Cipher 类的包装模式/函数,您就可以摆脱复杂性的麻烦。您可以看到 我的源代码 了解如何执行此操作的示例。
You could get out of complexity trouble by just us the wrap mode/function of the Cipher class. You can see my source code for an example of how to do that.