Files
--hp-socket-TCP--ssl--/生成证书指南.md
2026-01-23 08:39:07 +08:00

362 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# OpenSSL证书生成完整指南
## 前提条件
确保已安装OpenSSL
- Windows从 https://slproweb.com/products/Win32OpenSSL.html 下载安装
- 或使用Git Bash自带的OpenSSL
## 证书生成步骤
### 第一步:创建证书目录
```powershell
# 创建证书存放目录
mkdir E:\certs
cd E:\certs
```
### 第二步生成CA证书颁发机构
CA是用来签发服务器和客户端证书的根证书。
#### 2.1 生成CA私钥
```bash
openssl genrsa -out ca-key.pem 4096
```
**说明:** 生成4096位的RSA私钥不加密
#### 2.2 生成CA证书
```bash
openssl req -new -x509 -days 3650 -key ca-key.pem -out ca-cert.pem -subj "/C=CN/ST=Beijing/L=Beijing/O=Myself/OU=IT/CN=MyCA"
```
**说明:**
- `-days 3650`证书有效期10年
- `-subj`:证书主题信息(可以修改)
- `C`国家代码CN=中国)
- `ST`:省份
- `L`:城市
- `O`:组织名称
- `OU`:部门
- `CN`通用名称CA名称
### 第三步:生成服务器证书
#### 3.1 生成服务器私钥(带密码)
```bash
openssl genrsa -aes256 -passout pass:15AnnUBW97opUIMA10 -out server-key.pem 2048
```
**说明:**
- `-aes256`使用AES256加密私钥
- `-passout pass:15AnnUBW97opUIMA10`:私钥密码(请修改为自己的密码)
- `2048`:密钥长度
#### 3.2 生成服务器证书签名请求CSR
```bash
openssl req -new -key server-key.pem -passin pass:15AnnUBW97opUIMA10 -out server-csr.pem -subj "/C=CN/ST=Beijing/L=Beijing/O=MyCompany/OU=IT/CN=localhost"
```
**说明:**
- `CN=localhost`服务器地址如果用IP访问改为IP地址
#### 3.3 用CA签发服务器证书
```bash
openssl x509 -req -days 3650 -in server-csr.pem -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem
```
**说明:** 使用CA证书和CA私钥签发服务器证书
### 第四步:生成客户端证书
#### 4.1 生成客户端私钥(带密码)
```bash
openssl genrsa -aes256 -passout pass:1Annubw97opUIMA10 -out client-key.pem 2048
```
**说明:** 密码请修改为自己的密码
#### 4.2 生成客户端证书签名请求CSR
```bash
openssl req -new -key client-key.pem -passin pass:1Annubw97opUIMA10 -out client-csr.pem -subj "/C=CN/ST=Beijing/L=Beijing/O=MyCompany/OU=IT/CN=MyClient"
```
#### 4.3 用CA签发客户端证书
```bash
openssl x509 -req -days 3650 -in client-csr.pem -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out client-cert.pem
```
### 第五步:验证证书
#### 5.1 查看CA证书
```bash
openssl x509 -in ca-cert.pem -text -noout
```
#### 5.2 查看服务器证书
```bash
openssl x509 -in server-cert.pem -text -noout
```
#### 5.3 验证证书链
```bash
# 验证服务器证书
openssl verify -CAfile ca-cert.pem server-cert.pem
# 验证客户端证书
openssl verify -CAfile ca-cert.pem client-cert.pem
```
**应该输出:** `server-cert.pem: OK``client-cert.pem: OK`
## 完整的PowerShell脚本
将以下内容保存为 `generate-certs.ps1`
```powershell
# 证书生成脚本
$certDir = "E:\certs"
New-Item -ItemType Directory -Force -Path $certDir
Set-Location $certDir
Write-Host "==== 1. 生成CA证书 ====" -ForegroundColor Green
# 生成CA私钥
openssl genrsa -out ca-key.pem 4096
# 生成CA证书10年有效期
openssl req -new -x509 -days 3650 -key ca-key.pem -out ca-cert.pem `
-subj "/C=CN/ST=Beijing/L=Beijing/O=MyCompany/OU=IT/CN=MyCA"
Write-Host "==== 2. 生成服务器证书 ====" -ForegroundColor Green
# 生成服务器私钥密码MyServerPass123
openssl genrsa -aes256 -passout pass:MyServerPass123 -out server-key.pem 2048
# 生成服务器CSR
openssl req -new -key server-key.pem -passin pass:MyServerPass123 -out server-csr.pem `
-subj "/C=CN/ST=Beijing/L=Beijing/O=MyCompany/OU=IT/CN=localhost"
# 签发服务器证书
openssl x509 -req -days 3650 -in server-csr.pem `
-CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem
Write-Host "==== 3. 生成客户端证书 ====" -ForegroundColor Green
# 生成客户端私钥密码MyClientPass123
openssl genrsa -aes256 -passout pass:MyClientPass123 -out client-key.pem 2048
# 生成客户端CSR
openssl req -new -key client-key.pem -passin pass:MyClientPass123 -out client-csr.pem `
-subj "/C=CN/ST=Beijing/L=Beijing/O=MyCompany/OU=IT/CN=MyClient"
# 签发客户端证书
openssl x509 -req -days 3650 -in client-csr.pem `
-CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out client-cert.pem
Write-Host "==== 4. 验证证书 ====" -ForegroundColor Green
openssl verify -CAfile ca-cert.pem server-cert.pem
openssl verify -CAfile ca-cert.pem client-cert.pem
Write-Host "`n==== 证书生成完成! ====" -ForegroundColor Green
Write-Host "文件列表:" -ForegroundColor Yellow
Get-ChildItem -Filter *.pem | Format-Table Name, Length, LastWriteTime
Write-Host "`n接下来:" -ForegroundColor Cyan
Write-Host "1. 查看 ca-cert.pemCA证书"
Write-Host "2. 查看 server-cert.pem 和 server-key.pem服务器证书和私钥"
Write-Host "3. 查看 client-cert.pem 和 client-key.pem客户端证书和私钥"
Write-Host "4. 将证书内容替换到源代码中"
```
## 执行脚本
```powershell
# 执行生成脚本
powershell -ExecutionPolicy Bypass -File generate-certs.ps1
```
## 生成的文件说明
执行完成后,`E:\certs\` 目录下会有:
| 文件名 | 说明 | 用途 |
|--------|------|------|
| `ca-key.pem` | CA私钥 | 签发证书用(保密) |
| `ca-cert.pem` | CA证书 | 验证其他证书(公开) |
| `server-key.pem` | 服务器私钥 | 服务器解密用保密密码MyServerPass123 |
| `server-cert.pem` | 服务器证书 | 服务器身份证明(公开) |
| `server-csr.pem` | 服务器CSR | 证书请求文件(可删除) |
| `client-key.pem` | 客户端私钥 | 客户端解密用保密密码MyClientPass123 |
| `client-cert.pem` | 客户端证书 | 客户端身份证明(公开) |
| `client-csr.pem` | 客户端CSR | 证书请求文件(可删除) |
| `ca-cert.srl` | 序列号文件 | CA签发证书的序列号保留 |
## 将证书嵌入到源代码
### 方法1查看证书内容复制到代码
```powershell
# 查看CA证书
Get-Content E:\certs\ca-cert.pem
# 查看服务器证书
Get-Content E:\certs\server-cert.pem
# 查看服务器私钥
Get-Content E:\certs\server-key.pem
# 查看客户端证书
Get-Content E:\certs\client-cert.pem
# 查看客户端私钥
Get-Content E:\certs\client-key.pem
```
### 方法2自动生成C++代码(推荐)
创建 `convert-to-cpp.ps1` 脚本:
```powershell
$certDir = "E:\certs"
$outputFile = "$certDir\certificates.cpp"
$serverCert = Get-Content "$certDir\server-cert.pem" -Raw
$serverKey = Get-Content "$certDir\server-key.pem" -Raw
$clientCert = Get-Content "$certDir\client-cert.pem" -Raw
$clientKey = Get-Content "$certDir\client-key.pem" -Raw
$caCert = Get-Content "$certDir\ca-cert.pem" -Raw
$cppCode = @"
// 自动生成的证书代码
// 生成时间: $(Get-Date -Format "yyyy-MM-dd HH:mm:ss")
// 服务器证书
static const char* g_s_lpszPemCert =
"$($serverCert -replace "`r`n", "\n" -replace "\n", "\n`t`"" -replace "`"$", "`";")
// 服务器私钥密码MyServerPass123
static const char* g_s_lpszPemKey =
"$($serverKey -replace "`r`n", "\n" -replace "\n", "\n`t`"" -replace "`"$", "`";")
// 客户端证书
static const char* g_c_lpszPemCert =
"$($clientCert -replace "`r`n", "\n" -replace "\n", "\n`t`"" -replace "`"$", "`";")
// 客户端私钥密码MyClientPass123
static const char* g_c_lpszPemKey =
"$($clientKey -replace "`r`n", "\n" -replace "\n", "\n`t`"" -replace "`"$", "`";")
// CA证书服务器和客户端共用
static const char* g_s_lpszCAPemCert =
"$($caCert -replace "`r`n", "\n" -replace "\n", "\n`t`"" -replace "`"$", "`";")
static const char* g_c_lpszCAPemCert = g_s_lpszCAPemCert;
// 密钥密码
static const char* g_s_lpszKeyPassword = "MyServerPass123";
static const char* g_c_lpszKeyPassword = "MyClientPass123";
"@
$cppCode | Out-File -FilePath $outputFile -Encoding utf8
Write-Host "C++代码已生成: $outputFile" -ForegroundColor Green
```
执行:
```powershell
powershell -ExecutionPolicy Bypass -File convert-to-cpp.ps1
```
然后复制 `E:\certs\certificates.cpp` 的内容到你的源代码中。
## 修改源代码
### Server/main.cpp
找到证书定义部分第7-87行替换为新生成的证书
```cpp
// 将新生成的证书内容替换这里
static const char* g_s_lpszPemCert = "...新的服务器证书...";
static const char* g_s_lpszPemKey = "...新的服务器私钥...";
static const char* g_s_lpszCAPemCert = "...新的CA证书...";
static const char* g_s_lpszKeyPassword = "MyServerPass123"; // 改为你的密码
```
### Client/main.cpp
找到证书定义部分第7-99行替换为新生成的证书
```cpp
// 将新生成的证书内容替换这里
static const char* g_c_lpszPemCert = "...新的客户端证书...";
static const char* g_c_lpszPemKey = "...新的客户端私钥...";
static const char* g_c_lpszCAPemCert = "...新的CA证书...";
static const char* g_c_lpszKeyPassword = "MyClientPass123"; // 改为你的密码
```
## 重新编译
```powershell
cd "E:\开发\C_C++\hp-socket-6.0.4\hp-socket-6.0.7-src\Windows\Demo\TestEcho-SSL-Console"
& "D:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\MSBuild.exe" TestEcho-SSL-Console.sln /p:Configuration=Debug /p:Platform=x64
```
## 测试新证书
运行服务器和客户端,如果看到:
```
[服务器] SSL环境初始化成功
[客户端] SSL环境初始化成功
[客户端] OnHandShake - SSL握手完成
```
说明新证书工作正常!
## 常见问题
### Q: 生成证书时需要输入密码吗?
A: 不需要。脚本中使用 `-passout pass:xxx` 自动指定密码。如果想手动输入,去掉 `-passout` 参数。
### Q: CN通用名称应该填什么
A:
- 服务器证书填写服务器域名或IP`localhost``192.168.1.100`
- 客户端证书:填写客户端标识(任意,如 `MyClient``Client001`
- CA证书填写CA名称任意`MyCompanyCA`
### Q: 私钥密码可以不设置吗?
A: 可以。去掉 `-aes256 -passout pass:xxx` 参数,并在代码中将密码改为 `nullptr`
```cpp
static const char* g_s_lpszKeyPassword = nullptr;
```
### Q: 证书有效期到期怎么办?
A: 重新生成证书,或者生成时将 `-days 3650` 改为更大的值(如 `7300` = 20年
### Q: 如何批量生成多个客户端证书?
A: 修改脚本用循环生成多个客户端证书每个证书使用不同的CN`Client001`, `Client002`)。
## 安全建议
⚠️ **生产环境注意事项:**
1. **不要将私钥硬编码在源代码中**
- 使用配置文件或密钥管理系统
- 使用 `SetupSSLContext()` 从文件加载
2. **保护CA私钥**
- `ca-key.pem` 是最重要的文件
- 应存放在安全的地方
- 不要泄露给任何人
3. **使用强密码**
- 不要使用 `123456` 这样的简单密码
- 建议使用随机生成的复杂密码
4. **定期更新证书**
- 建议每1-2年更新一次证书
- 保持证书有效期在合理范围内
5. **证书分发**
- 客户端证书应单独生成和分发
- 不要多个客户端共用同一个证书
---
**完成后,你将拥有自己的证书体系,可以用于生产环境!**