【问题标题】:How to encrypt a RSAKey using another RSAKey?如何使用另一个 RSAKey 加密 RSAKey?
【发布时间】:2011-02-24 19:59:33
【问题描述】:

我知道这不是通常的做法。但是我正在实现的规范是这样描述的,我不能用完。

我试图加密私钥的模数和指数,但以下测试代码引发异常,因为字节数组比 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!");
    }

}

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

字节数组是 128 字节,正好是 RSA 块所允许的最大值,那么为什么会出现异常呢?以及如何解决?

编辑:如果我用 1023(而不是 1024)初始化密钥对生成器,它可以工作,但 RSA 密钥大小不是 1024 的通常情况吗?

【问题讨论】:

  • 它也不适用于 1023。
  • 为什么要加密无论如何都是公开的模数 byte[] byteArray = privateKey.getModulus().toByteArray();我认为你应该自己加密指数:privateKey.getPrivateExponent().toByteArray()
  • @GregS 正如我所说,它有效.. 你试过了吗?
  • @Krystian 我想我需要指数和模数来恢复密钥。
  • @Tom Brito:是的,我试过了。您的代码有一个错误(您丢弃了模数的高字节),这意味着它不会抛出异常,但它也不会工作。

标签: java encryption rsa


【解决方案1】:

首先:有人编写了这个规范。与他们核对而不是询问我们。他们有一些理由写这个要求,你需要知道它是什么。当面临一个不清楚的要求时,你能做的最糟糕的事情就是开始猜测——尤其是在处理密码学时。

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

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

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

【讨论】:

  • +1 如果规范不是很清楚,最好问两次。但是,原始 RSA 操作永远不应该单独使用,除非您使用适当的填充方法,如 OAEP,否则它是不安全的。
  • @Krystian:我意识到最好总是使用适当的填充,但在这种情况下(消息值大,消息空间大,没有解密-oracle 的机会)它实际上应该是与 PKCS#1-padding 一样安全。我忽略了什么吗?
  • @Rasmus:好吧,我手头没有任何攻击,但由于代数结构,我会害怕使用它。您的加密密钥将是 d1^e2 mod N2 ,其中 (e1,d1,N1) 是第一个 RSA 的参数,而 (e2,d2,N2) 是外部加密的参数。我们知道 e1,N1, e2,N2。我猜根据 N1、N2、e1、e2 的相对值,可能会有一些技巧会做一些讨厌的事情……我见过太多聪明的攻击,无法忽视这种可能性。
  • 你对指数的看法是正确的,它适合这个块,所以谢谢。
  • 私有指数总是小于它的模数,不一定是别人的。
【解决方案2】:

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

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

  (key_size/8) - 11 bytes

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

【讨论】:

  • 是的,很遗憾我需要加密私钥。我认为如果我加密模数和指数会起作用,模数是问题,但如果我用 1023 初始化密钥生成器,它会起作用。但规范说 RSA 的大小必须为 1024。
【解决方案3】:

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

【讨论】:

  • 我不想使用自己的加密协议,我想使用 RSA。 (实际上,我必须)
【解决方案4】:

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

【讨论】:

  • 我刚刚添加了这个问题:如果我用 1023 而不是 1024 初始化密钥生成器,它可以工作,所以我认为这 11 个字节不是问题......但我不是确定它是否正确,用 1023 初始化它。
  • 那么,我如何修改上面的代码以使用 PKCS#1 并且最大大小为 117 字节? (这个尺寸很合适)
  • 抱歉,我很困惑。如果你不使用填充,你只需要确保消息满足 0
  • 当我使用 java 密钥生成器生成密钥时,我不知道 p、q 和 n 值(在我的示例代码中)怎么办?
  • 您需要使用更长的新公钥加密它,而不是旧的。
【解决方案5】:

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

【讨论】:

  • 奇怪的是,如果我减小大小(到 1023),则不会引发异常。我不知道为什么。
【解决方案6】:

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

麻烦各位了(我想删除这个问题,但现在无法删除)。

【讨论】:

  • 请考虑在投票时发表评论。
猜你喜欢
  • 1970-01-01
  • 2017-08-29
  • 1970-01-01
  • 2017-08-28
  • 2017-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多