我记得很久以前用OpenSSL做过这件事,但我想知道是否可能以及如何在Java中使用密码学。
我记得很久以前用OpenSSL做过这件事,但我想知道是否可能以及如何在Java中使用密码学。
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);
}
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);
RSAPublicKeySpec publicKeySpec = new java.security.spec.RSAPublicKeySpec(privk.getModulus(), privk.getPublicExponent());
您无法直接从另一个密钥生成任何一种密钥,这在数学上是不可能的。如果您有一个包含公钥和私钥的密钥 blob,您可以相对容易地提取其中的任何一个。
编辑,2017年: 经过多年的发展和更好的加密理解,现在我明白这个答案并不完全正确。
引用维基百科的话:
公钥由模数n和公共(或加密)指数e组成。私钥由模数n和私有(或解密)指数d组成,必须保密。p、q和λ(n)也必须保密,因为它们可用于计算d。
公共模数n可以计算为p×q。原始私钥唯一缺少的是e值,但此值通常选择为65537,如果没有,您仍然可以从d和λ(n)计算出e。
但是,许多私钥存储格式实际上将公共模数n与其他组件一起包含在内,因此您可以直接提取这些值。
编辑,2018年:我仍然因为这个回答而受到负评,这是正确的!我保留这个回答,让人们看到我最初的错误,并提醒自己将来不要再犯错。