X.509

X.509证书包含3个文件:

  1. key:服务器上的私钥,用于对发送给客户的数据进行加密,以及对客户用公钥发回的数据进行解密;
  2. csr:证书签名请求文件,用于提交给证书颁发机构(CA)对证书签名;
  3. crt:由CA颁发机构签名,或者自签名的证书,包括持有者的公钥、持有者信息、签署人签名等;

其他格式

  1. PFX(Predecessor of PKCS#12) 证书,等价于CRT+私钥key,多用于IIS;
  2. JKS(Java Key Storage)证书,等价于CRT+私钥key,用java的keytool生成,多用于tomcat
  3. PEM(Privacy Enhanced Mail)证书,等价于CRT+私钥key,纯文本格式,多用于apache和nginx
  4. CER证书,即windows下的CRT,通常linux或unix下为CRT;

获取公钥代码

CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate)cf.generateCertificate(new FileInputStream("my.cer"));
PublicKey publicKey = cert.getPublicKey();
BASE64Encoder base64Encoder=new BASE64Encoder();
String publicKeyString = base64Encoder.encode(publicKey.getEncoded());
流程(正规流程)
  1. 创建一个私钥
    openssl genrsa -des3 -out www.fredric.com.key 4096
  2. 开始基于这个私钥再创建一个证书签名请求文件
    openssl req -new -key www.fredric.com.key -out www.fredric.com.csr
    这个创建的过程会包括国家、企业部门等
  3. 填写信息后完成对csr文件的创建
    openssl req -noout -text -in www.fredric.com.csr
  4. 向某个CA机构提交csr文件申请证书
  5. 申请通过后,下载CRT证书并配置到自己的nginx或者tomcat下;
流程(自签名)

区别主要在生成csr后,用自己的私钥签名一个证书

  1. 生成自签名证书
    openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
流程(创建私有CA)
  1. 创建CA的私钥
    openssl genrsa -des3 -out ca.key 4096
  2. 生成CA的自签名证书
    openssl req -new -x509 -days 365 -key ca.key -out ca.crt
  3. 下面的工作在待配置https的服务器上完成
    3.1 生成服务端私钥
    openssl genrsa -des3 -out server.key 4096
    3.2 创建对应私有CA的证书签名请求文件
    openssl req -new -key server.key -out server.csr
    3.3.用CA证书给上一步的csr文件进行签名并生成服务器的证书
    openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt

备注:若双向认证则客户端也需要生成证书和私钥

keytool

keytool只能用来生成自签名的数字证书,而openssl可以对证书进行签发。

  1. 生成服务端签名证书
    keytool -genkey -alias test -keypass 123456 -keyalg RSA -keysize 1024 -validity 365 -keystore test.keystore -storepass 123456
  2. 生成客户端签名证书
    keytool -genkey -alias client -keypass 123456 -keyalg RSA -keysize 1024 -validity 365 -storetype PKCS12 -keystore client.p12 -storepass 123456
  3. 服务端信任客户端证书
    3.1 导出CER文件
    keytool -export -alias client -keystore client.p12 -storetype PKCS12 -keypass 123456 -file client.cer
    3.2 导入服务端证书库
    keytool -import -v -file client.cer -keystore test.keystore -storepass 123456
    备注:这里的keystore就是第一步的服务端生成证书
  4. 客户端信任服务端证书(如果需要双向)
    4.1 导出CER文件
    keytool -keystore test.keystore -export -alias test -file test.cer
    4.2 双击CER安装证书
  5. 在tomcat配置里增加 test.keystore
双向认证策略举例
  1. 服务端生成一个SSL秘钥对
    keytool -genkeypair -v
  2. 导出服务端的公钥
    keytool -export **.jks
  3. 客户端生成一个秘钥对
    keytool -genkeypair -v
  4. 将服务端公钥导入客户端证书
    keytool --importcert
  5. 导出客户端的公钥

5.1 由私钥生成公钥

openssl rsa -in $CLIENT_FILE_PREFIX.pem -out $CLIENT_FILE_PREFIX.nopass.pem -passin pass:$CLIENT_KEY_PASSWORD

5.2 截取字符串得到公钥

tail -n +$(($(grep -m1 -n -e '-----BEGIN CERTIFICATE' $CLIENT_FILE_PREFIX.pem | cut -d: -f1) )) \
  $CLIENT_FILE_PREFIX.pem >> $CLIENT_FILE_PREFIX.pub.pem

备注:由于PEM文件是纯文本格式,因此其公钥只要截取字符串BEGIN CERTIFICATE和END PUBLIC KEY中的字符串就可以。

  1. 在消息传输时,客户端带服务端和客户端自己的公钥(PEM证书)

6.1 单项认证(不需要客户端端公钥)

client.tls_set(ca_certs="mqttserver.pub.pem", certfile=None, keyfile=None, cert_reqs=ssl.CERT_REQUIRED,
                       tls_version=ssl.PROTOCOL_TLSv1, ciphers=None);

6.2 双向认证(需要客户端公钥)

client.tls_set(ca_certs="mqttserver.pub.pem", certfile="mqttclient.nopass.pem", keyfile=None, cert_reqs=ssl.CERT_REQUIRED,
                       tls_version=ssl.PROTOCOL_TLSv1, ciphers=None);
  1. 在java 语言的编程中也可以直接采用jks文件,个人理解这个jks证书里包含了服务端的公钥和客户端的公钥;