2024年9月17日 星期二

使用 PowerShell 一行指令自動生成自簽署證書

使用 PowerShell 一行指令自動生成自簽署證書


這是其他生成簽證的辦法

  1. 使用 openssl 自簽署SSL憑證證書
  2. 使用 powershell 自簽署SSL證書

第二個一樣用 powershell 但是是有簽署過程的,而本篇沒有簽署過程一行代碼直接完成全部,並自動儲存在 windwos 商店中,所以還需要多一個導出過程。





基於 SharePoint 的無應答登入模式改版後必須使用證書,這邊提供一個最簡證書生成方法,直接使用 PowerShell 5.1 內建的函式即可。

不過有以下兩個小缺點

  1. 無法匯出空白密碼的證書 pfx 檔案。(有這個需求用 OpenSSL 生成吧)
  2. 無法直接生成檔案,必須先存入 Windwos Certificate Store 匯出後再刪除


# 1. 定義変数
$CNName = "PnP_Roks"
$OutPath = "D:\mycertificates"
$ExpiryYears = 10
if(-not (Test-Path $OutPath)) { mkdir $OutPath }


# 2. 生成自簽署證書,存儲在當前用戶證書存儲區 (這一行就產好了)
$cert = New-SelfSignedCertificate -Subject "CN=$CNName" -DnsName $CNName `
  -CertStoreLocation Cert:\CurrentUser\My `
  -NotAfter (Get-Date).AddYears($ExpiryYears).date
$cert
# 3. 將證書安裝到受信任儲存區
$store = New-Object Security.Cryptography.X509Certificates.X509Store("Root", "LocalMachine")
$store.Open("ReadWrite"); $store.Add($cert); $store.Close()


# 4. 將證書公鑰導出為 CER 檔案 (需上傳到應用程式中)
$cert |Export-Certificate -FilePath "$OutPath\$CNName.cer"
# 5. 將證書導出為 PFX 檔案 (選用)
$Pword = "YourPasswordHere"
$cert |Export-PfxCertificate -FilePath "$OutPath\$CNName.pfx" `
  -Password (ConvertTo-SecureString -String $Pword -Force -AsPlainText)


# 6. 移除剛剛生成在個人儲存區的證書 (已經複製到信任區了這裡可以砍)
$cert | Remove-Item

這樣就生成完畢了,如果沒有移除證書的話可以在 certmgr.msc 中的 個人/憑證 區域找到該生成的證書。


需要上傳到 "應用程式" 中的只有 cer 證書而已,包含私鑰的 pfx 檔案不可以外洩。

比較理想的辦法是直接在目標伺服器生成證書,然後只匯出 cer 公鑰上傳到伺服器,一定程度避免私鑰產生副本。

環境允許的話甚至可以設置成不可匯出徹底銷毀,沒了再造一個就行。


上傳完畢接下來登入可以參考這篇 身份驗證 |PnP PowerShell




讀取證書檔案

其中如果要讀取 Store 中的 pfx 檔案可以這樣用

# 當前使用者
Get-Item -Path "Cert:\CurrentUser\My\$($cert.Thumbprint)"

# 本機
Get-Item -Path "Cert:\LocalMachine\My\$($cert.Thumbprint)"

對應的管理介面是

  • 當前用戶: certmgr.msc
  • 本機電腦: certlm.msc





匯出Linux格式

因為 PowerShell 不支援匯出 key 這個只能用第三方或是拿pwsh做了,這邊用 openssl 的範例從 pfx 轉換

導出 key 檔案

openssl pkcs12 -in "$CNName.pfx" -nocerts -nodes -out "$CNName.key"

導出 crt 檔案

openssl pkcs12 -in "$CNName.pfx" -clcerts -nokeys -out "$CNName.crt"

 

在 powershell 5.1 中似乎無法取出私鑰,即使用 Security.Cryptography.X509Certificates.X509Certificate2 取出來也是空值我就放棄了,改用 pwsh 或 openssl 吧

調查的結果好像是『 CNG (Cryptography Next Generation) vs CSP (CryptoAPI) 』的差異,PowerShell 5.1 只支援 CSP 缺了這個關鍵函式導致解不出來無法轉換




匯出Linux格式2

2025-07-16 這裡有個在微軟工作的大大寫的 pwsh 代碼可以直接產出
X509Certificate2 PowerShell module

產出來可以直接餵給 Nginx Proxy Manager 很方便

簡單的快速安裝腳本 (結尾的 chgs.com 是要註冊的網域)

& { param( [Parameter(Mandatory)][string]$cn, [switch]$force )

    # 檢查 PowerShell 版本
    if ($PSVersionTable.PSVersion.Major -lt 6) {
        Write-Error "❌ 此腳本需要 PowerShell 6.0 或更新版本。目前版本: $($PSVersionTable.PSVersion)" -EA Stop
    }

    # 檢查是否已有同 CN 的證書(比對 Subject)
    if (-not $force) {
        $store = New-Object Security.Cryptography.X509Certificates.X509Store("Root", "LocalMachine")
        $store.Open("ReadOnly")
        if ($store.Certificates | Where-Object { $_.Subject -eq "CN=$cn" }) {
            Write-Error "⚠ 已存在 CN=$cn 的證書,跳過安裝與匯出。" -EA Stop
        } $store.Close()
    }

    # 載入模組
    irm gist.githubusercontent.com/heaths/7b296f23e06156397bf2f07d69a64765/raw/841b2599ee45a096260454afdba89d21685c1ba0/X509Certificate2.psm1 | iex

    # 生成 SSL 證書
    $cert = New-X509Certificate2 -SubjectName "CN=$cn" -TLS -ValidDays 3650

    # 匯出 Linux 格式
    $cert | Export-X509Certificate2 "$cn.crt" -Type Certificate | Out-Null
    $cert | Export-X509Certificate2 "$cn.key" -Type PrivateKey | Out-Null

    # 安裝到信任區
    $store = New-Object Security.Cryptography.X509Certificates.X509Store("Root", "LocalMachine")
    $store.Open("ReadWrite"); $store.Add($cert); $store.Close()

    Write-Host "✅ 已成功產生並安裝 CN=$cn 的自簽憑證。"

} chgs.com





沒有留言:

張貼留言