Ubuntu 22.04 开发环境 CA 证书签发完整笔记
开发环境
前端: Vue3+TS+Vite+ESM后端:NestJS数据库:MySQL+Redis虚拟机OS:Ubuntu 22.04 LTS
工作拓扑

开发环境参数(VS Code)
版本: 1.106.3 (Universal)Electron: 37.7.0ElectronBuildId: 12781156Chromium: 138.0.7204.251Node.js: 22.20.0V8: 13.8.258.32-electron.0OS: Darwin arm64 24.6.0
目录介绍
CA核心目录:(根CA私钥、证书、签发记录存放)
/opt/ca/root/
服务端目录:(服务端私钥、CSR、证书存放)
/opt/ca/server/
客户端目录:(客户端私钥、CSR、证书存放)
/opt/ca/server/client/
目标:生成根CA证书、NestJS服务端证书、Vue3客户端p12证书,完成验证与本地下载
一、前置准备
1. 检查OpenSSL版本(需1.1.1及以上)
openssl version
解释:Ubuntu 22.04默认已装,无需额外安装;若未装,执行以下命令(离线环境需提前下载deb包):
sudo apt update && sudo apt install openssl -y
2. 创建标准化CA目录结构(权限先行)
创建完整目录并配置安全权限(私钥目录仅root可读,避免泄露):
# 根CA核心目录(私钥严格保护)
mkdir -p /opt/ca/root/{private,certs,csr,newcerts}
chmod 700 /opt/ca/root/private # 仅root可进入
chown -R root:root /opt/ca/root # 目录归属root
# 服务端(NestJS)目录
mkdir -p /opt/ca/server/{private,certs,csr}
chmod 700 /opt/ca/server/private
chown -R root:root /opt/ca/server
# 客户端(Vue3)目录
mkdir -p /opt/ca/server/client/{private,certs,csr}
chmod 700 /opt/ca/server/client/private
chown -R root:root /opt/ca/server/client
# 初始化CA签发必需文件(记录签发信息)
touch /opt/ca/root/index.txt # 证书签发索引日志
echo 1000 > /opt/ca/root/serial # 证书序列号起始值(避免重复)
验证:执行以下命令确认目录结构完整:
ls -l /opt/ca/root/
预期输出:包含private/、certs/、csr/、newcerts/、index.txt、serial
二、步骤1:生成根CA私钥与自签证书
1. 生成根CA私钥(AES256加密)
进入根CA目录,生成加密私钥:
# 进入根CA目录
cd /opt/ca/root/
# 生成2048位AES256加密私钥
openssl genrsa -aes256 -out private/ca-root.key.pem 2048
# 权限锁死:仅root可读
chmod 400 private/ca-root.key.pem
交互说明:提示“Enter pass phrase”时,输入根CA密码(如CaRoot@2025!),务必牢记,丢失则所有后续证书无法签发/验证。
2. 生成根CA自签证书(有效期10年)
基于私钥生成自签证书(作为信任根,用于验证服务端/客户端证书):
openssl req -new -x509 -days 3650 -key private/ca-root.key.pem -out certs/ca-root.crt.pem
# 权限配置:全员可读(用于本地信任)
chmod 444 certs/ca-root.crt.pem
交互填写示例(开发环境简化,直接按如下输入):
Country Name (2 letter code) [AU]:CN
State or Province Name (full name) [Some-State]:YN
Locality Name (eg, city) []:KM
Organization Name (eg, company) [Internet Widgits Pty Ltd]:DevCA
Organizational Unit Name (eg, section) []:Offline
Common Name (e.g. server FQDN or YOUR name) []:LocalRootCA
Email Address []:dev@local.com
三、步骤2:生成NestJS服务端证书(私钥+CSR+CA签发)
1. 生成服务端私钥(无加密,启动免密)
# 进入服务端目录
cd /opt/ca/server/
# 生成服务端私钥
openssl genrsa -out private/server.key.pem 2048
# 权限:仅root可读
chmod 400 private/server.key.pem
2. 生成服务端CSR(证书请求文件)
openssl req -new -key private/server.key.pem -out csr/server.csr.pem
交互填写示例(Common Name必须为localhost,适配开发环境):
Country Name (2 letter code) [AU]:CN
State or Province Name (full name) [Some-State]:YN
Locality Name (eg, city) []:KM
Organization Name (eg, company) [Internet Widgits Pty Ltd]:DevServer
Organizational Unit Name (eg, section) []:NestJS
Common Name (e.g. server FQDN or YOUR name) []:localhost
// 这里要注意,如果是生产环境,使用域名或者服务器IP,本地开发用localhost
Email Address []:dev@local.com
A challenge password []:(直接回车,无需设置)
An optional company name []:(直接回车,无需设置)
3. 修正自定义CA配置文件
在根CA目录创建配置文件,适配服务端/客户端证书签发:
# 进入根CA目录
cd /opt/ca/root/
# 创建并写入配置
cat > my-ca.cnf << EOF
[ ca ]
default_ca = CA_default
[ CA_default ]
dir = /opt/ca/root
certs = $dir/certs
new_certs_dir = $dir/newcerts
database = $dir/index.txt
serial = $dir/serial
private_key = $dir/private/ca-root.key.pem
certificate = $dir/certs/ca-root.crt.pem
default_days = 365
default_md = sha256
preserve = no
policy = policy_anything
email_in_dn = no
rand_serial = no
[ policy_anything ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
# 服务端证书扩展
[ v3_server ]
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = DNS:localhost,IP:127.0.0.1
# 客户端证书扩展(新增,用于Vue3)
[ v3_client ]
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth
subjectAltName = DNS:localhost
EOF
4. 拷贝CSR并签发服务端证书
# 拷贝服务端CSR到CA目录
cp /opt/ca/server/csr/server.csr.pem /opt/ca/root/csr/
# 执行签发命令
openssl ca -config my-ca.cnf -extensions v3_server -days 365 -in csr/server.csr.pem -out certs/server.crt.pem
# 配置权限并拷贝到服务端目录
chmod 444 certs/server.crt.pem
cp certs/server.crt.pem /opt/ca/server/certs/
5. 签发交互流程与说明
| 终端提示 | 操作 | 解释 |
|---|---|---|
| Enter pass phrase for /opt/ca/root/private/ca-root.key.pem: | 输入根CA私钥密码 | 验证根CA权限,必须正确输入 |
| Sign the certificate? [y/n] | 输入 |
确认签发当前服务端证书请求 |
| 1 out of 1 certificate requests certified, commit? [y/n] | 输入 |
提交签发记录到index.txt日志 |
成功标志:终端输出,无报错。 |
四、步骤3:生成Vue3客户端证书(私钥+CSR+签发+p12转换)
1. 生成客户端私钥与CSR
# 进入客户端目录
cd /opt/ca/server/client/
# 生成客户端私钥
openssl genrsa -out private/client.key.pem 2048
chmod 400 private/client.key.pem
# 生成客户端CSR
openssl req -new -key private/client.key.pem -out csr/client.csr.pem
交互填写示例(Common Name自定义,标识客户端):
Country Name (2 letter code) [AU]:CN
State or Province Name (full name) [Some-State]:JS
Locality Name (eg, city) []:NJ
Organization Name (eg, company) [Internet Widgits Pty Ltd]:DevClient
Organizational Unit Name (eg, section) []:Vue3
Common Name (e.g. server FQDN or YOUR name) []:Vue3Client-Local
Email Address []:dev@local.com
A challenge password []:(直接回车)
An optional company name []:(直接回车)
2. 签发客户端证书
# 拷贝客户端CSR到CA目录
cp /opt/ca/server/client/csr/client.csr.pem /opt/ca/root/csr/
# 进入根CA目录执行签发
cd /opt/ca/root/
openssl ca -config my-ca.cnf -extensions v3_client -days 365 -in csr/client.csr.pem -out certs/client.crt.pem
# 配置权限并拷贝到客户端目录
chmod 444 certs/client.crt.pem
cp certs/client.crt.pem /opt/ca/server/client/certs/
交互流程:同服务端签发,输入根CA密码→输入→输入
y。
y
3. 转换为Vue3可用的p12格式
前端无法直接使用crt格式,转换为p12格式(含私钥和证书,带密码保护):
# 进入客户端目录
cd /opt/ca/server/client/
# 转换格式(-export指定导出为p12)
openssl pkcs12 -export -out certs/client.p12 -inkey private/client.key.pem -in certs/client.crt.pem
# 配置权限:全员可读
chmod 444 certs/client.p12
交互说明:提示“Enter Export Password”时,设置p12密码(如Vue3@2025!),牢记,Vue3配置时需使用。
五、步骤4:验证所有证书有效性(关键确认)
1. 验证根CA证书
openssl verify /opt/ca/root/certs/ca-root.crt.pem
成功输出:
/opt/ca/root/certs/ca-root.crt.pem: OK
2. 验证服务端证书(根CA签发合法性)
openssl verify -CAfile /opt/ca/root/certs/ca-root.crt.pem /opt/ca/server/certs/server.crt.pem
成功输出:
/opt/ca/server/certs/server.crt.pem: OK
3. 验证客户端证书
openssl verify -CAfile /opt/ca/root/certs/ca-root.crt.pem /opt/ca/server/client/certs/client.crt.pem
成功输出:
/opt/ca/server/client/certs/client.crt.pem: OK
4. 验证p12文件完整性
openssl pkcs12 -info -in /opt/ca/server/client/certs/client.p12 -noout
交互与成功标志:输入p12密码后,输出和
Certificate bag,无报错。
Private Key bag
六、步骤5:本地下载方法(虚拟机→本地)
核心前提
虚拟机IP:172.10.10.129(根据实际情况修改)
本地已创建证书存放目录(如Mac:/Users/xxx/dev/certs/;Windows:C:Usersxxxdevcerts)
使用root用户登录虚拟机(仅root有权限读取私钥)
1. 虚拟机内准备下载文件(解决权限问题)
# 复制所需文件到/tmp目录(宽松权限)
cp /opt/ca/root/certs/ca-root.crt.pem /tmp/
cp /opt/ca/server/private/server.key.pem /tmp/
cp /opt/ca/server/certs/server.crt.pem /tmp/
cp /opt/ca/server/client/certs/client.p12 /tmp/
# 临时放宽权限(仅用于下载)
chmod 644 /tmp/*
2. 本地执行下载命令
方案1:Mac/Linux本地终端
# 下载根CA公钥
scp root@172.10.10.129:/tmp/ca-root.crt.pem /Users/xxx/dev/certs/ca/
# 下载NestJS服务端文件
scp root@172.10.10.129:/tmp/server.key.pem /Users/xxx/dev/certs/nestjs/
scp root@172.10.10.129:/tmp/server.crt.pem /Users/xxx/dev/certs/nestjs/
# 下载Vue3客户端p12
scp root@172.10.10.129:/tmp/client.p12 /Users/xxx/dev/certs/vue3/
方案2:Windows PowerShell
# 下载根CA公钥
scp root@172.10.10.129:/tmp/ca-root.crt.pem C:Usersxxxdevcertsca
# 下载NestJS服务端文件
scp root@172.10.10.129:/tmp/server.key.pem C:Usersxxxdevcerts
estjs
scp root@172.10.10.129:/tmp/server.crt.pem C:Usersxxxdevcerts
estjs
# 下载Vue3客户端p12
scp root@172.10.10.129:/tmp/client.p12 C:Usersxxxdevcertsvue3/
3. 下载交互流程
| 终端提示 | 操作 |
|---|---|
| Are you sure you want to continue connecting (yes/no)? | 输入 |
| root@172.10.10.129’s password: | 输入虚拟机root密码 |
4. 下载后清理虚拟机临时文件(安全)
rm /tmp/ca-root.crt.pem /tmp/server.key.pem /tmp/server.crt.pem /tmp/client.p12
七、关键坑点总结
配置文件扩展错误:中
subjectAltName必须标注为
localhost,不能是
DNS:,OpenSSL对IP/域名类型校验极严格,错误会导致证书无法使用;
IP:
路径缺失/权限问题:CA目录必须包含private、certs等核心目录和index.txt、serial文件,私钥目录权限需设为700(仅root可读),否则会提示“文件不存在”或“权限拒绝”;
CSR信息匹配问题:开发环境建议将CA配置的设为
policy,放宽字段匹配规则,避免CSR信息与CA信息不一致导致签发失败;
policy_anything
前端证书格式问题:Vue3无法直接使用crt格式证书,必须转换为p12格式,转换时设置的密码需与前端配置一致,否则无法加载;
下载权限问题:直接下载/opt/ca目录下的文件可能因权限不足失败,建议先复制到/tmp目录并放宽权限,下载后及时清理临时文件。
八、最终可用文件清单
| 文件路径 | 用途 | 后续操作 |
|---|---|---|
| /opt/ca/root/certs/ca-root.crt.pem | 根CA公钥(验证证书合法性) | 拷贝到本地,导入浏览器/Node.js信任列表,同时拷贝到NestJS证书目录 |
| /opt/ca/server/private/server.key.pem | NestJS服务端私钥(解密/签名用) | 拷贝到NestJS证书目录,权限设为400(仅当前用户可读) |
| /opt/ca/server/certs/server.crt.pem | NestJS服务端证书(mTLS认证用) | 拷贝到NestJS证书目录,配置HTTPS时指定 |
| /opt/ca/server/client/certs/client.p12 | Vue3客户端证书(mTLS双向认证用) | 下载到本地,在Vue3项目中配置mTLS时导入,使用转换时设置的密码 |
