将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.pemcert2.pempkey.pem

使用openssl和以下语法将pkey.pem转换为DER格式:

openssl pkcs8 -topk8 -nocrypt -in pkey.pem -inform PEM -out pkey.der -outform DER

注意,如果私钥是encryption的,你需要提供一个密码(从原pem文件的供应商处获得)以转换为DER格式, openssl会询问你这样的密码:“为pkey.peminput一个密码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,它只是工作:

  1. 转到您最喜爱的浏览器并从安全网站下载主要证书。
  2. 执行以下两行代码:

     openssl x509 -outform der -in GlobalSignRootCA.crt -out GlobalSignRootCA.der keytool -import -alias GlobalSignRootCA -keystore GlobalSignRootCA.jks -file GlobalSignRootCA.der 
  3. 如果在Java SE环境中执行,请添加以下选项:

     java -Djavax.net.ssl.trustStore=GlobalSignRootCA.jks -Djavax.net.ssl.trustStorePassword=trustStorePassword -jar MyJar.jar 
  4. 或者将以下内容添加到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