https://wangbin.io/blog/it/https-ca.html
最近chrome提示https证书错误,缺少subjectAltName,查了下解决方法,更新下。
一. 简介
之前我的博客支持https使用的是向StartCom CA申请签发的一年免费证书。StartCom是受信赖的CA机构,它的根证书被各种操作系统和浏览器内置信任,所以由它签发的证书也会被信任。
最近做了个iOS ipa包上传下载程序,也需要使用https链接,上网查了下发现可以自己签名证书,所以实践了下,下面是详细步骤。
特别推荐下面这个网站,讲的是...非常详细。
https://jamielinux.com/docs/openssl-certificate-authority/index.html
教程里有些功能了解就可以了,我们不需要使用,所以我去掉了其中一些步骤,简单好用些。
二. CA
自己当CA,就是用openssl命令生成自己的根证书,让用户安装信任它,那么所有用这个根证书签名的证书,就也可以被信任啦。
所以做为CA,我们首先要生成自己的根证书ca.cert.pem,而生成根证书需要ca.key.pem。
开始
创建/root/ca文件夹,所有CA的操作都会在这个文件夹执行。
# mkdir /root/ca
# cd /root/ca
# mkdir certs crl newcerts private
# chmod 700 private
# touch index.txt
# echo 1000 > serial
# touch openssl.cnf
/root/ca:CA文件夹
/root/ca/certs:新签署证书和根证书存放的位置
/root/ca/crl:证书请求文件存放位置
/root/ca/newcerts:新签署证书存放的位置,是/root/ca/certs的备份
/root/ca/private:ca.key.pem存放位置,千万别丢失
/root/ca/index.txt:证书签名的纪录
/root/ca/serial:下一次证书签名的序列号,保存到index.txt
拷贝下面内容到/root/ca/openssl.cnf
# OpenSSL root CA configuration file.
# Copy to `/root/ca/openssl.cnf`.
[ ca ]
# `man ca`
default_ca = CA_default
[ CA_default ]
# Directory and file locations.
dir = /root/ca
certs = $dir/certs
crl_dir = $dir/crl
new_certs_dir = $dir/newcerts
database = $dir/index.txt
serial = $dir/serial
RANDFILE = $dir/private/.rand
# The root key and root certificate.
private_key = $dir/private/ca.key.pem
certificate = $dir/certs/ca.cert.pem
# For certificate revocation lists.
crlnumber = $dir/crlnumber
crl = $dir/crl/ca.crl.pem
crl_extensions = crl_ext
default_crl_days = 30
# SHA-1 is deprecated, so use SHA-2 instead.
default_md = sha256
name_opt = ca_default
cert_opt = ca_default
default_days = 3750
preserve = no
policy = policy_strict
[ policy_strict ]
# The root CA should only sign intermediate certificates that match.
# See the POLICY FORMAT section of `man ca`.
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ policy_loose ]
# Allow the intermediate CA to sign a more diverse range of certificates.
# See the POLICY FORMAT section of the `ca` man page.
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ req ]
# Options for the `req` tool (`man req`).
default_bits = 2048
distinguished_name = req_distinguished_name
string_mask = utf8only
# SHA-1 is deprecated, so use SHA-2 instead.
default_md = sha256
# Extension to add when the -x509 option is used.
x509_extensions = v3_ca
[ req_distinguished_name ]
# See <https://en.wikipedia.org/wiki/Certificate_signing_request>.
countryName = Country Name (2 letter code)
stateOrProvinceName = State or Province Name
localityName = Locality Name
0.organizationName = Organization Name
organizationalUnitName = Organizational Unit Name
commonName = Common Name
emailAddress = Email Address
# Optionally, specify some defaults.
countryName_default = CN
stateOrProvinceName_default = JiangSu
localityName_default = NanJing
0.organizationName_default = wangbin
organizationalUnitName_default = wangbin
emailAddress_default = webmaster@wangbin.io
[ v3_ca ]
# Extensions for a typical CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ v3_intermediate_ca ]
# Extensions for a typical intermediate CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ usr_cert ]
# Extensions for client certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = client, email
nsComment = "OpenSSL Generated Client Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, emailProtection
[ server_cert ]
# Extensions for server certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = server
nsComment = "OpenSSL Generated Server Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
IP.1 = 127.0.0.1
IP.2 = 192.168.1.1
DNS.1 = wangbin.io
DNS.2 = ioptimi.wangbin.io
[ crl_ext ]
# Extension for CRLs (`man x509v3_config`).
authorityKeyIdentifier=keyid:always
[ ocsp ]
# Extension for OCSP signing certificates (`man ocsp`).
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, digitalSignature
extendedKeyUsage = critical, OCSPSigning
具体的解释可以看上面的链接(真的是很推荐),这里我拣重要的说下
dir = /root/ca:这里需要改为上面的CA文件夹
policy = policy_strict:签CA证书使用strict策略
countryName_default = CN
0.organizationName_default = wangbin CA
这两个是国家和组织名字,会显示到生成的证书上。简单的签个CA证书,我们只设置这两个值,其他都是空。
[ v3_ca ]:签CA证书需要这个配置
[ server_cert ]:接下来签服务端证书需要这个
生成root key
# cd /root/ca
# openssl genrsa -aes256 -out private/ca.key.pem 4096
输入两次密码wangbin123456,这个是很重要的密码,设置严格点。
# chmod 400 private/ca.key.pem
生成root certificate
# cd /root/ca
# openssl req -config openssl.cnf
-key private/ca.key.pem
-new -x509 -days 7500 -sha256 -extensions v3_ca
-out certs/ca.cert.pem
根据提示输入key的密码:wangbin123456
然后一值回车下去,使用默认值
# chmod 444 certs/ca.cert.pem
-days 7300:有效期20年
到这一步ca.key.pem(root key)和ca.cert.pem(root certificate)都已经生成好了,路径如下
/root/ca/private/ca.key.pem
/root/ca/certs/ca.cert.pem
至此生成根证书完成。
ca.key.pem密码是wangbin123456,非常重要,需要好好保存。
ca.cert.pem就是根证书,需要把它发给用户,让用户安装信任它,这样以后我们用这个证书签名的证书就都可以被信任了。
三. 生成服务端证书
CA角色要做的工作已经完成了,下面我们以用户这个角色,生成一个tomcat和nginx可以使用的服务端证书。
这里假设我们网站的域名或ip地址是127.0.0.1,那么在ca同级目录下创建127.0.0.1文件夹,生成服务端证书操作都在这个目录下进行。
# mkdir /root/127.0.0.1
# cd /root/127.0.0.1
# openssl genrsa -out server.key 2048
# openssl req -new -key server.key -out server.csr
会出现提示,尽量全部都填写,防止以后浏览器对证书验证变得严格,又要重新签名。关键数据重复填写就可以了。
Country Name输入:CN
State or Province Name输入:JiangSu
Locality Name(eg, city)输入:NanJing
Organization Name (eg, company)输入:wangbin.io
Organizational Unit Name (eg, section)输入:wangbin.io
Common Name输入域名或ip:127.0.0.1
Email Address:xxx@qq.com
extra信息
A challenge password输入:server123456
An optional company name []:wangbin.io
openssl genrsa -out server.key 2048:这个命令后面2048代表加密位数,严格的使用4096,例如上面的根证书使用的就是这个,一般使用2048和1024就可以了,数值越大https链接等待时间越长。
到这儿,我们服务端key(server.key)和证书请求(server.csr)就生成啦。
接下来拷贝server.csr到ca/crl并改名为127.0.0.1.csr.pem
cp server.csr ../ca/crl/127.0.0.1.csr.pem
然后角色切换到CA角色,对这个请求进行处理。
首先修改下/root/ca/openssl.cnf
policy = policy_strict
改为
policy = policy_loose
policy_strict只在生成根证书的时候使用,其他时候使用loose策略就可以啦。
2017.08.31修改:将下面IP或者DNS更新为要签名的
[alt_names]
IP.1 = 127.0.0.1
IP.2 = 192.168.1.1
DNS.1 = wangbin.io
DNS.2 = ioptimi.wangbin.io
执行命令,生成证书
# cd /root/ca
# openssl ca -config openssl.cnf
-extensions server_cert -days 375 -notext -md sha256
-in crl/127.0.0.1.csr.pem
-out certs/127.0.0.1.cert.pem
-days 375:有效期375天,默认值也是375天
这时候,你会发现
- /root/ca/certs下多了127.0.0.1.cert.pem(这个就是生成好的证书)
- newcerts下面多了1000.pem(这个是证书备份,1000是从serial中取的)
-
/root/ca/index.txt多了行纪录
/root/ca/index.txt V 171014020124Z 1000 unknown /C=CN/ST=Some-State/O=Internet Widgits Pty Ltd/CN=127.0.0.1
- /root/ca/serial中的值+1变成了1001。
将/root/ca/certs/127.0.0.1.cert.pem证书发给用户,CA角色的工作就完成啦。
角色切换回用户,我们将CA发给我们的127.0.0.1.cert.pem拷贝到/root/127.0.0.1目录下,并改名为server.crt
cp certs/127.0.0.1.cert.pem ../127.0.0.1/server.crt
这时我们目录下有下面三个文件
server.crt server.csr server.key
server.crt就是我们要的证书,我们可以配置nginx支持https啦。
nginx配置
server {
listen 443;
server_name 127.0.0.1;
ssl on;
ssl_certificate /root/127.0.0.1/server.crt;
ssl_certificate_key /root/127.0.0.1/server.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://127.0.0.1;
}
location ~ ^(.*)/.svn/ {
deny all;
}
}
要支持tomcat的话,我们还需要进行下面的操作。
# cd /root/127.0.0.1
# openssl pkcs12 -export
-in server.crt
-inkey server.key
-out server.p12
输入两次密码:server123456
# keytool -importkeystore -v
-srckeystore server.p12
-srcstoretype pkcs12
-srcstorepass server123456
-destkeystore server.keystore
-deststoretype jks
-deststorepass server123456
操作后的文件目录
server.crt server.csr server.key
server.p12 server.keystore
tomcat配置
<Connector SSLEnabled="true" clientAuth="false"
keystoreFile="/root/127.0.0.1/server.keystore"
keystorePass="server123456"
maxThreads="150" port="8443" protocol="org.apache.coyote.http11.Http11Protocol" scheme="https" secure="true" sslProtocol="TLS"/>
结尾
以后如果需要生成别的服务端证书,我们就只用从三. 生成服务端证书开始就可以啦,是不是很easy.
最后
安装信任下我的根证书吧