如何通过在 java 中指定不同的输入来生成有效的 RSA 1024 位公钥和私钥?



(如果你对这个问题不熟悉,请跳转到编辑,编辑部分)

我可以使用以下代码生成随机有效的 RSA 1024 位公钥和私钥:

KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");    
keyPairGenerator.initialize(1024);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PublicKey publicKeyGenerated = keyPair.getPublic(); //Sun RSA public key, 1024 bits
PrivateKey privateKeyGenerated = keyPair.getPrivate(); //sun.security.rsa.RSAPrivateCrtKeyImpl@fffbfe07

上述代码中的注释提供了调试器的详细信息。

与其随机生成公钥和私钥,我想指定输入以生成有效密钥。类似的东西(链接在下面的评论中):

SecureRandom secureRandom = new SecureRandom();
BigInteger p = new BigInteger("41");
BigInteger q = new BigInteger("13");
BigInteger g = new BigInteger("17");
//http://www.javadocexamples.com/java_source/sun/security/provider/DSAKeyPairGenerator.java.html
//copying the methods generateKeyPair, generateX, generateY
KeyPair keyPair = generateKeyPair(p, q, g, secureRandom);
PublicKey publicKeyGenerated = keyPair.getPublic(); //Sun DSA Public Key
PrivateKey privateKeyGenerated = keyPair.getPrivate(); //DSAPrivateKey@fffa5e6a

使用上面的代码,我没有得到有效的RSA密钥,就像我的第一个例子一样。

如何通过在 java 中指定不同的输入来生成自己的有效 RSA 1024 位公钥和私钥?

编辑,回应罗伯特:

是的,我希望使用用户定义的值创建公钥和私钥,而不是随机的。为了回应您提供的链接,我写了以下内容:

BigInteger q = new BigInteger("114...15741");  //big prime number
BigInteger g = new BigInteger("65537"); //modulus
RSAPublicKeySpec publicSpec = new RSAPublicKeySpec(q, g);
RSAPrivateKeySpec privateSpec = new RSAPrivateKeySpec(q, g);
KeyFactory kf = KeyFactory.getInstance("RSA");
PublicKey publicKey = kf.generatePublic(publicSpec);
PrivateKey privateKey = kf.generatePrivate(privateSpec);

我创建了随机键,然后将我为公钥获得的指数和模值放在上面的变量qg中。我得到相同的公钥,但我没有得到相同的私钥。我尝试添加另一个大素数,而不是q,但我并没有真正得到我期望的答案。调试器显示差异。如何创建有效的公钥和私钥?

编辑,编辑响应mnistic之后

把事情拉得更靠拢一点

//randomly generate public and private keys
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");    
keyPairGenerator.initialize(1024);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PublicKey publicKeyGenerated = keyPair.getPublic(); //Sun RSA public key, 1024 bits
PrivateKey privateKeyGenerated = keyPair.getPrivate(); //sun.security.rsa.RSAPrivateCrtKeyImpl@fffbfe07
//pull out the exponents and modulus
BigInteger publicExponent = ((RSAPublicKey)keyPair.getPublic()).getPublicExponent();
BigInteger privateExponent = ((RSAPrivateKey)keyPair.getPrivate()).getPrivateExponent();
BigInteger modulus = ((RSAPublicKey)keyPair.getPublic()).getModulus();
//generate public and private keys using the above details
RSAPublicKeySpec publicSpec = new RSAPublicKeySpec(modulus, publicExponent);
RSAPrivateKeySpec privateSpec = new RSAPrivateKeySpec(modulus, privateExponent);
KeyFactory kf = KeyFactory.getInstance("RSA");
PublicKey publicKey = kf.generatePublic(publicSpec);
PrivateKey privateKey = kf.generatePrivate(privateSpec);
//check to see that the keys are the same
System.out.println((new BigInteger(publicKeyGenerated.getEncoded())).toString());
System.out.println((new BigInteger(publicKey.getEncoded())).toString());
System.out.println((new BigInteger(privateKeyGenerated.getEncoded())).toString());
System.out.println((new BigInteger(privateKey.getEncoded())).toString());
//the private keys are different :(

私钥不同,这是怎么回事?

您将公共指数传递给RSAPublicKeySpecRSAPrivateKeySpec,这是错误的。RSAPrivateKeySpec期望私有指数。如果要从第一个代码片段重新生成密钥,可以使用以下命令获取模数和指数:

BigInteger publicExponent = ((RSAPublicKey)keyPair.getPublic()).getPublicExponent();
BigInteger privateExponent = ((RSAPrivateKey)keyPair.getPrivate()).getPrivateExponent();
BigInteger modulus = ((RSAPublicKey)keyPair.getPublic()).getModulus();

然后使用以下命令重新生成密钥:

RSAPublicKeySpec publicSpec = new RSAPublicKeySpec(modulus, publicExponent);
RSAPrivateKeySpec privateSpec = new RSAPrivateKeySpec(modulus, privateExponent);
KeyFactory kf = KeyFactory.getInstance("RSA");
PublicKey publicKey = kf.generatePublic(publicSpec);
PrivateKey privateKey = kf.generatePrivate(privateSpec);

注意:要使私钥编码匹配,您可以尝试以下操作(使用RSAPrivateCrtKeySpec

BigInteger crtCoefficient = ((RSAPrivateCrtKey)keyPair.getPrivate()).getCrtCoefficient();
BigInteger primeExponentP = ((RSAPrivateCrtKey)keyPair.getPrivate()).getPrimeExponentP();
BigInteger primeExponentQ = ((RSAPrivateCrtKey)keyPair.getPrivate()).getPrimeExponentQ();
BigInteger p = ((RSAPrivateCrtKey)keyPair.getPrivate()).getPrimeP();
BigInteger q = ((RSAPrivateCrtKey)keyPair.getPrivate()).getPrimeQ();
BigInteger publicExponent = ((RSAPrivateCrtKey)keyPair.getPrivate()).getPublicExponent();
BigInteger privateExponent = ((RSAPrivateCrtKey)keyPair.getPrivate()).getPrivateExponent();
RSAPrivateCrtKeySpec crtKeySpec = new RSAPrivateCrtKeySpec(modulus, publicExponent, privateExponent, p, q, primeExponentP, primeExponentQ, crtCoefficient);
...
PrivateKey privateKey = kf.generatePrivate(crtKeySpec);

最新更新