将PEM导入Java密钥库
我试图连接到一个SSL服务器,这需要我来validation自己。 为了在Apache MINA上使用SSL,我需要一个合适的JKS文件。 但是,我只给了一个.PEM文件。
我将如何去从PEM文件创build一个JKS文件?
首先,以DER格式转换您的证书:
openssl x509 -outform der -in certificate.pem -out certificate.der
之后,将其导入到密钥库中:
keytool -import -alias your-alias -keystore cacerts -file certificate.der
如果您只想将PEM格式的证书导入到密钥库中,那么keytool将执行该任务:
keytool -import -alias *alias* -keystore cacerts -file *cert.pem*
我开发了http://code.google.com/p/java-keyutil/ ,将PEM证书直接导入到Java密钥库中。 其主要目的是导入一个多部分的PEM操作系统证书包,如ca-bundle.crt。 这些通常包含keytool无法处理的标题
</self promotion>
在我的情况下,我有一个pem文件,其中包含两个证书和一个encryption的私钥用于相互SSLauthentication。 所以我的文件看起来像这样:
-----BEGIN CERTIFICATE----- ... -----END CERTIFICATE----- -----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: DES-EDE3-CBC,C8BF220FC76AA5F9 ... -----END RSA PRIVATE KEY----- -----BEGIN CERTIFICATE----- ... -----END CERTIFICATE-----
这是我做的
将文件分成三个单独的文件,每个文件只包含一个条目,从---BEGIN..
开始,以---END..
行---END..
。 让我们假设我们现在有三个文件: cert1.pem
, cert2.pem
和pkey.pem
。
使用openssl和以下语法将pkey.pem
转换为DER格式:
openssl pkcs8 -topk8 -nocrypt -in pkey.pem -inform PEM -out pkey.der -outform DER
注意,如果私钥是encryption的,你需要提供一个密码(从原pem文件的供应商处获得)以转换为DER格式, openssl
会询问你这样的密码:“为pkey.pem
input一个密码pkey.pem
:“。
如果转换成功,您将得到一个名为pkey.der
的新文件。
创build一个新的Java密钥库并导入私钥和证书:
String keypass = "password"; // this is a new password, you need to come up with to protect your java key store file String defaultalias = "importkey"; KeyStore ks = KeyStore.getInstance("JKS", "SUN"); // this section does not make much sense to me, // but I will leave it intact as this is how it was in the original example I found on internet: ks.load( null, keypass.toCharArray()); ks.store( new FileOutputStream ( "mykeystore" ), keypass.toCharArray()); ks.load( new FileInputStream ( "mykeystore" ), keypass.toCharArray()); // end of section.. // read the key file from disk and create a PrivateKey FileInputStream fis = new FileInputStream("pkey.der"); DataInputStream dis = new DataInputStream(fis); byte[] bytes = new byte[dis.available()]; dis.readFully(bytes); ByteArrayInputStream bais = new ByteArrayInputStream(bytes); byte[] key = new byte[bais.available()]; KeyFactory kf = KeyFactory.getInstance("RSA"); bais.read(key, 0, bais.available()); bais.close(); PKCS8EncodedKeySpec keysp = new PKCS8EncodedKeySpec ( key ); PrivateKey ff = kf.generatePrivate (keysp); // read the certificates from the files and load them into the key store: Collection col_crt1 = CertificateFactory.getInstance("X509").generateCertificates(new FileInputStream("cert1.pem")); Collection col_crt2 = CertificateFactory.getInstance("X509").generateCertificates(new FileInputStream("cert2.pem")); Certificate crt1 = (Certificate) col_crt1.iterator().next(); Certificate crt2 = (Certificate) col_crt2.iterator().next(); Certificate[] chain = new Certificate[] { crt1, crt2 }; String alias1 = ((X509Certificate) crt1).getSubjectX500Principal().getName(); String alias2 = ((X509Certificate) crt2).getSubjectX500Principal().getName(); ks.setCertificateEntry(alias1, crt1); ks.setCertificateEntry(alias2, crt2); // store the private key ks.setKeyEntry(defaultalias, ff, keypass.toCharArray(), chain ); // save the key store to a file ks.store(new FileOutputStream ( "mykeystore" ),keypass.toCharArray());
(可选)validation新密钥库的内容:
$ keytool -list -keystore mykeystore -storepass password
密钥库types:JKS密钥库提供者:SUN
您的密钥库包含3个条目:
-
cn = …,ou = …,o = ..,2014年9月2日,trustedCertEntry,证书指纹(SHA1):2C:B8:…
-
importkey,2014年9月2日,PrivateKeyEntry,证书指纹(SHA1):9C:B0:…
-
cn = …,o = ….,2014年9月2日,trustedCertEntry,证书指纹(SHA1):83:63:…
(可选)根据您的SSL服务器从您的新密钥库中testing您的证书和私钥:(您可能希望启用debugging作为VM选项:-Djavax.net.debug = all)
char[] passw = "password".toCharArray(); KeyStore ks = KeyStore.getInstance("JKS", "SUN"); ks.load(new FileInputStream ( "mykeystore" ), passw ); KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); kmf.init(ks, passw); TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmf.init(ks); TrustManager[] tm = tmf.getTrustManagers(); SSLContext sclx = SSLContext.getInstance("TLS"); sclx.init( kmf.getKeyManagers(), tm, null); SSLSocketFactory factory = sclx.getSocketFactory(); SSLSocket socket = (SSLSocket) factory.createSocket( "192.168.1.111", 443 ); socket.startHandshake(); //if no exceptions are thrown in the startHandshake method, then everything is fine..
最后,如果打算使用它,请使用HttpsURLConnection注册您的证书:
char[] passw = "password".toCharArray(); KeyStore ks = KeyStore.getInstance("JKS", "SUN"); ks.load(new FileInputStream ( "mykeystore" ), passw ); KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); kmf.init(ks, passw); TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmf.init(ks); TrustManager[] tm = tmf.getTrustManagers(); SSLContext sclx = SSLContext.getInstance("TLS"); sclx.init( kmf.getKeyManagers(), tm, null); HostnameVerifier hv = new HostnameVerifier() { public boolean verify(String urlHostName, SSLSession session) { if (!urlHostName.equalsIgnoreCase(session.getPeerHost())) { System.out.println("Warning: URL host '" + urlHostName + "' is different to SSLSession host '" + session.getPeerHost() + "'."); } return true; } }; HttpsURLConnection.setDefaultSSLSocketFactory( sclx.getSocketFactory() ); HttpsURLConnection.setDefaultHostnameVerifier(hv);
我总是忘记如何做到这一点,因为这是一个偶尔的事情,这是一个可能的解决scheme,它只是工作:
- 转到您最喜爱的浏览器并从安全网站下载主要证书。
-
执行以下两行代码:
openssl x509 -outform der -in GlobalSignRootCA.crt -out GlobalSignRootCA.der keytool -import -alias GlobalSignRootCA -keystore GlobalSignRootCA.jks -file GlobalSignRootCA.der
-
如果在Java SE环境中执行,请添加以下选项:
java -Djavax.net.ssl.trustStore=GlobalSignRootCA.jks -Djavax.net.ssl.trustStorePassword=trustStorePassword -jar MyJar.jar
-
或者将以下内容添加到java代码中:
System.setProperty("javax.net.ssl.trustStore", "GlobalSignRootCA.jks"); System.setProperty("javax.net.ssl.trustStorePassword","trustStorePassword");
步骤2的其他选项只是使用keytool。 贝娄一个证书链的例子:
keytool -import -file org.eu.crt -alias orgcrt -keystore globalsignrs.jks keytool -import -file GlobalSignOrganizationValidationCA-SHA256-G2.crt -alias globalsignorgvalca -keystore globalsignrs.jks keytool -import -file GlobalSignRootCA.crt -alias globalsignrootca -keystore globalsignrs.jks