自己做CA

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.

最后

安装信任下我的根证书吧

posted @ 2020-08-27 15:09  liness0713  阅读(96)  评论(0编辑  收藏  举报