如何从Java中的PKCS#8格式中提取私有指数?

时间:2015-07-08 10:41:10

标签: java rsa pkcs#8

我有一个PKCS#8格式的2048位RSAPrivateKey。我想翻转私有指数的单个位,以便有必要使用暴力。

这就是我创建密钥对的方式:

KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();

为了翻转位,我将密钥转换为Java.util.BitSet:

BitSet priv = BitSet.valueOf(keyPair.getPrivate().getEncoded());

输出的BitSet得到priv.size() = 9792位(有时它有点不同)。我需要知道哪些包含位(可能是2048)代表私人秘密。我试图通过查看RFC5208找出它的结构,但我找不到任何与位相关的信息。我还尝试将私有指数rsaPrivateKey.getPrivateExponent()与整个私钥new BigInteger(rsaPrivateKey.getEncoded())进行比较,但未发现任何相似之处。

然而,当我开始翻转随机位时,无论如何解密工作或我得到BadPaddingExceptions。根据我的想法,解密可能与翻转位有关,但会导致错误的解密明文。我必须翻转才能实现这一目标?任何建议都是最受欢迎的。

1 个答案:

答案 0 :(得分:2)

我收集你想要做的是拿一个现有的RSA私钥,弄乱私有指数,然后把结果带回RSA私钥进行进一步的实验。我不会使用getEncoded()方法,因为编码对象是复杂ASN.1结构的DER编码,并且您不想解析它以找到通往私有指数的路径。更好的方法是直接将私有指数提取为BigInteger。

以下是如何执行此操作以翻转第29位的一个示例。显然,您可以根据自己的需要量身定制。

        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(2048);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();

        BigInteger d = rsaPrivateKey.getPrivateExponent();

        // Flip some bits in d

        BigInteger newD = d.flipBit(29);

        // Make a new RSA private key with the modified private exponent

        RSAPrivateKeySpec newRSAPrivateSpec = new RSAPrivateKeySpec(rsaPrivateKey.getModulus(), newD);
        KeyFactory kf = KeyFactory.getInstance("RSA");
        RSAPrivateKey newPrivateKey = (RSAPrivateKey) kf.generatePrivate(newRSAPrivateSpec);

要记住的一件事是:当你只修改私有指数时,公共指数不再正确 - 实际上私有指数也可能是无效的。如果你想要一个有效的 RSA密钥对,你必须验证新的私有指数d是否满足GCD(d,phi(n))= 1,其中phi(n)=(p- 1)*(q-1)和p和q是你的RSA模数的两个主要因子,然后计算新的公共指数e = d -1 mod phi(n)。