当前位置: 首页 > 面试题库 >

RSA块的数据过多失败。什么是PKCS#7?

谢奕
2023-03-14
问题内容

谈论 javax.crypto.Cipher

我试图使用加密数据,Cipher.getInstance("RSA/None/NoPadding", "BC")但出现异常:

ArrayIndexOutOfBoundsException:RSA块的数据过多

看起来与“ NoPadding”有关,因此,阅读有关填充的信息,看起来CBC是在此处使用的最佳方法。

我在Google上找到了有关“ RSA / CBC / PKCS#7”的东西,这是什么“
PKCS#7”?以及为什么它没有在sun的标准算法名称中列出?

更新:

我想知道,如果是填充问题,为什么这个示例运行得很好?

import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;

import javax.crypto.Cipher;

/**
 * Basic RSA example.
 */
public class BaseRSAExample
{
    public static void main(
        String[]    args)
        throws Exception
    {
        byte[]           input = new byte[] { (byte)0xbe, (byte)0xef };
        Cipher          cipher = Cipher.getInstance("RSA/None/NoPadding", "BC");
        KeyFactory       keyFactory = KeyFactory.getInstance("RSA", "BC");

        // create the keys

        RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(
                new BigInteger("d46f473a2d746537de2056ae3092c451", 16),
                new BigInteger("11", 16));
        RSAPrivateKeySpec privKeySpec = new RSAPrivateKeySpec(
                new BigInteger("d46f473a2d746537de2056ae3092c451", 16),  
                new BigInteger("57791d5430d593164082036ad8b29fb1", 16));

        RSAPublicKey pubKey = (RSAPublicKey)keyFactory.generatePublic(pubKeySpec);
        RSAPrivateKey privKey = (RSAPrivateKey)keyFactory.generatePrivate(privKeySpec);

        // encryption step

        cipher.init(Cipher.ENCRYPT_MODE, pubKey);

        byte[] cipherText = cipher.doFinal(input);

        // decryption step

        cipher.init(Cipher.DECRYPT_MODE, privKey);

        byte[] plainText = cipher.doFinal(cipherText);

    }
}

更新2:

我意识到即使我只使用Cipher.getInstance("RSA", "BC")它也会引发相同的异常。


问题答案:

如果使用分组密码,则输入的密码必须是分组位长度的精确倍数。

为了加密任意长度的数据,首先需要将数据填充为块长度的倍数。可以使用任何方法来完成此操作,但是有许多标准。PKCS7是非常常见的一种,您可以在wikipedia上有关padding的文章中看到概述。

由于块密码对块进行操作,因此您还需要提出一种将加密的块级联的方法。这非常重要,因为天真的技术大大降低了加密强度。对此也有维基百科文章。

您要做的是尝试加密(或解密)长度与密码的块长度不匹配的数据,并且您还明确要求不要填充,也不要链接操作模式。

因此,分组密码无法应用于您的数据,并且您收到了报告的异常。

更新:

作为对您的更新和GregS的评论的回应,我想承认GregS是正确的(我不了解RSA),并详细说明一下:

RSA不对位进行运算,而是对整数进行运算。为了使用RSA你因此需要将字符串信息转换为整数米:0 < m < n,其中n是在生成过程中所选择的两个不同的素数的模量。RSA算法中密钥的大小通常指n。有关此问题的更多详细信息,请参见RSA上的Wikipedia文章。

通常遵循将字符串消息转换为整数而不会丢失(例如截断初始零)的过程,通常使用PKCS#1标准。此过程还添加了一些其他信息,以确保消息的完整性(哈希摘要),语义安全性(IV)等。有了这些额外的数据,可以提供给RSA
/ None /
PKCS1Padding的最大字节数为(keylength-11)。我不知道PKCS#1如何将输入数据映射到输出整数范围,但是我的印象是,它可以接受小于或等于密钥长度-11的任何长度的输入,并为RSA加密生成有效的整数。

如果不使用填充,则您的输入将被简单地解释为数字。您的示例输入{0xbe,0xef}很可能会被解释为{10111110 + o 11101111} =
1011111011101111_2 = 48879_10 = beef_16(原文如此!)。由于0 <Beef_16
<d46f473a2d746537de2056ae3092c451_16,您的加密将成功。它应以小于d46f473a2d746537de2056ae3092c451_16的任何数字成功。

bouncycastle
FAQ中提到了此问题。他们还声明以下内容:

Bouncy
Castle随附的RSA实现仅允许加密单个数据块。RSA算法不适用于流数据,因此不应以这种方式使用。在这种情况下,您应该使用随机生成的密钥和对称密码对数据加密,然后再使用RSA加密随机生成的密钥,然后将加密的数据和加密的随机密钥发送到另一端逆转该过程(即使用其RSA私钥解密随机密钥,然后解密数据)。



 类似资料:
  • 问题内容: 我的Android应用程序存在一些问题。我正在尝试与RSA加密/解密相关的应用程序。这是我的问题: 我可以清楚地加密短句,但是当我尝试将此消息解密为原始文本时,我给出一个错误(“ RSA块数据太多”)。另外,如果我想加密一个长句子,我也会遇到同样的错误。 但是我什么都不懂,这些解决方案太复杂了。我该如何解决这个问题,谁能给我一个更简单的解决方案?谢谢。 EDİT:这些是我用于该项目的代

  • 本文向大家介绍什么是RSA算法?相关面试题,主要包含被问及什么是RSA算法?时的应答技巧和注意事项,需要的朋友参考一下 回答:RSA(Rivest-Shamir-Adelman)算法是用于签名数据和加密的第一个算法。它最广泛用于保护敏感数据。它也被称为非对称密码算法,它对两个不同的密钥(即公共密钥和私有密钥)起作用。公开密钥可以与任何人共享,并且私有密钥必须保密。

  • 我有以下代码: 它产生: 但是,我想创建一个看起来像这样的东西: 我如何更改代码,使它包含一个为所有学生的0的Fail列,并提供一个总计?

  • 用例:I有一个用例,其中客户机生成私钥和公钥,将64位编码的公钥发送给服务器。 在服务器端,我将使用此公钥加密消息,并将加密的消息发送到客户端,客户端使用其私钥对其进行解密。商定的算法是“RSA”。 问题是在服务器端,我看到某些密钥正在使用作为密钥规范工作 虽然一些键抛出异常()使用但使用工作: 所以,我开始理解的是,客户端和服务器需要同意是否使用:或来编码密钥。我的问题是哪一个更适合我的用例?什

  • 问题内容: 因此,我来​​到了一个地方,我想将存储在Redis中的数据分割到单独的数据库中,因为有时我需要对一种特定类型的数据使用keys命令,并希望将其分离以使其更快。 如果我细分为多个数据库,那么所有内容仍然都是单线程的,而且我仍然只能使用一个内核。如果我只是在同一盒子上启动另一个Redis实例,那么我将使用一个额外的内核。最重要的是,我无法命名Redis数据库,也无法给它们提供任何更逻辑的标