我需要在Java中使用非对称加密。我使用openssl生成带有自定义密码的.key和.crt文件,详情请参考http://www.imacat.idv.tw/tech/sslcerts.html 。
如何使用这些.key和.crt文件从Java中提取公钥和私钥?
我需要在Java中使用非对称加密。我使用openssl生成带有自定义密码的.key和.crt文件,详情请参考http://www.imacat.idv.tw/tech/sslcerts.html 。
如何使用这些.key和.crt文件从Java中提取公钥和私钥?
你的.key
和.crt
文件可能是PEM格式的。要检查这一点,请使用文本编辑器打开它们并检查内容是否类似于------BEGIN CERTIFICATE------
(或 "begin RSA private key" ...)。这通常是OpenSSL使用的默认格式,除非您明确指定了DER格式。
虽然可能不是必需的(请参见下文),但如果您的证书采用DER格式(二进制格式),您可以使用以下命令将其转换为PEM格式:
openssl x509 -inform DER -in cert.crt -outform PEM -out cert.pem
(如果需要,可以检查有关使用私钥进行类似操作的帮助,具体请参考openssl rsa
。)
随后您将获得两个选项:
构建PKCS#12文件
openssl pkcs12 -export -in myhost.crt -inkey myhost.key -out myhost.p12
你可以将其直接用作Java中的“PKCS12”类型密钥库。大多数Java应用程序应该允许您在文件位置之外指定密钥库类型。对于默认的系统属性,可以使用javax.net.ssl.keyStoreType
来完成此操作(但您使用的应用程序可能未使用此选项)。否则,如果需要显式加载它,请使用以下代码:KeyStore ks = KeyStore.getInstance("PKCS12");
FileInputStream fis =
new FileInputStream("/path/to/myhost.p12");
ks.load(fis, "password".toCharArray()); // There are other ways to read the password.
fis.close();
然后,您应该能够遍历KeyStore
的aliases()
并使用getCertificate
(然后对于公钥使用getPublicKey()
)和getKey()
。
FileReader fr = ... // Create a FileReader for myhost.crt
PEMReader pemReader = new PEMReader(fr);
X509Certificate cert = (X509Certificate)pemReader.readObject();
PublicKey pk = cert.getPublicKey();
// Close reader...
对于私钥,如果它有密码保护,您需要实现一个PasswordFinder
(请参见PEMReader doc中的链接)来构建 PEMReader
。 (您需要将 readObject()
的结果强制转换为 Key
或 PrivateKey
。)public static byte[] pemToPKCS12(final String keyFile, final String cerFile, final String password) throws Exception {
// Get the private key
FileReader reader = new FileReader(keyFile);
PEMReader pem = new PEMReader(reader, new PasswordFinder() {
@Override public char[] getPassword() {
return password.toCharArray();
}
});
PrivateKey key = ((KeyPair)pem.readObject()).getPrivate();
pem.close();
reader.close();
// Get the certificate
reader = new FileReader(cerFile);
pem = new PEMReader(reader);
X509Certificate cert = (X509Certificate)pem.readObject();
pem.close();
reader.close();
// Put them into a PKCS12 keystore and write it to a byte[]
ByteArrayOutputStream bos = new ByteArrayOutputStream();
KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(null);
ks.setKeyEntry("alias", (Key)key, password.toCharArray(), new java.security.cert.Certificate[]{cert});
ks.store(bos, password.toCharArray());
bos.close();
return bos.toByteArray();
}
请看org.bouncycastle.crypto.generators.OpenSSLPBEParametersGenerator。
getKey()
。当使用PKCS#12格式时,密钥的密码与存储本身的密码相同。 - BrunoPEMReader
并不总是必要的,这取决于你需要读取什么。如果只是为了证书,可以尝试使用CertificateFactory
(JSSE的一部分)。请参见此处的示例和此处的注意事项(该评论可能会有用)。 - Bruno