【问题标题】:Encrypted AES key too large to Decrypt with RSA (Java)加密的 AES 密钥太大而无法使用 RSA (Java) 解密
【发布时间】:2010-05-03 14:48:48
【问题描述】:

我正在尝试制作一个使用 AES 加密数据,然后使用 RSA 加密 AES 密钥,然后解密的程序。但是,一旦我加密了 AES 密钥,它就会变成 128 个字节。 RSA 只允许我解密 117 个字节或更少,所以当我去解密 AES 密钥时它会抛出一个错误。

相关代码:

    KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
    kpg.initialize(1024);
    KeyPair kpa = kpg.genKeyPair();
    pubKey = kpa.getPublic();
    privKey = kpa.getPrivate();

    updateText("Private Key: " +privKey +"\n\nPublic Key: " +pubKey);

    updateText("Encrypting " +infile);
    //Genereate aes key
    KeyGenerator kgen = KeyGenerator.getInstance("AES");
    kgen.init(128); // 192/256
    SecretKey aeskey = kgen.generateKey();
    byte[] raw = aeskey.getEncoded();

    SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");

    updateText("Encrypting data with AES");
    //encrypt data with AES key
    Cipher aesCipher = Cipher.getInstance("AES");
    aesCipher.init(Cipher.ENCRYPT_MODE, skeySpec);
    SealedObject aesEncryptedData = new SealedObject(infile, aesCipher);

    updateText("Encrypting AES key with RSA");
    //encrypt AES key with RSA
    Cipher cipher = Cipher.getInstance("RSA");
    cipher.init(Cipher.ENCRYPT_MODE, pubKey);
    byte[] encryptedAesKey = cipher.doFinal(raw);

    updateText("Decrypting AES key with RSA. Encrypted AES key length: " +encryptedAesKey.length);
    //decrypt AES key with RSA       
    Cipher decipher = Cipher.getInstance("RSA");
    decipher.init(Cipher.DECRYPT_MODE, privKey);
    byte[] decryptedRaw = decipher.doFinal(encryptedAesKey); //error thrown here because encryptedAesKey is 128 bytes
    SecretKeySpec decryptedSecKey = new SecretKeySpec(decryptedRaw, "AES");

    updateText("Decrypting data with AES");
    //decrypt data with AES key
    Cipher decipherAES = Cipher.getInstance("AES");
    decipherAES.init(Cipher.DECRYPT_MODE, decryptedSecKey);
    String decryptedText = (String) aesEncryptedData.getObject(decipherAES);

    updateText("Decrypted Text: " +decryptedText);

知道如何解决这个问题吗?

【问题讨论】:

  • 您对错误的描述没有意义。您应该发布完整的堆栈跟踪。就目前而言,您的代码的 RSA 部分应该可以正常工作。我对其进行了测试,对我来说效果很好。
  • 啊,我明白了,你是个懒惰的混蛋。我看到你一个月前在 sun 论坛上发布了相同的代码你被告知你的错误是什么。然后你只是重新发布相同的代码只是为了浪费大家的时间。如果我经营这个网站,我会删除你的帐户。

标签: java security encryption cryptography rsa


【解决方案1】:

当您使用加密时,始终指定填充。否则,您的明文将被填充到块大小。例如,

Cipher aes = Cipher.getInstance("AES/CBC/PKCS5Padding");

Cipher rsa = Cipher.getInstance("RSA/None/PKCS1Padding");

对于 128 位,AES 密钥只有 16 个字节。所以它应该很适合任何 RSA 块。

【讨论】:

  • 谢谢,你有更多关于哪些算法可以使用哪些填充方案的信息吗?
  • 每种算法支持的填充取决于 JCE 实现。我的示例中的值是 AES 和 RSA 的推荐设置。
  • -1 他的问题与所使用的填充类型完全无关。块密码总是会产生相同大小的块,并且需要填充。例如,AES 128 将始终生成可被 128 位整除的密文。当然,除非您使用的是 OFB 模式。
  • 似乎无论我指定哪个填充(甚至是 NOPADDING),加密的 AES 密钥总是出现 128 个字节
【解决方案2】:

编辑:我误解了这个问题。您应该使用更大的 RSA 密钥,例如 RSA 4096 允许您加密 501 个字节。

您可以尝试在OFB mode 中使用 AES,这将允许您加密任意大小的消息。或者,您可以使用像 RC4 这样的流密码,它还允许您加密任意大小的消息。如果您使用 RC4,请确保使用 RC4-drop1024,这意味着您丢弃了密文的前 1024 个字节。 rc4 的前 1024 位是可预测的,这以及许多其他问题导致了用于保护 WIFI 的 WEP 的失败。 RC4 的另一个问题是你不能重用 PRNG 流,基本上你必须为每条消息使用不同的密钥,否则攻击者可以很容易地使用 XOR 来破坏系统。我会在 OFB 模式下使用 AES,但可以安全地使用 RC4。

所有其他块密码模式将始终生成可被其块大小整除的消息。例如,CBC 模式下的 AES 128 将始终产生可被 128 位整除的消息。如果消息小于 128 位,则通常用空值填充。如果这是一个字符串,那么它应该是空终止的,你不必担心。

另一方面,请确保您不使用ECB mode。另一个问题是我没有看到您正在使用旋转或随机初始化向量 (IV),这会显着削弱任何分组密码。未能正确实施 IV 是 CWE-329 公认的漏洞。

【讨论】:

  • 感谢您的建议,尤其是关于 IV 的建议,但问题不在于 AES 的实现,而在于 RSA。每当我加密 16 字节的 AES 密钥(使用 RSA)时,结果为 128 字节,大于 RSA 的 117 字节上限,因此我无法解密。
  • @Petey B 哦,对不起,我误解了,这是一个更容易解决的问题,只需使用更大的 RSA 密钥。例如 RSA 4096 允许您加密 501 个字节。
  • 这太令人困惑了。原始 RSA 密钥的大小应该绰绰有余。并且贴出的代码不会出现报错。
【解决方案3】:

只需我们使用 Cipher 类的包装模式/功能,您就可以摆脱复杂性的麻烦。您可以查看my source code 了解如何执行此操作的示例。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-08
    • 1970-01-01
    • 1970-01-01
    • 2017-11-08
    • 1970-01-01
    相关资源
    最近更新 更多