5

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

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

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

4

2 回答 2

14

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

如果您真的需要处理更长的消息,那么您必须添加其他内容。在这种情况下,请,不要尝试做任何你自己设计的花哨的事情,将数据拆分成小块之类的东西。那条路通向厄运。你可能会产生一些看起来可以编译和运行的东西,但在某些方面总是很弱,就像几乎所有其他自制的密码学变体一样。那是因为无法测试安全性:这不是“有效”或“无效”的情况。

非对称加密的成熟路径是这样的:

  1. 您选择一些适当长度的随机字节序列,例如 128 位(即 16 个字节)。我们称它为K
  2. 你用 RSA 公钥加密K ;这产生E
  3. 您使用对称加密算法 ( ) 使用K"AES/CBC/PKCS5Padding"加密消息。由于这是一次性键,因此您可以使用全零 IV。这会产生一堆字节,我们称之为F
  4. 加密的消息是EF的串联。

解密以相反的顺序进行:RSA 私钥用于从E中恢复K,然后K用于将F解密为原始消息。密钥K永远不会存储在任何地方,并且每次都会生成一个新的密钥 K (即使您对同一消息进行了两次加密)。这很重要,除非您了解自己在做什么(如果您了解了,那么您已经知道了),否则不要改变这一点。

鉴于您对问题的陈述,您必须做的不仅仅是“只是 RSA”。我上面描述的过程是关于安全方面你能想到的最好的“其他东西”。

将一些加密元素组装到这样的协议中是一个充满陷阱的过程,因此使用已经定义的格式和支持库可能会更好。非对称加密的两种常见格式是CMSOpenPGP。一个支持两者并享有良好声誉的图书馆是Bouncy Castle

于 2010-04-16T15:54:39.167 回答
3

如果您确实需要使用 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();
于 2014-05-18T15:15:03.020 回答