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

时间:2018-04-21 16:57:35

标签: java rsa

(如果您对该问题不熟悉,请跳至编辑,编辑部分)

我可以使用以下代码生成随机有效的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

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

我不想随机生成公钥和私钥,而是指定输入以生成有效密钥。类似于(link的内容在下面的评论中):

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);

我创建了随机密钥,然后将上面的变量 q g 中的公钥的指数和模数值。我得到相同的公钥但我没有获得相同的私钥。我尝试添加另一个大素数,而不是 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 :(

私钥是不同的,这里发生了什么?

1 个答案:

答案 0 :(得分:1)

您正在将公开指数传递给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);