# 一键生成证书并转换为C++代码
# 使用方法：powershell -ExecutionPolicy Bypass -File .\generate-and-convert.ps1

param(
    [string]$CertDir = ".\certs",
    [string]$ServerPass = "MyServerPass123",
    [string]$ClientPass = "MyClientPass123",
    [string]$Country = "CN",
    [string]$State = "Beijing",
    [string]$City = "Beijing",
    [string]$Organization = "MyCompany",
    [string]$OrgUnit = "IT",
    [string]$ServerCN = "localhost",
    [string]$ClientCN = "MyClient",
    [string]$CACN = "MyCA"
)

Write-Host "=====================================" -ForegroundColor Cyan
Write-Host "  HP-Socket SSL证书生成工具" -ForegroundColor Cyan
Write-Host "=====================================" -ForegroundColor Cyan
Write-Host ""

# 创建证书目录
if (Test-Path $CertDir) {
    Write-Host "警告: 目录 $CertDir 已存在" -ForegroundColor Yellow
    $confirm = Read-Host "是否删除并重新生成? (y/n)"
    if ($confirm -eq 'y') {
        Remove-Item -Recurse -Force $CertDir
    } else {
        Write-Host "已取消" -ForegroundColor Red
        exit
    }
}

New-Item -ItemType Directory -Force -Path $CertDir | Out-Null
Push-Location $CertDir

Write-Host "[1/5] 生成CA证书..." -ForegroundColor Green

# 生成CA私钥
openssl genrsa -out ca-key.pem 4096 2>&1 | Out-Null

# 生成CA证书
openssl req -new -x509 -days 3650 -key ca-key.pem -out ca-cert.pem `
    -subj "/C=$Country/ST=$State/L=$City/O=$Organization/OU=$OrgUnit/CN=$CACN" 2>&1 | Out-Null

Write-Host "✓ CA证书生成完成" -ForegroundColor Green

Write-Host "[2/5] 生成服务器证书..." -ForegroundColor Green

# 生成服务器私钥
openssl genrsa -aes256 -passout pass:$ServerPass -out server-key.pem 2048 2>&1 | Out-Null

# 生成服务器CSR
openssl req -new -key server-key.pem -passin pass:$ServerPass -out server-csr.pem `
    -subj "/C=$Country/ST=$State/L=$City/O=$Organization/OU=$OrgUnit/CN=$ServerCN" 2>&1 | Out-Null

# 签发服务器证书
openssl x509 -req -days 3650 -in server-csr.pem `
    -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem 2>&1 | Out-Null

Write-Host "✓ 服务器证书生成完成" -ForegroundColor Green

Write-Host "[3/5] 生成客户端证书..." -ForegroundColor Green

# 生成客户端私钥
openssl genrsa -aes256 -passout pass:$ClientPass -out client-key.pem 2048 2>&1 | Out-Null

# 生成客户端CSR
openssl req -new -key client-key.pem -passin pass:$ClientPass -out client-csr.pem `
    -subj "/C=$Country/ST=$State/L=$City/O=$Organization/OU=$OrgUnit/CN=$ClientCN" 2>&1 | Out-Null

# 签发客户端证书
openssl x509 -req -days 3650 -in client-csr.pem `
    -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out client-cert.pem 2>&1 | Out-Null

Write-Host "✓ 客户端证书生成完成" -ForegroundColor Green

Write-Host "[4/5] 验证证书..." -ForegroundColor Green

$serverVerify = openssl verify -CAfile ca-cert.pem server-cert.pem 2>&1
$clientVerify = openssl verify -CAfile ca-cert.pem client-cert.pem 2>&1

if ($serverVerify -like "*OK*" -and $clientVerify -like "*OK*") {
    Write-Host "✓ 证书验证通过" -ForegroundColor Green
} else {
    Write-Host "✗ 证书验证失败" -ForegroundColor Red
    Write-Host $serverVerify
    Write-Host $clientVerify
    Pop-Location
    exit 1
}

Write-Host "[5/5] 转换为C++代码..." -ForegroundColor Green

# 读取证书内容
$serverCert = Get-Content "server-cert.pem" -Raw
$serverKey = Get-Content "server-key.pem" -Raw
$clientCert = Get-Content "client-cert.pem" -Raw
$clientKey = Get-Content "client-key.pem" -Raw
$caCert = Get-Content "ca-cert.pem" -Raw

# 转换函数
function Convert-ToCppString {
    param([string]$content)
    
    $lines = $content -split "`n" | ForEach-Object { $_.TrimEnd("`r") }
    $cppLines = $lines | ForEach-Object { "`t`"$_\n`"" }
    return ($cppLines -join "`n")
}

