前言
通过OpenSSL实现私有证书颁发机构的认证和授权。
在这之前,需了解6个概念:
- SSL概念
- OpenSSL概念
- OpenSSL会话建立过程
- CA概念
- 私钥交换原理
- 三大加密算法
环境
系统环境
Distributor ID: Ubuntu
Description: Ubuntu 18.04.4 LTS
Release: 18.04
Codename: bionic
Linux version : 5.3.0-46-generic ( buildd@lcy01-amd64-013 )
Gcc version: 7.5.0 ( Ubuntu 7.5.0-3ubuntu1~18.04 )
软件信息
version :
openssl
正文
了解上述的概念之后,再了解CA证书的获取途径:
1、通过OpenSSL软件自建CA,响应用户的证书请求并实现证书的颁发、管理等操作
2、通过第三方合法的证书颁发机构提出申请,并经过各种审核确认用户身份,CA将申请真的相关信息进行审核后,进行签名,最后形成证书颁发给申请者。
本章主要介绍如何通过OpenSSL软件自建CA及其给各种应用(以OpenLDAP应用为例)签发证书,实现加密传输数据。
以下所用的到CA文件架构:
.
├── cacert.pem
├── certs
├── crl
├── index.txt
├── newcerts
├── private
│ └── cakey.pem
└── serial
现在不明白这个文件结构的用意不紧要,先粗略的记住他,继续往下看。
自建CA
创建CA的基本步骤如下:
-
安装OpenSSL软件
自建CA,需要OpenSSL软件支持,安装命令如下:
# 安装openssl和它的开发库 $ apt install openssl libssl-dev -y # 查看Ubuntu所安装的Openssl版本 $ openssl version -a openssl version -a OpenSSL 1.1.1d 10 Sep 2019 built on: Tue Feb 16 22:08:43 2021 UTC platform: debian-amd64 options: bn(64,64) rc4(8x,int) des(int) blowfish(ptr) compiler: gcc -fPIC -pthread -m64 -Wa,--noexecstack -Wall -Wa,--noexecstack -g -O2 -fdebug-prefix-map=/build/openssl-m9Qnvk/openssl-1.1.1d=. -fstack-protector-strong -Wformat -Werror=format-security -DOPENSSL_USE_NODELETE -DL_ENDIAN -DOPENSSL_PIC -DOPENSSL_CPUID_OBJ -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DKECCAK1600_ASM -DRC4_ASM -DMD5_ASM -DAESNI_ASM -DVPAES_ASM -DGHASH_ASM -DECP_NISTZ256_ASM -DX25519_ASM -DPOLY1305_ASM -DNDEBUG -Wdate-time -D_FORTIFY_SOURCE=2 OPENSSLDIR: "/usr/lib/ssl" ENGINESDIR: "/usr/lib/x86_64-linux-gnu/engines-1.1" Seeding source: os-specific
-
CA中心生成自身私钥
为了保证CA机构私钥的安全,需要把私钥文件的权限设置为077
创建符合docker-ldap的mycakey.crt
# mkdir CA && cd CA $ mkdir -p private $ (umask 077; openssl genrsa -out private/mycakey.crt 2048) Generating RSA private key, 2048 bit long modulus (2 primes) ....+++++ ...............+++++ e is 65537 (0x010001)
-
CA签发自身公钥
docker-ldap pause
$ SUBJECT="/C=CN/ST=Guangzhou/L=Guangzhou/O=MyCompany.com/OU=Tech/CN=*.caMyCompany.com" $ openssl req -new -days 365 -subj $SUBJECT -x509 -key private/mycakey.crt -out mycacert.crt
-
创建数据库文件及证书序列文件
# 目前文件情况 $ tree . . ├── cacert.pem └── private └── cakey.pem 1 directory, 2 files # 新建三个文件夹 $ mkdir demoCA certs crl demoCA/newcerts # 新建两个文件 $ touch demoCA/serial demoCA/index.txt $ echo "01" > demoCA/serial $ tree . . ├── cacert.pem # CA自身证书文件 ├── certs # 客户端证书存放目录 ├── crl # CA吊销的客户端证书存放目录 ├── demoCA # openssl.cnf的TSA root directory │ ├── index.txt # 存放客户端证书信息 │ ├── newcerts # 生成新证书存放目录 │ └── serial # 客户端证书编号,用于识别客户端证书 └── private # 存放CA自身私钥的目录 └── cakey.pem 5 directories, 4 files
-
通过OpenSSL命令获取根证书信息,查看是否成功
$ openssl x509 -noout -text -in ./cacert.pem Certificate: Certificate: Data: Version: 3 (0x2) Serial Number: ...... Signature Algorithm: sha256WithRSAEncryption Issuer: C = CN, ST = Guangzhou, L = Guangzhou, O = MyCompany.com, OU = Tech, CN = ca.MyCompany.com, emailAddress = ca@MyCompany.com Validity Not Before: May 12 15:14:58 2021 GMT Not After : May 12 15:14:58 2022 GMT Subject: C = CN, ST = Guangzhou, L = Guangzhou, O = MyCompany.com, OU = Tech, CN = ca.MyCompany.com, emailAddress = ca@MyCompany.com Subject Public Key Info: Public Key Algorithm: rsaEncryption RSA Public-Key: (2048 bit) Modulus:..... Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Subject Key Identifier: .... X509v3 Authority Key Identifier: keyid:..... X509v3 Basic Constraints: critical CA:TRUE Signature Algorithm: ....
查看证书情况
$ openssl x509 -noout -text -in ./mycacert.crt Certificate: Data: Version: 3 (0x2) Serial Number: ...... Signature Algorithm: sha256WithRSAEncryption Issuer: C = CN, ST = Guangzhou, L = Guangzhou, O = MyCompany.com, OU = Tech, CN = ca.MyCompany.com, emailAddress = ca@MyCompany.com Validity Not Before: May 12 15:14:58 2021 GMT Not After : May 12 15:14:58 2022 GMT Subject: C = CN, ST = Guangzhou, L = Guangzhou, O = MyCompany.com, OU = Tech, CN = ca.MyCompany.com, emailAddress = ca@MyCompany.com Subject Public Key Info: Public Key Algorithm: rsaEncryption RSA Public-Key: (2048 bit) Modulus:..... Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Subject Key Identifier: .... X509v3 Authority Key Identifier: keyid:..... X509v3 Basic Constraints: critical CA:TRUE Signature Algorithm: ....
# 查看官方demo的证书 $ openssl x509 -noout -text -in ./ca.crt > cacrt.txt # 明文打印私钥信息 $ openssl rsa -text -in ./ca.key > cakey.txt # .明文打印公钥信息: # $ openssl rsa -pubin -in test_pub.key -text # CA签发证书的序列号记录文件, $ cat ca.srl $ openssl x509 -noout -text -in ./ldap.crt > ldapcrt.txt $ openssl x509 -noout -text -in ./ldap.csr > ldapcsr.txt $ openssl rsa -text -in ./ldap.key > ldapkey.txt
至此,通过OpenSSL软件自建CA就完成了,后续就要接受客户端证书请求,验证所提供信息的合法性并签发证书以及后续证书的颁发、吊销证书等操作。
OpenLDAP与CA集成
默认情况下,OpenLDAP服务器与客户端之间使用明文验证、查询等一系列操作,由于互联网上进行传输存在不安全的因素,那么如何通过密文交换数据?OpenLDAP在开发时支持以SSL 、TLS方式进行会话加密,这需要提供OpenLDAP服务端证书以及修改配置文件来支持加密传输,该具体如何操作?
将OpenLDAP服务端也作为CA服务器。
-
OpenLDAP证书获取
-
OpenLDAP服务端生成秘钥
docker-ldap 的myldap.key
$ mkdir LDAP && cd LDAP $ (umask 077;openssl genrsa -out myldap.key 4096) Generating RSA private key, 2048 bit long modulus (2 primes) ...................+++++ .....+++++ e is 65537 (0x010001) Enter pass phrase for myldap.key:test Verifying - Enter pass phrase for myldap.key:test
-
OpenLDAP服务端向CA申请证书签署请求
docker-ldap
# CN 为 访问ip域名 $ CN_domain=ladpservice $ SUBJECT="/C=CN/ST=Guangzhou/L=Guangzhou/O=MyCompany.com/OU=Tech/CN=$CN_domain" $ openssl req -new -subj $SUBJECT -key $CN_domain.key -out $CN_domain.csr # 查看文件情况 $ tree . . ├── ldap.csr └── ldapkey.pem 0 directories, 2 files
注: 除了Common Name,Email Address 以外,以上所有值必须和CA证书填写信息保持一致,否则无法得到验证。(因为手误打错注册信息导致信息不一致导致无法验证通过)
以上一句话听不懂没有关系。接着往下看。
-
CA核实LDAP证书签署请求并签发证书
注:CA签署用户请求时,需监测用户证书请求信息,检测通过后,才能签署证书。
将LDAP的ldap.csr证书颁发请求文件复制到 CA/certs 客户端
$ docker cp myopenldap:./LDAP/myldap.csr .\localCA\certs
注:如果CA为独立的服务器,则需将用户的请求证书 通过ssh传至CA服务端中,当服务器完成签发后,再通过SSH将用户证书文件传送给客户端即可。本次教程,将OpenLDAP服务端也作为CA,所以不需要通过SSH进行传输数据。在生产环境中部署时,不建议二者混合使用,二推荐采用独立的服务器作为CA。
目前文件情况
$ tree . . ├── CA # CA服务器ssl证书根目录 │ ├── cacert.pem # CA 公钥 │ ├── certs # 客户端证书存储目录 │ │ ├── ldap.csr # ldap 证书颁发请求文件 │ ├── crl # CA吊销的客户端证书存放目录 │ ├── demoCA # openssl.cnf的TSA root directory │ │ ├── index.txt # 序号文件 │ │ ├── newcerts # 新生成客户端公钥存储目录 │ │ └── serial # 序号 │ └── private # 私钥存储目录 │ └── cakey.pem # CA私钥 └── LDAP # LDAP 服务器ssl证书目录 ├── ldap.csr # ldap 证书颁发请求文件 └── ldapkey.pem # LDAP私钥 7 directories, 7 files
重头戏:CA核实LDAP证书签署请求并签发证书。
docker-ldap
$ cd CA $ openssl ca -in ./certs/myldap.csr -out myldapcert.crt -days 3650 -keyfile ./private/mycakey.crt -cert ./mycacert.crt $ CN_domain=xxx $ openssl ca -in ./certs/$CN_domain.csr -out $CN_domain.crt -days 3650 -keyfile ./private/mycakey.crt -cert ./mycacert.crt Using configuration from /usr/lib/ssl/openssl.cnf Enter pass phrase for ./private/mycakey.crt:test Check that the request matches the signature Signature ok Certificate Details: Serial Number: 1 (0x1) Validity Not Before: May 20 09:29:58 2021 GMT Not After : May 18 09:29:58 2031 GMT Subject: countryName = CN stateOrProvinceName = Guangzhou organizationName = MyCompany.com organizationalUnitName = Tech commonName = ca.MyCompany.com X509v3 extensions: X509v3 Basic Constraints: CA:FALSE Netscape Comment: OpenSSL Generated Certificate X509v3 Subject Key Identifier: 91:8B:68:BD:5D:5C:66:64:AA:F6:E1:EA:3D:14:7B:1E:5D:53:4B:06 X509v3 Authority Key Identifier: keyid:64:3F:39:18:2A:71:45:99:E8:05:52:6F:01:01:D0:2B:AA:CB:FE:70 Certificate is to be certified until May 18 09:29:58 2031 GMT (3650 days) Sign the certificate? [y/n]:y 1 out of 1 certificate requests certified, commit? [y/n]y Write out database with 1 new entries Data Base Updated
可能会出现以下错误:
因为手误打错注册信息导致信息不一致导致无法验证通过。
#CA 证书和 请求证书的organizationName字段值不一致 Using configuration from /usr/lib/ssl/openssl.cnf Check that the request matches the signature Signature ok The organizationName field is different between CA certificate (MyCompany.com) and the request (MyCompany)
重新将两者ldap.csr 和 cacert.pem的注册信息一致就可以。
$ openssl ca -in ./certs/ldap.csr -out ldapcert.pem -keyfile ./private/cakey.pem -cert ./cacert.pem -days 3650 Using configuration from /usr/lib/ssl/openssl.cnf Check that the request matches the signature Signature ok Certificate Details: Serial Number: 1 (0x1) Validity Not Before: May 11 14:28:06 2021 GMT Not After : May 9 14:28:06 2031 GMT Subject: countryName = CN stateOrProvinceName = Guangzhou organizationName = MyCompany.com organizationalUnitName = Tech commonName = LDAP.MyCompany.com emailAddress = ldap@MyCompany.com X509v3 extensions: X509v3 Basic Constraints: CA:FALSE Netscape Comment: OpenSSL Generated Certificate X509v3 Subject Key Identifier: 34:BB:CF:7D:5B:6C:53:3A:F2:3B:C4:FB:14:BC:82:F6:7F:CD:14:01 X509v3 Authority Key Identifier: keyid:4E:8F:A0:F0:34:D1:90:37:77:1B:A2:47:ED:73:4B:9D:73:29:01:0B Certificate is to be certified until May 9 14:28:06 2031 GMT (3650 days) Sign the certificate? [y/n]:y 1 out of 1 certificate requests certified, commit? [y/n]y Write out database with 1 new entries Data Base Updated # 查看文件变化 $ cd .. && tree . . ├── CA │ ├── cacert.pem │ ├── certs │ │ └── ldap.csr │ ├── crl │ ├── demoCA │ │ ├── index.txt │ │ ├── index.txt.attr │ │ ├── index.txt.old │ │ ├── newcerts │ │ │ └── 01.pem │ │ ├── serial │ │ └── serial.old │ ├── ldapcert.pem │ └── private │ └── cakey.pem └── LDAP ├── ldap.csr └── ldapkey.pem 7 directories, 12 files
检验:CA中的demoCA文件夹变化比较大, 和生成ldapcert.pem
$ cd ./CA/demoCA/ $ cat serial.old 01 $ cat serial 02 $ cat index.txt.old $ cat index.txt.attr unique_subject = yes $ cat index.txt V 310509142806Z 01 unknown /C=CN/ST=Guangzhou/O=MyCompany.com/OU=Tech/CN=LDAP.MyCompany.com/emailAddress=ldap@MyCompany.com # 对比两个生成的文件 $ diff newcerts/01.pem ../ldapcert.pem $ mv cd # 完成相同的两个文件
-
-
OpenLDAP TLS/SASL部署
docker cp myopenldap:/container/service/slapd/assets/certs/myldap.key .\docker_file\ldap\certs
要完成OpenLDAP TLS/SASL部署,可按照一下步骤操作
-
修改证书权限
-
修改OpenLDAP配置文件,添加证书文件
-
开启OpenLDAP SSL功能
-
加载slapd数据库文件
-
查看后端slapd监听端口
$ netstat -ntplu | grep :636
-
通过CA证书公钥验证OpenLDAP服务端证书的合法性
docker-ldap
$ openssl verify -CAfile mycacert.crt myldapcert.crt myldapcert.crt: OK
-
确认当前套接字是否能通过CA的验证。
$ openssl s_client -connect openldap-host:636 -showcerts -state -CAfile mycacert.crt CONNECTED(00000003) SSL_connect:before SSL initialization SSL_connect:SSLv3/TLS write client hello SSL_connect:SSLv3/TLS write client hello Can't use SSL_get_servername SSL_connect:SSLv3/TLS read server hello depth=0 C = CN, ST = Guangzhou, O = MyCompany.com, OU = Tech, CN = LDAP.MyCompany.com, emailAddress = ldap@MyCompany.com verify error:num=66:EE certificate key too weak verify return:1 depth=1 C = CN, ST = Guangzhou, L = Guangzhou, O = MyCompany.com, OU = Tech, CN = ca.MyCompany.com, emailAddress = ca@MyCompany.com verify return:1 depth=0 C = CN, ST = Guangzhou, O = MyCompany.com, OU = Tech, CN = LDAP.MyCompany.com, emailAddress = ldap@MyCompany.com verify return:1 SSL_connect:SSLv3/TLS read server certificate SSL_connect:SSLv3/TLS read server key exchange SSL_connect:SSLv3/TLS read server certificate request SSL_connect:SSLv3/TLS read server done SSL_connect:SSLv3/TLS write client certificate SSL_connect:SSLv3/TLS write client key exchange SSL_connect:SSLv3/TLS write change cipher spec SSL_connect:SSLv3/TLS write finished SSL_connect:error in SSLv3/TLS write finished write:errno=0 Certificate chain 0 s:C = CN, ST = Guangzhou, O = MyCompany.com, OU = Tech, CN = LDAP.MyCompany.com, emailAddress = ldap@MyCompany.com i:C = CN, ST = Guangzhou, L = Guangzhou, O = MyCompany.com, OU = Tech, CN = ca.MyCompany.com, emailAddress = ca@MyCompany.com -----BEGIN CERTIFICATE----- ...... X+/a8dfCyCU= -----END CERTIFICATE----- 1 s:C = CN, ST = Guangzhou, L = Guangzhou, O = MyCompany.com, OU = Tech, CN = ca.MyCompany.com, emailAddress = ca@MyCompany.com i:C = CN, ST = Guangzhou, L = Guangzhou, O = MyCompany.com, OU = Tech, CN = ca.MyCompany.com, emailAddress = ca@MyCompany.com -----BEGIN CERTIFICATE----- ======================== -----END CERTIFICATE----- ================= Server certificate subject=C = CN, ST = Guangzhou, O = MyCompany.com, OU = Tech, CN = LDAP.MyCompany.com, emailAddress = ldap@MyCompany.com issuer=C = CN, ST = Guangzhou, L = Guangzhou, O = MyCompany.com, OU = Tech, CN = ca.MyCompany.com, emailAddress = ca@MyCompany.com ==================== Acceptable client certificate CA names C = CN, ST = Guangzhou, L = Guangzhou, O = MyCompany.com, OU = Tech, CN = ca.MyCompany.com, emailAddress = ca@MyCompany.com Client Certificate Types: RSA sign, DSA sign, ECDSA sign Requested Signature Algorithms: RSA+SHA384:RSA-PSS+SHA384:RSA-PSS+SHA384:ECDSA+SHA384:RSA+SHA512:RSA-PSS+SHA512:RSA-PSS+SHA512:ECDSA+SHA512:RSA+SHA256:RSA-PSS+SHA256:RSA-PSS+SHA256:ECDSA+SHA256:Ed25519 Shared Requested Signature Algorithms: RSA+SHA384:RSA-PSS+SHA384:RSA-PSS+SHA384:ECDSA+SHA384:RSA+SHA512:RSA-PSS+SHA512:RSA-PSS+SHA512:ECDSA+SHA512:RSA+SHA256:RSA-PSS+SHA256:RSA-PSS+SHA256:ECDSA+SHA256:Ed25519 Peer signing digest: SHA256 Peer signature type: RSA-PSS Server Temp Key: X25519, 253 bits --- SSL handshake has read 2467 bytes and written 388 bytes Verification error: EE certificate key too weak --- New, TLSv1.2, Cipher is ECDHE-RSA-AES256-GCM-SHA384 Server public key is 1024 bit Secure Renegotiation IS supported Compression: NONE Expansion: NONE No ALPN negotiated SSL-Session: Protocol : TLSv1.2 Cipher : ECDHE-RSA-AES256-GCM-SHA384 Session-ID: 8A842ECE73A72ACFF36BBDAE95D4526B2AE7D34E6B6F5D8225EAC1623F75DC2B Session-ID-ctx: Master-Key: A0147AB67A53378E5D05E13A5B9ECA0ACBB99D5134ADAE97CA2823AAD91C28C3AE470967BEF4C40072FC34547FDD88C0 PSK identity: None PSK identity hint: None SRP username: None Start Time: 1620835450 Timeout : 7200 (sec) Verify return code: 66 (EE certificate key too weak) Extended master secret: yes andsoon
以上信息错误为Can’t use SSL_get_servername、和66 (EE certificate key too weak),换个加密算法,重新生成证书。
openssl s_client -connect openldap-host:636 -showcerts -state -CAfile ca.crt CONNECTED(00000003) SSL_connect:before SSL initialization SSL_connect:SSLv3/TLS write client hello SSL_connect:SSLv3/TLS write client hello SSL_connect:SSLv3/TLS read server hello SSL_connect:SSLv3/TLS write change cipher spec SSL_connect:SSLv3/TLS write client hello SSL_connect:SSLv3/TLS write client hello SSL_connect:SSLv3/TLS read server hello Can't use SSL_get_servername SSL_connect:TLSv1.3 read encrypted extensions SSL_connect:SSLv3/TLS read server certificate request depth=1 C = US, ST = New Mexico, L = Albuquerque, O = A1A Car Wash, OU = Information Technology Dep., CN = docker-light-baseimage verify return:1 depth=0 C = US, ST = New Mexico, L = Albuquerque, O = A1A Car Wash, OU = Information Technology Dep., CN = openldap-host verify return:1 SSL_connect:SSLv3/TLS read server certificate SSL_connect:TLSv1.3 read server certificate verify SSL_connect:SSLv3/TLS read finished SSL_connect:SSLv3/TLS write client certificate SSL_connect:SSLv3/TLS write finished --- Certificate chain 0 s:C = US, ST = New Mexico, L = Albuquerque, O = A1A Car Wash, OU = Information Technology Dep., CN = openldap-host i:C = US, ST = New Mexico, L = Albuquerque, O = A1A Car Wash, OU = Information Technology Dep., CN = docker-light-baseimage -----BEGIN CERTIFICATE----- ...... EK6Z0Q== -----END CERTIFICATE----- 1 s:C = US, ST = New Mexico, L = Albuquerque, O = A1A Car Wash, OU = Information Technology Dep., CN = docker-light-baseimage i:C = US, ST = New Mexico, L = Albuquerque, O = A1A Car Wash, OU = Information Technology Dep., CN = docker-light-baseimage -----BEGIN CERTIFICATE----- ..... -----END CERTIFICATE----- Server certificate subject=C = US, ST = New Mexico, L = Albuquerque, O = A1A Car Wash, OU = Information Technology Dep., CN = openldap-host issuer=C = US, ST = New Mexico, L = Albuquerque, O = A1A Car Wash, OU = Information Technology Dep., CN = docker-light-baseimage Acceptable client certificate CA names C = US, ST = New Mexico, L = Albuquerque, O = A1A Car Wash, OU = Information Technology Dep., CN = docker-light-baseimage Requested Signature Algorithms: RSA+SHA384:RSA-PSS+SHA384:RSA-PSS+SHA384:ECDSA+SHA384:RSA+SHA512:RSA-PSS+SHA512:RSA-PSS+SHA512:ECDSA+SHA512 Shared Requested Signature Algorithms: RSA+SHA384:RSA-PSS+SHA384:RSA-PSS+SHA384:ECDSA+SHA384:RSA+SHA512:RSA-PSS+SHA512:RSA-PSS+SHA512:ECDSA+SHA512 Peer signing digest: SHA384 Peer signature type: ECDSA Server Temp Key: ECDH, P-521, 521 bits SSL handshake has read 2275 bytes and written 777 bytes Verification: OK New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384 Server public key is 384 bit Secure Renegotiation IS NOT supported Compression: NONE Expansion: NONE No ALPN negotiated Early data was not sent Verify return code: 0 (ok) read:errno=0
出现以上信息,说明iopenldap服务端使用SSL/TLS加密传输协议,此时传输的数据均为加密传输,从而保障了数据的安全性。
-
查看后端日志
tail -f /var/log/ldap.log
-
后记
None