如何通过在 java 中指定不同的输入来生成有效的 RSA 1024 位 public 和私钥?
How can I generate valid RSA 1024 bits public and private keys by specifying different inputs in java?
(如果您不熟悉这个问题,请跳至 编辑、编辑 部分)
我可以使用以下代码生成随机有效的 RSA 1024 位 public 和私钥:
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
以上代码中的注释给出了调试器的详细信息。
我不想随机生成 public 和私钥,而是指定输入以生成有效密钥。类似于(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 位 public 和私钥?
编辑,回复罗伯特:
是的,我希望使用用户定义的值创建 public 和私钥,而不是随机的。为了回应您提供的link,我写了这个:
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);
我创建了随机密钥,然后将我为 public 密钥获得的指数和模数的值放入变量 q 和 g 以上。我得到相同的 public 密钥,但我没有得到相同的私钥。我尝试添加另一个大素数,而不是 q 但我并没有真正得到我期望的答案。调试器显示出差异。如何创建有效的 public 和私钥?
EDIT, EDIT, 回复 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 :(
私钥不一样,这是怎么回事?
您将 public 指数传递给 RSAPublicKeySpec
和 RSAPrivateKeySpec
,这是错误的。 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);
(如果您不熟悉这个问题,请跳至 编辑、编辑 部分)
我可以使用以下代码生成随机有效的 RSA 1024 位 public 和私钥:
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
以上代码中的注释给出了调试器的详细信息。
我不想随机生成 public 和私钥,而是指定输入以生成有效密钥。类似于(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 位 public 和私钥?
编辑,回复罗伯特:
是的,我希望使用用户定义的值创建 public 和私钥,而不是随机的。为了回应您提供的link,我写了这个:
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);
我创建了随机密钥,然后将我为 public 密钥获得的指数和模数的值放入变量 q 和 g 以上。我得到相同的 public 密钥,但我没有得到相同的私钥。我尝试添加另一个大素数,而不是 q 但我并没有真正得到我期望的答案。调试器显示出差异。如何创建有效的 public 和私钥?
EDIT, EDIT, 回复 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 :(
私钥不一样,这是怎么回事?
您将 public 指数传递给 RSAPublicKeySpec
和 RSAPrivateKeySpec
,这是错误的。 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);