证书签发与自签名证书
证书签发与自签名证书
密钥生成
一般是ssh/github/WireGuard使用,生成一对公私钥
ssh-keygen -t [rsa/ecdsa/ed25519] -f [path] -C "comment"
目前RSA不建议使用,又长还不安全,建议使用ed25519,
证书生成
几个概念和文件解释
文件
- .key: 证书对应的私钥文件
- .crt: CA认证后的文件,即证书
- .csr: 证书签名请求, 用私钥签名得到的文件
- .crl: 证书吊销列表
- .pem; 导出导入证书用的格式, .crt+.key, 使用base64存储
根证书和用户证书: 根证书是信任链顶级, 用户证书是根证书签发的
对于自签证书, 只要根证书是有效的(安装在电脑上), 则由它签发的用户证书就是可信的
.x509: 证书格式标准
生成证书有两种, 自签名和CA签发, 只有CA签发的才有https锁标志, 但是加密功能来说两者等效
自签名证书
下面讲解如何生成自己的证书
根证书生成
首先需要一个根证书,我们自己就是CA
- 创建工作目录
mkdir -p ./myca/{certs,crl,newcerts,private}
cd myca
touch index.txt
echo 1000 > serial
chmod 700 private
目录应该是这样的
.
├── certs # 证书位置
├── crl # 吊销列表
├── index.txt # 证书目录
├── newcerts # 新证书
├── private # 私钥
└── serial # 自增的index
- 准备OpenSSL文件
(openssl.cnf)
[ ca ]
default_ca = CA_default
[ CA_default ]
dir = /home/nolan/code/myca # CA 根目录
certs = $dir/certs
new_certs_dir = $dir/newcerts
database = $dir/index.txt
serial = $dir/serial
private_key = $dir/private/ca.key.pem
certificate = $dir/certs/ca.cert.pem
default_md = sha256
policy = policy_loose
default_days = 3650
x509_extensions = v3_ca
[ policy_loose ]
# policy设置
# optional指后面的CSR可以不写,supplied需要写
# match是必须写且值必须和CA的相同
countryName = optional
stateOrProvinceName = optional
organizationName = optional
commonName = supplied
[ req ]
prompt = no # 设置为No直接使用下面的默认值,否则交互式询问
default_bits = 4096 # RSA有效,ED25519是没用的
distinguished_name = req_distinguished_name
string_mask = utf8only
[ req_distinguished_name ]
# 证书主题默认值
C = CN # Country Name
ST = Hubei # State or Province Name
L = WuHan # Locality Name
O = Apeiria # Organization Name
CN = Apeiria # Common Name
[ v3_ca ]
# CA:TRUE=CA标识,critical=客户端验证时,不认识就直接拒绝
basicConstraints = critical, CA:TRUE
# 用途,keyCertSign/cRLSign=签发下级证书/吊销列表,critical=拒绝其他用途
keyUsage = critical, keyCertSign, cRLSign
# Subject Key Identifier 扩展,快速找到上级证书
subjectKeyIdentifier = hash
- 生成根CA私钥
# 签发证书
openssl genrsa -out private/ca.key.pem 4096
# 用ED25519,上面默认RSA
openssl genpkey -algorithm Ed25519 -out private/ca.key.pem
chmod 400 private/ca.key.pem
- 签发根 CA 证书
openssl req -config openssl.cnf \
-key private/ca.key.pem \
-new -x509 -days 3650 -sha256 \
-extensions v3_ca \
-out certs/ca.cert.pem
chmod 444 certs/ca.cert.pem
- 验证
openssl x509 -in certs/ca.cert.pem -noout -text
结果
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
18:09:35:aa:82:e4:6a:e4:8d:d2:35:5d:f2:51:49:83:55:84:5e:e1
Signature Algorithm: ED25519
Issuer: C=CN, ST=Hubei, L=WuHan, O=Apeiria, CN=Apeiria
Validity
Not Before: Apr 19 08:41:35 2025 GMT
Not After : Apr 17 08:41:35 2035 GMT
Subject: C=CN, ST=Hubei, L=WuHan, O=Apeiria, CN=Apeiria
Subject Public Key Info:
Public Key Algorithm: ED25519
ED25519 Public-Key:
pub:
e5:ac:18:8f:81:7c:d9:e4:59:8d:a3:b0:79:8d:70:
fb:04:c2:4f:27:7b:34:3c:6b:a6:15:c0:a5:29:46:
ab:97
X509v3 extensions:
X509v3 Basic Constraints: critical
CA:TRUE
X509v3 Key Usage: critical
Certificate Sign, CRL Sign
X509v3 Subject Key Identifier:
DE:05:5A:55:8B:F6:63:FD:C7:0F:EC:BE:70:7C:55:9E:8A:84:92:1E
Signature Algorithm: ED25519
Signature Value:
57:ba:4b:ba:3d:ea:fa:0d:e1:cf:cc:74:e0:03:9b:f4:94:56:
24:dc:f7:e5:d4:3e:47:21:b5:df:e4:8c:e1:c1:2f:84:46:fc:
4a:90:60:e2:df:77:97:0f:e4:2c:c0:60:92:32:d6:69:0d:40:
fb:14:cb:39:f9:81:7d:cd:aa:08
最终我们得到了
.
├── certs
│ └── ca.cert.pem # CA证书
├── crl
├── index.txt
├── newcerts
├── openssl.cnf
├── private
│ └── ca.key.pem # CA私钥
└── serial
用户证书签发
上面已经有了 CA 和私钥,下面讲解如何签发自己的证书
生成用户的私钥,其实和CA生成私钥是一样的,私钥并不分是否是CA
总之需要一个私钥
openssl genpkey -algorithm Ed25519 -out nolan.key.pem
chmod 400 nolan.key.pem
生成CSR,也就是提交给CA的证书签名请求,通过私钥获取到证书
openssl req -new -key nolan.key.pem -out nolan.csr.pem
这一步需要调整`openssl.cnf`,末尾添加 user_crt 相关配置
[ usr_cert ]
# 普通用户证书,非 CA
basicConstraints = critical, CA:FALSE
# 标识这个证书用作客户端认证
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
- 签发证书
# -extensions usr_cert 就指定了刚刚的配置
openssl ca -config openssl.cnf \
-extensions usr_cert \
-days 3650 \
-notext \
-md sha256 \
-in nolan.csr.pem \
-out certs/nolan.cert.pem
- 验证
openssl x509 -in certs/nolan.cert.pem -noout -text
结果
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 4096 (0x1000)
Signature Algorithm: ED25519
Issuer: C=CN, ST=Hubei, L=WuHan, O=Apeiria, CN=Apeiria
Validity
Not Before: Apr 19 09:01:42 2025 GMT
Not After : Apr 17 09:01:42 2035 GMT
Subject: C=CN, ST=Hubei, O=Apeiria, CN=Apeiria
Subject Public Key Info:
Public Key Algorithm: ED25519
ED25519 Public-Key:
pub:
03:cb:ee:2b:b6:62:0d:4f:86:6b:37:45:f1:c0:ad:
c8:af:1a:0c:01:5e:6b:ab:c7:a1:ee:5a:46:87:38:
6b:dc
X509v3 extensions:
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
X509v3 Extended Key Usage:
TLS Web Client Authentication
X509v3 Subject Key Identifier:
DD:0B:04:82:65:DA:6E:76:7A:50:39:AC:C5:E9:9B:9B:35:3F:CC:84
X509v3 Authority Key Identifier:
DE:05:5A:55:8B:F6:63:FD:C7:0F:EC:BE:70:7C:55:9E:8A:84:92:1E
Signature Algorithm: ED25519
Signature Value:
af:6b:79:2b:a4:fb:c3:84:33:9d:9a:3a:02:1a:df:c4:70:ac:
8d:7b:42:bf:e3:b3:63:98:f7:12:db:83:89:b2:0c:3b:c8:7e:
ad:e3:e5:25:00:e3:c7:fb:af:1b:67:70:0c:af:47:3e:39:13:
6e:66:5e:11:c3:6b:3a:c8:95:05
Let's Encrypt 申请
certbot方法
# 安装certbot ACME
sudo apt-get install certbot
# 验证域名所有权, 并获取证书, 不过需要确保80和443没有占用
sudo certbot certonly --standalone
Let's Encrypt证书有效期一般只有90天, 需要续订
certbot一般会自动设置定时任务自动续订证书, 也可以用下面的命令测试
sudo certbot renew --dry-run # 查看续订(dry-run)
OpenSSL常用命令
- 解析 pem 证书
openssl x509 -in cert.pem -noout -text
- 验证证书链
openssl verify -CAfile ca-chain.pem cert.pem
- 检查服务器证书
openssl s_client -connect axi.moe:443 \
-servername axi.moe -showcerts </dev/null \
2>/dev/null | openssl x509 -noout -text
- DEBUG 用,Serve AS TLS
openssl s_server -key key.pem -cert cert.pem -accept 8443