如何使用另一个RSAKey加密RSAKey?

时间:2010-05-27 19:16:36

标签: java encryption rsa

我知道这不是通常的事情。但是我正在实施的规范是这样描述的,我不能用完。

我试图加密私钥的模数和指数,但是下面的测试代码引发了异常,因为字节数组比RSA块允许的最大值大1个字节:

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;

import javax.crypto.Cipher;

import org.apache.commons.lang.ArrayUtils;

public class TEST {

    public static KeyPair generateKeyPair() throws NoSuchAlgorithmException, NoSuchProviderException {
 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA", "BC");
 keyPairGenerator.initialize(1024);
 return keyPairGenerator.generateKeyPair();
    }

    public static void main(String[] args) throws Exception {

 KeyPair keyPair = generateKeyPair();
 RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();

 System.out.println("Priv modulus len = " + privateKey.getModulus().bitLength());
 System.out.println("Priv exponent len = " + privateKey.getPrivateExponent().bitLength());
 System.out.println("Priv modulus toByteArray len = " + privateKey.getModulus().toByteArray().length);

 byte[] byteArray = privateKey.getModulus().toByteArray();
 // the byte at index 0 have no value (in every generation it is always zero)
 byteArray = ArrayUtils.subarray(byteArray, 1, byteArray.length);

 System.out.println("byteArray size: " + byteArray.length);

 RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
 Cipher cipher = Cipher.getInstance("RSA", "BC");
 cipher.init(Cipher.ENCRYPT_MODE, publicKey);
 byte[] encryptedBytes = cipher.doFinal(byteArray);

 System.out.println("Success!");
    }

}

(只是一个测试,我永远不会用它的公钥加密私钥)

字节数组是128字节,RSA块允许的确切最大值,为什么会出现异常?以及如何解决它?

编辑:如果我使用1023(而不是1024)启动密钥对生成器,它可以工作,但不是通常的RSA密钥大小1024?

6 个答案:

答案 0 :(得分:2)

第一:有人编写了这个规范。与他们核实而不是问我们。他们有一些理由来编写这个要求,你需要知道它是什么。当面对不明确的要求时,你可以做的最糟糕的事情就是开始猜测 - 尤其是在处理加密时。

第二:在您的测试代码中,您正在加密私钥模数。模数在RSA加密系统中并不是秘密,因此不需要加密。您没有尝试加密私有指数(这是实际的秘密部分)。私有指数总是小于模数,因此您应该能够使用原始RSA操作对其进行加密(如果确保删除前置零)。这应该是安全的(翻译:我没有看到任何明显的攻击,考虑它30秒) - 如果是非标准的。

编辑:正如GregS在评论中指出的那样,您无法确定要加密的密钥的私有指数是否小于要用于加密的密钥的模数。我认为大约25%的时间就是这种情况。所以请改用下面的方法。

更好的方法(完全标准,我怀疑是规范编写者实际上打算)将使用通常的混合方法加密私钥:生成对称密钥,用它来加密私钥(这里可以使用标准的序列化格式而不必担心长度),使用其他公钥(使用RSA / PKCS#1)加密对称密钥,并将两个加密传输给执行相反的接收方步骤。

答案 1 :(得分:1)

您确定需要这样做吗?大多数人使用RSA密钥加密对称密钥,但在RSA内部加密RSA并不会给你带来任何好处。

RSA可以加密明文的最大大小

  (key_size/8) - 11 bytes

因此,您只能为1024位密钥加密117个字节。您需要使用更大的密钥来加密更小的密钥。

答案 2 :(得分:1)

如果您绝对想要使用自己的加密协议(这通常不是一个好主意),那么您可以将公钥(即模数N和公钥e)保持为明文,并简单地加密其中一个因素N由于对于1024位模数,facotors大约是512位,因此加密应该没有问题。了解其中一个因素和公钥足以确定私钥的剩余部分。

答案 3 :(得分:0)

PKCS#1方法添加了11个字节的校验和和填充,因此您的最大纯文本大小将为117个字节。见Too much data for RSA block fail. What is PKCS#7?

答案 4 :(得分:0)

您可以在RSA中加密的数据量等于密钥大小 - 11个字节。如果要存储更多数据,则应将密钥大小从1024增加。

答案 5 :(得分:0)

我看到的答案是(几乎隐藏)在项目的规范中。它通过部分加密rsa密钥,并连接部分。解密相同(当然,大小需要是加密器和解密器已知的默认大小)。这样我就可以在没有任何对称密钥的情况下使用RSA(不是说我同意这是最好的加密方法)。

对不起给大家带来麻烦(我试图删除这个问题,但现在无法删除)。