您好,这是两年前问过的同一个问题:Java/JCE:解密使用 RSA 加密的“长”消息

我有一个大字节数组和 rsa 密钥对,由值 1024 启动。使用 rsa 加密和指定密钥大小是强烈要求,我无法更改它。所以我不能使用对称加密和非对称加密对称密钥。我无法使用任何其他键。我有一个字节数组,需要返回加密的字节数组。我想知道是否有任何现成的工具可以解决这个问题?

很抱歉提出这样一个业余问题,但我真的需要帮助。

有帮助吗?

解决方案

如前所述,您的问题只有一个答案,那就是“不”。RSA 加密是一种将消息加密至给定大小的算法,该大小取决于密钥大小;使用 1024 位 RSA 密钥,并且 RSA 作为 标准 描述它,最大大小是117字节,没有更多。仅使用 RSA 无法加密更大的消息,这是明确的数学确定性。

如果您确实需要处理更长的消息,那么您 一定 必须添加其他东西。在这种情况下,请 , ,不要尝试做任何你自己设计的奇特的事情,比如将数据巧妙地分割成小块等。这条路通向厄运。你可能会生产出一些东西 出现 编译和运行,但在某种程度上总是很弱,就像几乎所有其他自制的密码学变体一样。这是因为安全性无法测试:这不是“有效”或“无效”的情况。

非对称加密的常用路径是这样的:

  1. 您选择适当长度的随机字节序列,例如128 位(即 16 个字节)。我们就这样称呼它吧 K.
  2. 你加密 K 使用 RSA 公钥;这产生 .
  3. 您使用以下方式加密消息 K 使用对称加密算法("AES/CBC/PKCS5Padding")。由于这是一次性密钥,因此您可以使用全零 IV。这会产生一堆字节,我们称之为 F.
  4. 加密消息是以下内容的串联 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();
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top