# 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.pem(CA证书)" 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. **证书分发** - 客户端证书应单独生成和分发 - 不要多个客户端共用同一个证书 --- **完成后,你将拥有自己的证书体系,可以用于生产环境!**