创建 Android 上使用的自签名证书
太阳火神的美丽人生 (http://blog.csdn.net/opengl_es)
本文遵循“署名-非商业用途-保持一致”创作公用协议
创建 Android 上使用的自签名证书
Creating self-signed certificates for use on Android
24 NOVEMBER 2011 // MARCUS KRANTZ
我刚刚在 Android 上开始实现 TLS/SSL 双向认证。如何实际在 Android 上实现这一功能已在我的另一篇文章 Android - TLS/SSL Mutual Authentication 中提到。在这个实现可以落实之前,密钥和证书的准备就显得很重要了。本文演示了如何创建这些东西。然而,本文不只适用于 Android ,同时也应该可以用于其它情况。
A while ago I started to implement TLS/SSL mutual authentication on Android. How to actually implement the functionality on the Android platform is covered in my other article Android - TLS/SSL Mutual Authentication. Before such implementation can be done, it is important to have the keys and certificates prepared. In this article demonstrate how you can create these. However, this article is not just applicable to Android and should be usable in other scenarios as well.
本文想要发挥作用,必需的工具有:openssl,Java 的 Keytool 和 BouncyCastle-provider 。还有一些强烈推荐的资源也很有用:
For this article to be useful, the required tools are: openssl, Java’s Keytool and the BouncyCastle-provider. There are also some resources that I strongly recommend and has been very useful:
有人可能会问,为什么我不使用 keytool 生成密钥和证书,这样就马上能有的用了。噢,我有非常强烈的求知欲望,我想学到更多有关 openssl 以及如何处理各种格式密钥和证的知识。
One might argue why I don’t use keytool to generate the keys and certificates and use them right away. Well, I was very curious about learning more about openssl and how to deal with various formats of keys and certificates.
1. 创建私钥(CREATE PRIVATE KEYS)
来,咱们从头开始。首先,我们需要私钥。我们使用 openssl 创建:
Let’s start from scratch. First of all we need private keys. We use openssl to create these:
$ openssl genrsa -des3 -out client_key.pem 2048
$ openssl genrsa -des3 -out server_key.pem 2048
这两行命令会创建两个密钥:client.pem
和 server.pem
。我们在下一步中会用它们来签名我们的证书。通常情况下,我们会创建一个 CA 签名请求,再把它发送给 CA,CA就会给你颁发证书了。但是,由于我想要自签名我们的证书,签名请求这一步就显得多余了。
This will create the two keys; client.pem
and server.pem
. We will use these in the next step to sign our certificates with. In normal cases we would create a CA-signing request, that is sent to a CA who will issue your certificates. But since we want to self-sign our certificates this step is redundant.
2. 创建自签名证书(CREATE SELF-SIGNED CERTIFICATES)
$ openssl req -new -x509 -key client_key.pem -out client.pem -days 365
$ openssl req -new -x509 -key server_key.pem -out server.pem -days 365
另外,如果不想被提示输入证书的主题行,你也可以给 openssl req 命令传递一个 -subj 参数。刚执行的两条命令主要是创建一个 CA 签名请求并使用我们的私钥来签名输出的 x509 证书。该证书就会以 pem 格式进行编码,并且有效期为 365 天。
Additionally, instead of being prompted for the certificate’s subject line you can use the -subj
parameter and pass it to the openssl req
command. What we just did was basically creating a CA signing request using our private keys to sign the outgoing x509-certificates. The certificates will be coded in pem-format and valid for 365 days.
3. 创建可信库(CREATE TRUST STORES)
为了能在 Java 应用中使用我们的密钥和证书,我们需要将它们导入到密钥库里。首先,我们想让客户端信任服务器证书。要做到这一点,我们必须创建一个客户端可信库,并导入服务器的证书。
In order to use our keys and certificates in Java applications we need to import them into keystores. First of all, we want the client to trust the server certificate. To do this we must create a client trust store and import the server’s certificate.
$ keytool –importcert -trustcacerts
–keystore clienttruststore.bks –storetype bks –storepass <truststore_password> -file server.pem -provider org.bouncycastle.jce.provider.BouncyCastleProvider –providerpath <path_to_bcprov_jar>
注意(Note):
在客户端,我们当前的情况是一个 Android 应用,我们使用 Bouncy Castle 作为我们的提供者,因为它能被 Android 平台支持。
On the client side, which in our case will be an Android app we use Bouncy Castle as our provider since it is supported on the Android platform.
(以下命令用于)创建一个服务器可信库,并将客户端的证书导入。
Create a trust store for the server and import the client’s certificate into it.
$ keytool –importcert -trustcacerts –keystore servertruststore.jks –storetype jks –storepass <server_truststore_password> -file client.pem
当前,我们已经有了两个可信库,一个是服务器的,其中导入了客户端的证书,一个是客户端的,其中导入了服务器的证书。
Currently, we have two trust stores one for the server in which we imported the client’s certificate and one for the client in which we imported the server’s certificate.
4. 合并密钥和证书(COMBINE KEYS AND CERTIFICATES)
Java 的 keytool 工具有一个问题,它无法做到让我们把一个已存在的私钥导入到密钥库这样简单的事情。这个问题的一个变通方案是,把私钥和证书合并到一个 pkcs12 文件中(这个文件格式能被 Java 的 keytool 识别),然后再把这个 pkcs12 密钥库导入(译者注:译作‘转换成’可能更好,这表示里面是密钥和证书而非这个 pkcs12 密钥库,是赋值关系而非嵌套关系)到常规的密钥库。
A problem with Java’s keytool application is that it won’t let us do such a simple thing as importing an existing private key into a keystore. The workaround to this problem is to combine the private key with the certificate into a pkcs12-file (which is understood by Java’s keytool) and then import this pkcs12 keystore into a regular keystore.
分别组合服务器和客户端的证书和私钥:
Combine the certificate and the private key for the server and client respectively:
$ openssl pkcs12 –export –inkey client_key.pem –in client.pem –out client.p12
$ openssl pkcs12 –export –inkey server_key.pem –in server.pem –out server.p12
5. 转换 PKCS12 到支持的库类型(CONVERT FROM PKCS12)
Import the created keystores to new ones with common formats:
$ keytool –importkeystore –srckeystore client.p12 –srcstoretype pkcs12 –destkeystore client.bks –deststoretype bks –provider org.bouncycastle.jce.provider.BouncyCastleProvider –providerpath <path_to_bcprov_jar>
$ keytool –importkeystore –srckeystore server.p12 –srcstoretype pkcs12 –destkeystore server.jks –deststoretype jks
We should now have all files we need for a successful TLS/SSL mutual authentication. The files we move to our Android project will be: clienttruststore.bks
and client.bks
. The files we move to our server will be: servertruststore.jks
and server.jks
.