准备工作
创建相关目录和文件
代码语言:javascript复制mkdir -p ./CA/{private,newcerts} && cd ./CA
echo 01 > serial
touch index.txt index.txt.attr
OpenSSL配置文件
编辑openssl.cnf
vi openssl.cnf
将以下内容复制到openssl.cnf
文件
[ ca ]
default_ca = CA_default
[ CA_default ]
# Directory and file locations.
dir = ../CA # Where everything is kept
certs = $dir/certs # Where the issued certs are kept
crl_dir = $dir/crl # Where the issued crl are kept
new_certs_dir = $dir/newcerts # default place for new certs.
database = $dir/index.txt # database index file.
serial = $dir/serial # The current serial number
RANDFILE = $dir/private/.rand # private random number file
#unique_subject = no # Set to 'no' to allow creation of
# several ctificates with same subject.
# The root key and root certificate.
private_key = $dir/private/cakey.pem# The private key
certificate = $dir/cacert.pem # The CA certificate
# For certificate revocation lists.
crlnumber = $dir/crlnumber # the current crl number
crl = $dir/crl.pem # The current CRL
crl_extensions = crl_ext
# SHA-1 is deprecated, so use SHA-2 instead.
preserve = no # keep passed DN ordering
default_md = sha256 # use SHA-256 by default
default_days = 365 # how long to certify for
default_crl_days = 30 # how long before next CRL
# A few difference way of specifying how similar the request should look
# For type CA, the listed attributes must be the same, and the optional
# and supplied fields are just that :-)
policy = policy_match
# For the CA policy
[ policy_match ]
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
代码语言:javascript复制vi root.conf
代码语言:javascript复制[ req ]
default_bits = 2048
default_keyfile = r.pem
default_md = sha256
string_mask = nombstr
distinguished_name = req_distinguished_name
req_extensions = req_ext
x509_extensions = x509_ext
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = CN
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = Guangdong
localityName = Locality Name (eg, city)
localityName_default = Shaoguan
organizationName = Organization Name (eg, company)
organizationName_default = jwj
commonName = Common Name (e.g. server FQDN or YOUR name)
commonName_max = 64
commonName_default = jwj
[ x509_ext ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
basicConstraints = CA:TRUE,pathlen:3
keyUsage = digitalSignature, keyEncipherment, keyCertSign, cRLSign
[ req_ext ]
subjectKeyIdentifier = hash
basicConstraints = CA:TRUE
keyUsage = digitalSignature, keyEncipherment, keyCertSign, cRLSign
参数含义:
字段 值 countryName 国家名缩写 stateOrProvinceName 州或省 localityName 地点,如城市 organizationName 组织名 commonName 商标(证书上显示的 CA 名称)
- xxx_default 设置该字段默认值,这样等一下生成证书时就不用手动填写信息,直接回车使用默认值就行了。
生成 CA 根密钥:
代码语言:javascript复制openssl genrsa -out ./private/cakey.pem 2048
代码语言:javascript复制Generating RSA private key, 2048 bit long modulus
......................................
........................
e is 65537 (0x10001)
自签发 CA 根证书:
代码语言:javascript复制openssl req -new -x509 -key ./private/cakey.pem -out ./cacert.pem -days 7300 -config ./root.conf
代码语言:javascript复制You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [CN]:
State or Province Name (full name) [GuangDong]:
Locality Name (eg, city) [ShaoGuan]:
Organization Name (eg, company) [jwj]:
Common Name (e.g. server FQDN or YOUR name) [My CA]:
将 PEM 格式证书转为常用的 DER 格式:
代码语言:javascript复制openssl x509 -inform PEM -in ./cacert.pem -outform DER -out ./CA.cer
用 CA 证书签发 SSL 证书 创建文件夹方便管理:
代码语言:javascript复制mkdir ../i0w.cn && cd ../i0w.cn
创建用户证书配置文件:
代码语言:javascript复制vi server.conf
代码语言:javascript复制[ req ]
default_bits = 2048
default_keyfile = r.pem
default_md = sha256
string_mask = nombstr
distinguished_name = req_distinguished_name
req_extensions = req_ext
x509_extensions = x509_ext
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = CN
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = Guangdong
localityName = Locality Name (eg, city)
localityName_default = Shaoguan
organizationName = Organization Name (eg, company)
organizationName_default = jwj
commonName = Common Name (e.g. server FQDN or YOUR name)
commonName_max = 64
commonName_default = localhost
[ x509_ext ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment
subjectAltName = @alt_names
[ req_ext ]
subjectKeyIdentifier = hash
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = localhost
DNS.2 = i0w.cn
DNS.3 = *.i0w.cn
IP.1 = 127.0.0.1
IP.2 = 192.168.0.111
IP.3 = 192.168.1.111
注意:
- 在 [ alt_names ] 下填写要签发证书的域名或 IP,支持通配符;
- Firefox 下出现 MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY,原因是 basicConstraints 被设置成了 CA:TRUE,改为 CA:FALSE 即可。
生成用户 RSA 密钥:
代码语言:javascript复制openssl genrsa -out ./server.key 2048
代码语言:javascript复制Generating RSA private key, 2048 bit long modulus
.......................................................................................
................
e is 65537 (0x10001)
生成用户证书请求:
代码语言:javascript复制openssl req -new -key ./server.key -out ./server.csr -config ./server.conf
代码语言:javascript复制Generating RSA private key, 2048 bit long modulus
.......................................................................................
................
e is 65537 (0x10001)
[root@huawei i0w.cn]# openssl req -new -key ./server.key -out ./server.csr -config ./server.conf
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [CN]:
State or Province Name (full name) [GuangDong]:
Locality Name (eg, city) [ShaoGuang]:
Organization Name (eg, company) [jwj]:
Common Name (e.g. server FQDN or YOUR name) [*.i0w.cn]:
签发用户证书:
代码语言:javascript复制openssl ca -config ../CA/openssl.cnf -in ./server.csr -out ./server.crt -days 3650 -extensions x509_ext -extfile ./server.conf
代码语言:javascript复制Using configuration from ../CA/openssl.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName :PRINTABLE:'CN'
stateOrProvinceName :PRINTABLE:'GuangDong'
localityName :PRINTABLE:'ShaoGuang'
organizationName :PRINTABLE:'jwj'
commonName :T61STRING:'*.i0w.cn'
Certificate is to be certified until Jun 10 01:39:26 2030 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
附上证书签发目录结构:
代码语言:javascript复制$ tree
.
├── demoCA
│ ├── CA.cer # CA 证书(DER 格式)
│ ├── cacert.pem # CA 证书(PEM 格式)
│ ├── index.txt # 签发记录数据库
│ ├── index.txt.attr
│ ├── index.txt.old
│ ├── newcerts
│ │ └── 01.pem
│ ├── private
│ │ └── cakey.pem # CA 私钥
│ ├── serial
│ └── serial.old
├── 2heng.xin
│ ├── 2heng.xin.crt # 用户证书
│ ├── 2heng.xin.csr
│ └── 2heng.xin.key # 用户证书私钥
├── root.conf # CA 配置文件
└── server.conf # 用户配置文件
参考来源: https://2heng.xin/2018/12/16/your-own-ca-with-openssl/ https://blog.csdn.net/cuitone/article/details/87966042