我有一个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。根据我的想法,解密可能与翻转位有关,但会导致错误的解密明文。我必须翻转才能实现这一目标?任何建议都是最受欢迎的。
答案 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)。