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

How to extract the private exponent from PKCS#8 format in Java?

我有一个 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 Bits(有时会有点不同)。我需要知道包含哪些位(可能是 2048)代表私人秘密。我试图通过查看 RFC5208 来找出它的结构,但我找不到任何相关信息。我还尝试将私有指数 rsaPrivateKey.getPrivateExponent() 与整个私钥 new BigInteger(rsaPrivateKey.getEncoded()) 进行比较,但找不到任何相似之处。

但是,当我开始翻转随机位时,要么解密无论如何都有效,要么我得到 BadPaddingExceptions。以我的思维方式,解密可能适用于翻转位,但会导致错误的解密明文。我必须翻转哪些位才能实现这一目标?欢迎提出任何建议。

我知道你想做的是获取一个现有的 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);

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