在Java中从私有获取公钥

我记得很久以前用OpenSSL这么做了,但我想知道它是否可能以及如何,我从来没有在java上使用过Cryptography。

您无法直接从另一个生成任一键。 这在数学上是不可能的。 如果你有一个包含公钥和私钥的密钥blob,你可以相对容易地提取其中一个。

2017编辑:很多年以后对加密的理解要好得多,现在我很清楚这个答案并不正确。

引用维基百科:

公钥由模数n和公共(或加密)指数e组成。 私钥由模数n和私有(或解密)指数d组成,它必须保密。 p,q和λ(n)也必须保密,因为它们可用于计算d。

公共模数n可以计算为p×q。 原始私钥中唯一缺少的是e,但是这个值通常被选为65537,如果不是,你仍然可以从d和λ(n)计算e。

但是,许多私钥存储格式实际上包含公共模数n和其他组件,因此您可以直接提取值。

编辑,2018年:仍然得到这个,这是正确的! 我正在离开这个答案,所以人们可以看到我原来错的原因,并提醒自己将来不要错。

我们假设我们正在讨论RSA私钥和公钥。 然后,如果您使用的是PEM格式文件,那么首先需要将文件中的私钥读入PrivateKey对象:

public PrivateKey readPemRsaPrivateKey(String pemFilename) throws java.io.IOException, java.security.NoSuchAlgorithmException, java.security.spec.InvalidKeySpecException { String pemString = File2String(pemFilename); pemString = pemString.replace("-----BEGIN RSA PRIVATE KEY-----\n", ""); pemString = pemString.replace("-----END RSA PRIVATE KEY-----", ""); byte[] decoded = Base64.decodeBase64(pemString); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decoded); KeyFactory kf = KeyFactory.getInstance("RSA"); return kf.generatePrivate(keySpec); } 

其中File2String是这样的:

  private static String File2String(String fileName) throws java.io.FileNotFoundException, java.io.IOException { File file = new File(fileName); char[] buffer = null; BufferedReader bufferedReader = new BufferedReader(new FileReader(file)); buffer = new char[(int)file.length()]; int i = 0; int c = bufferedReader.read(); while (c != -1) { buffer[i++] = (char)c; c = bufferedReader.read(); } return new String(buffer); } 

现在,您可以使用以下代码生成相应的PublicKey:

  import java.security.interfaces.RSAPrivateCrtKey; import java.security.spec.RSAPublicKeySpec; 

  PrivateKey myPrivateKey = readPemRsaPrivateKey(myPrivateKeyPemFileName); RSAPrivateCrtKey privk = (RSAPrivateCrtKey)myPrivateKey; RSAPublicKeySpec publicKeySpec = new java.security.spec.RSAPublicKeySpec(privk.getModulus(), privk.getPublicExponent()); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PublicKey myPublicKey = keyFactory.generatePublic(publicKeySpec); 

致谢: 如何通过提供私钥来获得RSA PublicKey?

请确保Eli Rosencruft答案基本正确,但模数和公共指数的顺序不正确! 这是正确的陈述:

 RSAPublicKeySpec publicKeySpec = new java.security.spec.RSAPublicKeySpec(privk.getModulus(), privk.getPublicExponent());