转载自:https://wangbin.io/blog/it/https-ca.html
自己做CA
最近chrome提示https证书错误,缺少subjectAltName,查了下解决方法,更新下。
一. 简介
之前我的博客支持https使用的是向StartCom CA申请签发的一年免费证书。StartCom是受信赖的CA机构,它的根证书被各种操作系统和浏览器内置信任,所以由它签发的证书也会被信任。
最近做了个iOS ipa包上传下载程序,也需要使用https链接,上网查了下发现可以自己签名证书,所以实践了下,下面是详细步骤。
特别推荐下面这个网站,讲的是...非常详细。
OpenSSL Certificate Authority — Jamie Nguyen
教程里有些功能了解就可以了,我们不需要使用,所以我去掉了其中一些步骤,简单好用些。
二. 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.
最后
安装信任下我的根证书吧
参考: