解密用RSA java加密的“长”消息

时间:2010-04-16 14:19:34

标签: java encryption rsa encryption-asymmetric jce

嗨,这是同一个问题,两年前被问过: Java/JCE: Decrypting “long” message encrypted with RSA

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

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

2 个答案:

答案 0 :(得分:12)

如上所述,您的问题只有一个答案,那就是“不”。 RSA加密是一种算法,它对给定大小的消息进行加密,这取决于密钥大小;使用1024位RSA密钥和RSA the standard描述它,最大大小为117字节,不再多。单独使用RSA无法加密更大的消息,这是一个明确的数学确定性。

如果您确实需要处理更长的邮件,那么必然必须添加其他内容。在这种情况下,请,不要尝试做任何你自己设想的事情,用一些非常聪明的数据分成小块等。那条道路导致厄运。您可能会生成一些出现来编译和运行的东西,但在某种程度上它总是很弱,就像几乎所有其他自制的密码学变体一样。这是因为无法测试安全性:它不是“工作”或“不工作”的情况。

非对称加密的良好路径因此:

  1. 您可以选择一些适当长度的随机字节序列,例如: 128位(即16字节)。我们称之为 K
  2. 使用RSA公钥加密 K ;这会产生 E
  3. 使用对称加密算法("AES/CBC/PKCS5Padding")使用 K 加密邮件。由于这是一次性密钥,因此您可以使用全零IV。这会产生一堆字节,我们称之为 F
  4. 加密邮件是 E F 的串联。
  5. 解密以相反的顺序进行:RSA私钥用于从 E 恢复 K ,然后 K 用于解密< em> F 进入原始邮件。密钥 K 永远不会存储在任何地方,并且每次都会生成新密钥K (即使您将相同的消息加密两次)。这很重要,除非你明白自己在做什么,否则不要改变它(如果你这样做,那么你就已经知道了。)

    鉴于您对问题的陈述, 除了“只是RSA”之外还要做其他事情。我上面描述的程序是关于你可以提出的最好的“其他东西”,安全方面。

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

答案 1 :(得分:1)

如果您确实需要使用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();