解密使用 RSA java 加密的“长”消息
-
27-09-2019 - |
题
您好,这是两年前问过的同一个问题:Java/JCE:解密使用 RSA 加密的“长”消息
我有一个大字节数组和 rsa 密钥对,由值 1024 启动。使用 rsa 加密和指定密钥大小是强烈要求,我无法更改它。所以我不能使用对称加密和非对称加密对称密钥。我无法使用任何其他键。我有一个字节数组,需要返回加密的字节数组。我想知道是否有任何现成的工具可以解决这个问题?
很抱歉提出这样一个业余问题,但我真的需要帮助。
解决方案
如前所述,您的问题只有一个答案,那就是“不”。RSA 加密是一种将消息加密至给定大小的算法,该大小取决于密钥大小;使用 1024 位 RSA 密钥,并且 RSA 作为 标准 描述它,最大大小是117字节,没有更多。仅使用 RSA 无法加密更大的消息,这是明确的数学确定性。
如果您确实需要处理更长的消息,那么您 一定 必须添加其他东西。在这种情况下,请 请, ,不要尝试做任何你自己设计的奇特的事情,比如将数据巧妙地分割成小块等。这条路通向厄运。你可能会生产出一些东西 出现 编译和运行,但在某种程度上总是很弱,就像几乎所有其他自制的密码学变体一样。这是因为安全性无法测试:这不是“有效”或“无效”的情况。
非对称加密的常用路径是这样的:
- 您选择适当长度的随机字节序列,例如128 位(即 16 个字节)。我们就这样称呼它吧 K.
- 你加密 K 使用 RSA 公钥;这产生 乙.
- 您使用以下方式加密消息 K 使用对称加密算法(
"AES/CBC/PKCS5Padding"
)。由于这是一次性密钥,因此您可以使用全零 IV。这会产生一堆字节,我们称之为 F. - 加密消息是以下内容的串联 乙 和 F.
解密按相反的顺序进行:RSA私钥用于恢复 K 从 乙, , 然后 K 用于解密 F 到原始消息中。钥匙 K 永远不会存储在任何地方,并且 新钥匙K 每次都会生成(即使您对同一消息加密两次)。这很重要,除非您了解自己在做什么(如果您了解,那么您已经知道了),否则不要更改它。
鉴于您对问题的陈述,您 有 做“只是 RSA”以外的事情。我上面描述的过程是关于安全方面您可以想出的最好的“其他东西”。
将一些加密元素组装到这样的协议中是一个充满陷阱的过程,因此使用已经定义的格式和支持库可能会运气更好。非对称加密的两种常见格式是 内容管理系统 和 开放PGP. 。一个同时支持两者并具有良好声誉的图书馆是 充气城堡.
其他提示
如果你需要加密/解密的使用RSA,则可以突破到较小的“块”的字节并在每次处理通过加密一个字节的每个组块,同时存储在一个字节缓冲区的结果长字符串。
<强>加密强>
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();