嗨,这是两年前问过的同一个问题: Java/JCE:解密用 RSA 加密的“长”消息
我有一个大字节数组和 rsa 密钥对,由值 1024 启动。使用 rsa 加密和密钥的指定大小是强要求,我无法更改它。所以我不能将对称加密与非对称加密对称密钥一起使用。我不能使用任何其他键。我有一个字节数组,需要返回加密的字节数组。我想知道是否有任何现成的工具可以解决这个问题?
对于这样一个业余的问题,我很抱歉,但我真的需要帮助。
嗨,这是两年前问过的同一个问题: Java/JCE:解密用 RSA 加密的“长”消息
我有一个大字节数组和 rsa 密钥对,由值 1024 启动。使用 rsa 加密和密钥的指定大小是强要求,我无法更改它。所以我不能将对称加密与非对称加密对称密钥一起使用。我不能使用任何其他键。我有一个字节数组,需要返回加密的字节数组。我想知道是否有任何现成的工具可以解决这个问题?
对于这样一个业余的问题,我很抱歉,但我真的需要帮助。
如前所述,您的问题只有一个答案,那就是“否”。RSA 加密是一种将消息加密到给定大小的算法,具体大小取决于密钥大小;具有 1024 位 RSA 密钥,并且 RSA 作为标准描述的,最大大小为 117 字节,仅此而已。仅使用 RSA 无法加密更大的消息,这是一个明确的数学确定性。
如果您真的需要处理更长的消息,那么您必须添加其他内容。在这种情况下,请,请不要尝试做任何你自己设计的花哨的事情,将数据拆分成小块之类的东西。那条路通向厄运。你可能会产生一些看起来可以编译和运行的东西,但在某些方面总是很弱,就像几乎所有其他自制的密码学变体一样。那是因为无法测试安全性:这不是“有效”或“无效”的情况。
非对称加密的成熟路径是这样的:
"AES/CBC/PKCS5Padding"
加密消息。由于这是一次性键,因此您可以使用全零 IV。这会产生一堆字节,我们称之为F。解密以相反的顺序进行:RSA 私钥用于从E中恢复K,然后K用于将F解密为原始消息。密钥K永远不会存储在任何地方,并且每次都会生成一个新的密钥 K (即使您对同一消息进行了两次加密)。这很重要,除非您了解自己在做什么(如果您了解了,那么您已经知道了),否则不要改变这一点。
鉴于您对问题的陈述,您必须做的不仅仅是“只是 RSA”。我上面描述的过程是关于安全方面你能想到的最好的“其他东西”。
将一些加密元素组装到这样的协议中是一个充满陷阱的过程,因此使用已经定义的格式和支持库可能会更好。非对称加密的两种常见格式是CMS和OpenPGP。一个支持两者并享有良好声誉的图书馆是Bouncy Castle。
如果您确实需要使用 RSA 加密/解密长字符串,那么您可以将字节分解为更小的“块”,并一次通过密码处理每个字节块,同时将结果存储在 ByteBuffer 中。
加密:
byte[] encData = null;
try {
// create public key
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(key);
KeyFactory kf = KeyFactory.getInstance("RSA");
PublicKey pk = kf.generatePublic(publicKeySpec);
Cipher pkCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
pkCipher.init(Cipher.ENCRYPT_MODE, pk);
int chunkSize = 117; // 1024 / 8 - 11(padding) = 117
int encSize = (int) (Math.ceil(data.length/117.0)*128);
int idx = 0;
ByteBuffer buf = ByteBuffer.allocate(encSize);
while (idx < data.length) {
int len = Math.min(data.length-idx, chunkSize);
byte[] encChunk = pkCipher.doFinal(data, idx, len);
buf.put(encChunk);
idx += len;
}
// fully encrypted data
encData = buf.array();
} catch (Exception e) {
e.printStackTrace();
解密
Cipher rsaCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
rsaCipher.init(Cipher.DECRYPT_MODE, rsaPk);
int chunkSize = 128;
int idx = 0;
ByteBuffer buf = ByteBuffer.allocate(data.length);
while(idx < data.length) {
int len = Math.min(data.length-idx, chunkSize);
byte[] chunk = rsaCipher.doFinal(data, idx, len);
buf.put(chunk);
idx += len;
}
// fully decrypted data
byte[] decryptedData = buf.array();