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

11 KiB
Raw Permalink Blame History

OpenSSL证书生成完整指南

前提条件

确保已安装OpenSSL

证书生成步骤

第一步:创建证书目录

# 创建证书存放目录
mkdir E:\certs
cd E:\certs

第二步生成CA证书颁发机构

CA是用来签发服务器和客户端证书的根证书。

2.1 生成CA私钥

openssl genrsa -out ca-key.pem 4096

说明: 生成4096位的RSA私钥不加密

2.2 生成CA证书

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 生成服务器私钥(带密码)

openssl genrsa -aes256 -passout pass:15AnnUBW97opUIMA10 -out server-key.pem 2048

说明:

  • -aes256使用AES256加密私钥
  • -passout pass:15AnnUBW97opUIMA10:私钥密码(请修改为自己的密码)
  • 2048:密钥长度

3.2 生成服务器证书签名请求CSR

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签发服务器证书

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 生成客户端私钥(带密码)

openssl genrsa -aes256 -passout pass:1Annubw97opUIMA10 -out client-key.pem 2048

说明: 密码请修改为自己的密码

4.2 生成客户端证书签名请求CSR

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签发客户端证书

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证书

openssl x509 -in ca-cert.pem -text -noout

5.2 查看服务器证书

openssl x509 -in server-cert.pem -text -noout

5.3 验证证书链

# 验证服务器证书
openssl verify -CAfile ca-cert.pem server-cert.pem

# 验证客户端证书
openssl verify -CAfile ca-cert.pem client-cert.pem

应该输出: server-cert.pem: OKclient-cert.pem: OK

完整的PowerShell脚本

将以下内容保存为 generate-certs.ps1

# 证书生成脚本
$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 -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查看证书内容复制到代码

# 查看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 脚本:

$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 -ExecutionPolicy Bypass -File convert-to-cpp.ps1

然后复制 E:\certs\certificates.cpp 的内容到你的源代码中。

修改源代码

Server/main.cpp

找到证书定义部分第7-87行替换为新生成的证书

// 将新生成的证书内容替换这里
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行替换为新生成的证书

// 将新生成的证书内容替换这里
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";  // 改为你的密码

重新编译

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:

  • 服务器证书填写服务器域名或IPlocalhost192.168.1.100
  • 客户端证书:填写客户端标识(任意,如 MyClientClient001
  • CA证书填写CA名称任意MyCompanyCA

Q: 私钥密码可以不设置吗?

A: 可以。去掉 -aes256 -passout pass:xxx 参数,并在代码中将密码改为 nullptr

static const char* g_s_lpszKeyPassword = nullptr;

Q: 证书有效期到期怎么办?

A: 重新生成证书,或者生成时将 -days 3650 改为更大的值(如 7300 = 20年

Q: 如何批量生成多个客户端证书?

A: 修改脚本用循环生成多个客户端证书每个证书使用不同的CNClient001, Client002)。

安全建议

⚠️ 生产环境注意事项:

  1. 不要将私钥硬编码在源代码中

    • 使用配置文件或密钥管理系统
    • 使用 SetupSSLContext() 从文件加载
  2. 保护CA私钥

    • ca-key.pem 是最重要的文件
    • 应存放在安全的地方
    • 不要泄露给任何人
  3. 使用强密码

    • 不要使用 123456 这样的简单密码
    • 建议使用随机生成的复杂密码
  4. 定期更新证书

    • 建议每1-2年更新一次证书
    • 保持证书有效期在合理范围内
  5. 证书分发

    • 客户端证书应单独生成和分发
    • 不要多个客户端共用同一个证书

完成后,你将拥有自己的证书体系,可以用于生产环境!