RSA块的太多数据失败。什么是PKCS#7? [英] Too much data for RSA block fail. What is PKCS#7?

查看:155
本文介绍了RSA块的太多数据失败。什么是PKCS#7?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

讨论 javax.crypto.Cipher

我试图使用 Cipher.getInstance(RSA / None / NoPadding,BC)但我有个异常:

I was trying to encrypt data using Cipher.getInstance("RSA/None/NoPadding", "BC") but I got the exception:

ArrayIndexOutOfBoundsException: too much data for RSA block

看起来像是与NoPadding相关的东西,所以,阅读关于填充,看起来像CBC是最好的使用方法这里。

Looks like is something related to the "NoPadding", so, reading about padding, looks like CBC is the best approach to use here.

我在google上发现了RSA / CBC / PKCS#7,这是什么PKCS#7?以及为什么其未列在 sun的标准算法名称< a>?

I found at google something about "RSA/CBC/PKCS#7", what is this "PKCS#7"? And why its not listed on sun's standard algorithm names?

更新:

padding问题,为什么这个例子运行就好了?

I'm wondering, if is a padding problem, why this example run just fine?

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: / strong>

Update 2:

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

I realized that even if I use just Cipher.getInstance("RSA", "BC") it throws the same exception.

推荐答案

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

If you use a block cipher, you input must be an exact multiple of the block bit length.

为了加密任意长度的数据,您需要先将数据填充到块长度的倍数。这可以用任何方法完成,但有一些标准。 PKCS7是很常见的一种,您可以在wikipedia文章中查看填充

In order to encipher arbitrary length data, you need first to pad you data to a multiple of the block length. This can be done with any method, but there are a number of standards. PKCS7 is one which is quite common, you can see an overview on the wikipedia article on padding.

由于区块清除器对块进行操作,因此您还需要提供一种连接加密块的方法。这是非常重要的,因为朴素的技术大大降低了加密的强度。此外,还有维基百科的文章

Since block cipers operate on blocks, you also need to come up with a way of concatenating the encrypted blocks. This is very important, since naive techniques greatly reduce the strength of the encryption. There is also a wikipedia article on this.

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

What you did was to try to encrypt (or decrypt) data of a length which didn't match the block length of the cipher, and you also explicitly asked for no padding and also no chaining mode of operation.

因此,区块密码无法套用到您的资料,而且得到报告的例外。

Consequently the block cipher could not be applied to your data, and you got the reported exception.

UPDATE :

作为对您的更新和GregS的评论的回应,我想承认GregS是正确的(我不知道这个关于RSA),并阐述一点:

As a response to your update and GregS's remark, I would like to acknowledge that GregS was right (I did not know this about RSA), and elaborate a bit:

RSA不对位操作,它对整数进行操作。为了使用RSA,你需要将你的字符串消息转换成一个整数m: 0< m < n ,其中 n 是在生成过程中选择的两个不同素数的模数。 RSA算法中的键的大小通常指 n 。有关详情,请参阅关于RSA的维基百科

RSA does not operate on bits, it operates on integer numbers. In order to use RSA you therefore need to convert your string message into an integer m: 0 < m < n, where n is the modulus of the two distinct primes chosen in the generation process. The size of a key in the RSA algorithm typically refers to n. More details on this can be found on the wikipedia article on RSA.

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

The process of converting a string message to an integer, without loss (for instance truncating initial zeroes), the PKCS#1 standard is usually followed. This process also adds some other information for message integrity (a hash digest), semantical security (an IV) ed cetera. With this extra data, the maximum number of bytes which can be supplied to the RSA/None/PKCS1Padding is (keylength - 11). I do not know how PKCS#1 maps the input data to the output integer range, but my impression is that it can take any length input less than or equal to keylength - 11 and produce a valid integer for the RSA encryption.

如果不使用填充,您的输入将简单地解释为一个数字。您的示例输入{0xbe,0xef}很可能被解释为{10111110 + o 11101111} = 1011111011101111_2 = 48879_10 = beef_16(sic!)。由于0 < beef_16< d46f473a2d746537de2056ae3092c451_16,您的加密将成功。

If you use no padding, your input will simply be interpreted as a number. Your example input, {0xbe, 0xef} will most probably be interpreted as {10111110 +o 11101111} = 1011111011101111_2 = 48879_10 = beef_16 (sic!). Since 0 < beef_16 < d46f473a2d746537de2056ae3092c451_16, your encryption will succeed. It should succeed with any number less than d46f473a2d746537de2056ae3092c451_16.

bouncycastle常见问题。它们还声明了以下内容:

This is mentioned in the bouncycastle FAQ. They also state the following:



附带的RSA实现Bouncy Castle只允许
加密单个数据块。
RSA算法不适用于
流数据,不应该使用
。在这样的情况下,
应该使用
随机生成的密钥和对称的
密码加密数据,之后应该使用RSA,$ b加密
随机生成的密钥$ b然后发送加密的数据和
加密的随机密钥到另一个
结束,他们可以逆转过程
(即使用
解密随机密钥他们的RSA私人键,然后解密
数据)。

The RSA implementation that ships with Bouncy Castle only allows the encrypting of a single block of data. The RSA algorithm is not suited to streaming data and should not be used that way. In a situation like this you should encrypt the data using a randomly generated key and a symmetric cipher, after that you should encrypt the randomly generated key using RSA, and then send the encrypted data and the encrypted random key to the other end where they can reverse the process (ie. decrypt the random key using their RSA private key and then decrypt the data).

这篇关于RSA块的太多数据失败。什么是PKCS#7?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