X.509
X.509证书包含3个文件:
- key:服务器上的私钥,用于对发送给客户的数据进行加密,以及对客户用公钥发回的数据进行解密;
- csr:证书签名请求文件,用于提交给证书颁发机构(CA)对证书签名;
- crt:由CA颁发机构签名,或者自签名的证书,包括持有者的公钥、持有者信息、签署人签名等;
其他格式
- PFX(Predecessor of PKCS#12) 证书,等价于CRT+私钥key,多用于IIS;
- JKS(Java Key Storage)证书,等价于CRT+私钥key,用java的keytool生成,多用于tomcat
- PEM(Privacy Enhanced Mail)证书,等价于CRT+私钥key,纯文本格式,多用于apache和nginx
- 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());
流程(正规流程)
- 创建一个私钥
openssl genrsa -des3 -out www.fredric.com.key 4096- 开始基于这个私钥再创建一个证书签名请求文件
openssl req -new -key www.fredric.com.key -out www.fredric.com.csr
这个创建的过程会包括国家、企业部门等- 填写信息后完成对csr文件的创建
openssl req -noout -text -in www.fredric.com.csr- 向某个CA机构提交csr文件申请证书
- 申请通过后,下载CRT证书并配置到自己的nginx或者tomcat下;
流程(自签名)
区别主要在生成csr后,用自己的私钥签名一个证书
- 生成自签名证书
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
流程(创建私有CA)
- 创建CA的私钥
openssl genrsa -des3 -out ca.key 4096- 生成CA的自签名证书
openssl req -new -x509 -days 365 -key ca.key -out ca.crt- 下面的工作在待配置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可以对证书进行签发。
- 生成服务端签名证书
keytool -genkey -alias test -keypass 123456 -keyalg RSA -keysize 1024 -validity 365 -keystore test.keystore -storepass 123456- 生成客户端签名证书
keytool -genkey -alias client -keypass 123456 -keyalg RSA -keysize 1024 -validity 365 -storetype PKCS12 -keystore client.p12 -storepass 123456- 服务端信任客户端证书
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.1 导出CER文件
keytool -keystore test.keystore -export -alias test -file test.cer
4.2 双击CER安装证书- 在tomcat配置里增加 test.keystore
双向认证策略举例
- 服务端生成一个SSL秘钥对
keytool -genkeypair -v- 导出服务端的公钥
keytool -export **.jks- 客户端生成一个秘钥对
keytool -genkeypair -v- 将服务端公钥导入客户端证书
keytool --importcert- 导出客户端的公钥
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中的字符串就可以。
- 在消息传输时,客户端带服务端和客户端自己的公钥(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);
- 在java 语言的编程中也可以直接采用jks文件,个人理解这个jks证书里包含了服务端的公钥和客户端的公钥;