隨著經歷鬼故事漸多,見識過光怪陸離的茶包,我解決日常電腦疑難雜症的速度也漸漸變快,印象中已很少被問題困住幾小時,而最近遇上的這隻足足耗掉我半天以上,算來都快接近下弦鬼了... Orz

一切始於 IIS 的鬼訊息,與自己用 PowerShell 呼叫 openssl 做 PFX 有關係,因為舊版 IIS 相容需求與不熟 Windows 憑證檢視工具,Vibe Coding 再加了一把助燃劑,種種巧合疊加在一起,才進化成刁鑽問題。

用之前寫的憑證簽署請求檔(CSR)指令工具產生 CSR,拿到 CA 簽好的憑證 (.cer) 併入私鑰轉成 PKCS12 格式 (.pfx),拿到目標主機安裝,輸入密碼成功將憑證匯入到「本機電腦/個人」區,到這裡一切都很正常:

但在設定 HTTPS 繫結時卻冒出「指定的登入工作階段不存在,可能已被終止」錯誤:

爬文發現,這個含糊的錯誤訊息很常見,主要是無法匯出私鑰,背後可能原因很多,像是未勾選「允許匯出此憑證」選項、憑證不是放在本機電腦/個人、權限設定不正確、憑證擴展屬性損壞... 等等。

類似操作之前做過,也確定密碼沒有敲錯,何況我的憑證都正確匯入「本機電腦/個人」區了啊~

反覆刪除重裝了好幾次結果都一樣,東試西試一陣子發現這張憑證跟正常憑證有個差異 - 使用「匯出」功能時無法包含私鑰,並會顯示「找不到關聯的私密金鑰,只能匯出憑證」:

所以問題出在 .pfx 的製作過程,該不會是 Make-PFX.ps1 工具有問題?改用手工輸入一模一樣的 openssl pkcs12 -export ... 指令,這回產生的 .pfx 就可以正常設定給 IIS 用。

接著又追了很久很久,總算真相大白。

問題一,為了確保跟舊版 Windows 相容,我參考之前 openssl 匯出 pfx 在 Windows 密碼百敲不過的經驗,依據 Stackoverflow 討論的討論建議加了 openssl pkcs12 -export -certpbe PBE-SHA1-3DES -keypbe PBE-SHA1-3DES -nomac .... 參數。而我沒有意識到其中的 -nomac 參數,會導致 Windows 忽略密碼檢查,一樣會彈出密碼視窗,若密碼敲錯一樣可以成功匯入不含私鑰的憑證,而且不會有任何提示。

所以問題出在密碼敲錯了?呃... 答案介於對與不對之間。我輸入的確是當初設定的密碼沒錯,卻不是正確的密碼。

問題二,Make-PFX.ps1 有個 Bug,以下這段程式有問題,而這段程是 Copilot 生給我的,當時覺得應該沒問題,就用了:

if ($LegacyIIS) {
    $pbeParams = "-certpbe PBE-SHA1-3DES -keypbe PBE-SHA1-3DES -nomac"
}
else {
    $pbeParams = ""
}
$cmd = "& `"$opensslPath`" pkcs12 -export $pbeParams -out `"$pfxPath`" -inkey `"$PrivKeyPath`" -in `"$pemPath`" -passout pass:$plainPasswd"
Invoke-Expression $cmd

問題出在 Invoke-Expression $cmd 寫法,一旦 $cmd 包含 $a 之類的文字,會被當成 PowerShell 變數解讀。而聰明如你,一定已經想到問題出在哪裡了,好死不死密碼中間有個 $,"xxx$xxx" 中的 $xxx 不存在置換成空字串,實際 .pfx 設定的密碼是 "xxx",再遇上 -nomac 不檢查密碼,Windows 沒匯入私鑰不吭聲,組成了一個迷宮讓我闖關。

但其實這種帶雙引號複雜參數的情境我之前研究過(PowerShell 傳遞含雙引號與空白的複雜參數給外部 EXE),按照文章中的兩種寫法都不會有此問題,但 Vibe Coding 程式都生成好了,跑起來也沒問題,我就沒多想。若是自己寫,我應會參考之前文章,用陣列組參數,算來也是因為用 AI 輔助寫 Code 才犯的錯。


Comments

# by 小黑

有點刺激

# by SY

讓我想起了我遇到的另一個情況 在寫k8s設定的時候,會遇到需要在 YAML 中嵌入 Go template 然後就是一場惡夢

# by

日前想用 powershell 匯入各 SSL 憑證讓 IIS 憑證更新自動化,直接匯入到 Web Hosting 還是會跳出 IIS 那意味不明的錯誤訊息,參考保哥的blog.miniasp.com/post/2011/08/14/How-to-import-SSL-certificate-to-IIS7-without-any-problem),最終還是全部好幾個站台都手動匯入才讓 IIS 能正常使用該憑證 到現在還沒搞懂手動匯入跟透過 powershell 匯入 SSL 憑證的差異在哪邊

Post a comment