OpenSSL生成CA(根证书)并自签署证书(支持IP地址)
X.509证书包含三个文件:key,csr,crt
key是服务器上的私钥文件,用于对发送给客户端数据的加密,以及对从客户端接收到数据的解密
csr是证书签名请求文件,用于提交给证书颁发机构(CA)对证书签名
crt是由证书颁发机构(CA)签名后的证书,或者是开发者自签名的证书,包含证书持有人的信息,持有的公钥,以及签署者的签名等信息
备注:在密码学中,X.509是一个标准,规范了公开秘钥认证、证书吊销列表、授权凭证、凭证路径验证算法等。
一、生成CA根证书
生成CA根证书私钥
openssl genrsa -des3 -out ca.pass.key 2048
去除CA私钥中的密码
openssl rsa -in ca.pass.key -out ca.key
生成CA根证书包括了国家(C=CN)、省/州(ST=BJ)、城市(L=BJ)、组织/公司(O=MyRootCA)、组织单位/部门(OU=MyCA)、通用名称(CN=CA)等信息
openssl req -new -sha256 -x509 -days 3650 -key ca.key -subj "/C=CN/ST=Chonqing/L=Chonqing/O=CA/OU=CA/CN=CA" -addext "basicConstraints=critical,CA:TRUE" -addext "keyUsage=critical,keyCertSign,cRLSign" -out ca.crt
注:critical是x509证书扩展中的一个标记,用于指示客户端必须识别并处理该扩展,否则应拒绝证书;可加在basicConstraints、keyUsage、extendedKeyUsage中。
二、生成服务器证书
生成v3.ext文件
cat > $HOST.ext << EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=critical,CA:FALSE
keyUsage=digitalSignature,keyEncipherment
extendedKeyUsage=serverAuth,clientAuth
subjectAltName=@alt_names
[alt_names]
DNS.1=${HOST}
DNS.2=*.${HOST}
DNS.3=localhost
IP.1=127.0.0.1
EOF
keyUsage各项值的含义:
数字签名(digitalSignature):用于对数据进行签名,确保数据的完整性和来源的真实性
密钥加密(keyEncipherment):用于加密别的密钥,常见于保护会话密钥或对称密钥
数据加密(dataEncipherment):用于公钥加密原始数据
不可否认(nonRepudiation):用于确保发送方不能否认其发送的数据
签名证书(keyCertSign):只有CA证书
签名CRL(cRLSign):只有CA证书
实际选型组合:
普通SSL证书:digitalSignature+keyEncipherment
代码签名/文档签名:digitalSignature,可选nonRepudiation
extendedKeyUsage各项值的含义:
serverAuth:SSL/TLS服务器认证,HTTPS、TLS服务器
clientAuth:SSL/TLS客户端认证,双向SSL、客户端证书
codeSigning:代码签名,可执行文件、驱动程序签名
emailProtection:邮件安全,S/MIME 加密和签名
timeStamping:时间戳,数字签名时间戳
生成服务器证书
openssl req -newkey rsa:2048 -nodes -keyout $HOST.key -subj "/C=CN/ST=Chonqing/L=Chonqing/O=MyRootServer/OU=MyServer/CN=$HOST" -out $HOST.csr
注:PDF阅读器里看到的签名人,通常就是CN字段;中文CN的写法CN=utf8string:张三
对服务器证书进行签名
openssl x509 -req -sha256 -days 3650 -CA ca.crt -CAkey ca.key -CAcreateserial -extfile $HOST.ext -in $HOST.csr -out $HOST.crt
签名成PDF签名证书
openssl x509 -req -sha256 -days 3650 -CA ca.crt -CAkey ca.key -CAcreateserial -addext "authorityKeyIdentifier=keyid,issuer" -addext "basicConstraints=critical,CA:FALSE" -addext "keyUsage=critical,digitalSignature,nonRepudiation" -addext "extendedKeyUsage=emailProtection,codeSigning" -in $HOST.csr -out $HOST.crt
查看服务器证书信息
openssl x509 -text -noout -in $HOST.crt
将CRT证书转为P12证书(可对PDF文件进行签名)
openssl pkcs12 -export -clcerts -in $HOST.crt -inkey $HOST.key -out $HOST.p12
将P12证书转为CRT证书
openssl pkcs12 -in $HOST.p12 -nokeys -out $HOST.crt # 导出证书
openssl pkcs12 -in $HOST.p12 -nocerts -nodes -out $HOST.key # 导出私钥
三、信任CA证书
CentOS
cp ca.crt /etc/pki/ca-trust/source/anchors/
update-ca-trust
Ubuntu
cp ca.crt /usr/local/share/ca-certificates/
update-ca-certificates
Windows
右键点击文件,选择安装证书,选择本地计算机,指定安装到受信任的根证书颁发机构即可。
附:证书生成脚本
#!/bin/bash
set -e # 遇到错误立即退出
# 显示帮助信息
show_help() {
cat << EOF
用法: $0 [选项]
选项:
--host HOST 域名(必需)
--days N 证书有效天数(默认3650天,约10年)
--key-size N 密钥大小(默认2048,可选4096)
环境变量:
SSL_C 国家代码(默认:CN)
SSL_ST 省份(默认:Chongqing)
SSL_L 城市(默认:Chongqing)
SSL_O 组织名称(默认:MyRootCA)
SSL_OU 组织单位(默认:MyCA)
示例:
$0 --host example.com
$0 --host example.com --days 365
$0 --host example.com --key-size 4096
EOF
}
# 默认配置
HOST=""
DAYS=3650 # 10年
KEY_SIZE=2048
# 证书信息默认值
C=${SSL_C:-"CN"}
ST=${SSL_ST:-"Chongqing"}
L=${SSL_L:-"Chongqing"}
O=${SSL_O:-"MyRootCA"}
OU=${SSL_OU:-"MyCA"}
# 解析命令行参数
while [[ $# -gt 0 ]]; do
case $1 in
-h|--help)
show_help
exit 0
;;
--host)
HOST="$2"
shift 2
;;
--days)
DAYS="$2"
shift 2
;;
--key-size)
KEY_SIZE="$2"
shift 2
;;
-*)
echo "错误: 未知选项 $1"
show_help
exit 1
;;
*)
esac
done
# 检查参数
if [ -z "$HOST" ]; then
show_help
exit 1
fi
# 简单的域名格式验证
if ! [[ "$HOST" =~ ^[a-zA-Z0-9][a-zA-Z0-9.-]*[a-zA-Z0-9]$ ]]; then
echo "警告: 域名格式可能不正确,继续执行..."
fi
# 验证天数是否为数字
if ! [[ "$DAYS" =~ ^[0-9]+$ ]]; then
echo "错误: 天数必须是数字"
exit 1
fi
# 验证密钥大小
if [[ "$KEY_SIZE" != "2048" ]] && [[ "$KEY_SIZE" != "4096" ]]; then
echo "错误: 密钥大小必须是2048或4096"
exit 1
fi
echo "========================================="
# 判断是否有根证书,有就不生成根证书了
if [ ! -f "ca.crt" ]; then
echo ""
echo "=== 生成CA根证书 ==="
# 生成CA根证书私钥
echo "1.生成CA根证书私钥 (带密码保护)"
openssl genrsa -des3 -out ca.pass.key $KEY_SIZE
# 去除CA根证书私钥中的密码
echo "2.去除CA根证书私钥中的密码"
openssl rsa -in ca.pass.key -out ca.key
# 设置私钥权限
chmod 600 ca.key
# 生成CA根证书
echo "3.生成CA根证书"
openssl req -new -sha256 -x509 -days $DAYS -key ca.key -subj "/C=$C/ST=$ST/L=$L/O=$O/OU=$OU/CN=CA" -addext "basicConstraints=critical,CA:TRUE" -addext "keyUsage=critical,keyCertSign,cRLSign" -out ca.crt
fi
# 生成服务器证书
echo ""
echo "=== 生成服务器证书 ==="
# 生成v3.ext文件(支持SAN扩展)
echo "1.生成证书扩展配置文件"
cat > $HOST.ext << EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=critical,CA:FALSE
keyUsage=digitalSignature,keyEncipherment
extendedKeyUsage=serverAuth,clientAuth
subjectAltName=@alt_names
[alt_names]
DNS.1=${HOST}
DNS.2=*.${HOST}
DNS.3=localhost
IP.1=127.0.0.1
EOF
# 生成服务器私钥和CSR
echo "2.生成服务器私钥和证书签名请求(CSR)"
openssl req -newkey rsa:$KEY_SIZE -nodes -keyout $HOST.key -subj "/C=$C/ST=$ST/L=$L/O=${O}Server/OU=${OU}Server/CN=$HOST" -out $HOST.csr
# 对服务器证书进行签名
echo "3.使用CA证书签署服务器证书"
openssl x509 -req -sha256 -days $DAYS -CA ca.crt -CAkey ca.key -CAcreateserial -extfile $HOST.ext -in $HOST.csr -out $HOST.crt
# 将CRT证书转为P12证书(可对PDF文件进行签名)
echo "4.将CRT证书转为P12证书"
openssl pkcs12 -export -clcerts -in $HOST.crt -inkey $HOST.key -out $HOST.p12
# 将P12证书转为CRT证书
# echo "5.将P12证书转为CRT证书"
# openssl pkcs12 -in $HOST.p12 -nokeys -out $HOST.crt # 导出证书
# openssl pkcs12 -in $HOST.p12 -nocerts -nodes -out $HOST.key # 导出私钥