$serverCertCpp = Convert-ToCppString $serverCert
$serverKeyCpp = Convert-ToCppString $serverKey
$clientCertCpp = Convert-ToCppString $clientCert
$clientKeyCpp = Convert-ToCppString $clientKey
$caCertCpp = Convert-ToCppString $caCert

# 生成C++头文件
$cppCode = @"
// ============================================
// SSL证书配置
// 自动生成时间: $(Get-Date -Format "yyyy-MM-dd HH:mm:ss")
// ============================================
//
// 证书信息:
//   CA CN: $CACN
//   服务器 CN: $ServerCN
//   客户端 CN: $ClientCN
//   有效期: 10年
//
// 使用说明:
//   1. 将此文件内容复制到 Server/main.cpp 和 Client/main.cpp 的证书定义部分
//   2. 服务器使用: g_s_lpszPemCert, g_s_lpszPemKey, g_s_lpszCAPemCert
//   3. 客户端使用: g_c_lpszPemCert, g_c_lpszPemKey, g_c_lpszCAPemCert
//   4. 修改密码: g_s_lpszKeyPassword, g_c_lpszKeyPassword
//
// ============================================

// CA证书（服务器和客户端共用）
static const char* g_s_lpszCAPemCert =
$caCertCpp;

// 服务器证书
static const char* g_s_lpszPemCert =
$serverCertCpp;

// 服务器私钥（密码保护）
static const char* g_s_lpszPemKey =
$serverKeyCpp;

// 服务器私钥密码
static const char* g_s_lpszKeyPassword = "$ServerPass";

// ============================================

// CA证书（客户端使用，与服务器相同）
static const char* g_c_lpszCAPemCert = g_s_lpszCAPemCert;

// 客户端证书
static const char* g_c_lpszPemCert =
$clientCertCpp;

// 客户端私钥（密码保护）
static const char* g_c_lpszPemKey =
$clientKeyCpp;

// 客户端私钥密码
static const char* g_c_lpszKeyPassword = "$ClientPass";

// ============================================
// 配置参数
// ============================================

// 服务器验证模式：要求客户端提供证书并验证
static const int g_s_iVerifyMode = SSL_VM_PEER | SSL_VM_FAIL_IF_NO_PEER_CERT;

// 客户端验证模式：验证服务器证书
static const int g_c_iVerifyMode = SSL_VM_PEER;

// 服务器监听地址和端口
static const LPCTSTR ADDRESS = _T("0.0.0.0");
static const USHORT PORT = 5555;

// 客户端连接地址和端口
static const LPCTSTR DEFAULT_ADDRESS = _T("127.0.0.1");
static const USHORT DEFAULT_PORT = 5555;
"@

$cppCode | Out-File -FilePath "certificates.h" -Encoding utf8 -NoNewline

Write-Host "✓ C++代码生成完成: certificates.h" -ForegroundColor Green

Pop-Location

# 生成摘要信息
Write-Host ""
Write-Host "=====================================" -ForegroundColor Cyan
Write-Host "  生成完成！" -ForegroundColor Cyan
Write-Host "=====================================" -ForegroundColor Cyan
Write-Host ""
Write-Host "证书目录: $CertDir" -ForegroundColor Yellow
Write-Host ""
Write-Host "生成的文件:" -ForegroundColor Yellow
Get-ChildItem $CertDir -Filter *.pem | Format-Table Name, @{Label="大小"; Expression={"{0:N0} bytes" -f $_.Length}}
Write-Host ""
Write-Host "下一步操作:" -ForegroundColor Cyan
Write-Host "  1. 查看 $CertDir\certificates.h" -ForegroundColor White
Write-Host "  2. 复制证书代码到 Server\main.cpp 和 Client\main.cpp" -ForegroundColor White
Write-Host "  3. 重新编译项目" -ForegroundColor White
Write-Host ""
Write-Host "快速查看C++代码:" -ForegroundColor Cyan
Write-Host "  notepad $CertDir\certificates.h" -ForegroundColor White
Write-Host ""
Write-Host "证书信息:" -ForegroundColor Cyan
Write-Host "  CA通用名称: $CACN" -ForegroundColor White
Write-Host "  服务器通用名称: $ServerCN" -ForegroundColor White
Write-Host "  客户端通用名称: $ClientCN" -ForegroundColor White
Write-Host "  服务器密钥密码: $ServerPass" -ForegroundColor White
Write-Host "  客户端密钥密码: $ClientPass" -ForegroundColor White
Write-Host "  证书有效期: 10年" -ForegroundColor White
Write-Host ""

# 询问是否打开certificates.h
$openFile = Read-Host "是否打开 certificates.h 文件? (y/n)"
if ($openFile -eq 'y') {
    notepad "$CertDir\certificates.h"
}
