在上一篇隨筆“記一次三方接口開發的數據加密方案”中,使用SHA256對數據進行簽名時,我提到了一個異常,System.Security.Cryptography.CryptographicException "Invalid algorithm specified.",中文為“指定的算法無效”。自己用openssl命令生成的證書沒有這個問題,但是網站上導出的免費證書不行,對此不想過多糾結。但是,后來使用從CFCA申請的證書,居然也不行,所以不得不對這個問題做了更深入的探究。順便以此為切入點,學習下使用openssl命令操作證書。
一、產生原因
針對證書私鑰采用SHA256算法對數據進行簽名時,報“指定的算法無效”這一異常,我查詢了不少資料,才找到問題原因,在百度上幾乎什么有用的信息也搜不出來,在google上翻閱了多篇文章,才弄清楚問題的根本。
實際原因是RSACryptoServiceProvider依賴底層CryptoAPI來完成其工作,只有CrytoAPI支持SHA256算法的Windows版本才會啟用此功能,這意味着它取決於我們用來執行加密操作的CSP(加密服務提供程序)。因為Microsoft CSP是在Rsaenh.dll上實現的,所以當我們使用SHA256對數據做簽名時,函數CryptCreateHash將在后台被CALG_SHA_256的ALG_ID調用。此加密API本身不執行加密操作。它將從應用程序獲得的參數重定向到所需的CSP,並且CSP代表它執行操作。所以我們得到的錯誤實際上來自於CSP。
因此,為了檢查我們是否可以使用SHA256,我們必須確保:
- 您的證書必須在支持SHA256的情況下生成。
- 用於生成證書的CSP必須支持SHA256。
二、解決方案
針對第1種情況,生成證書時我們會指定SHA256簽名算法,所以只要生成了證書就不會有問題。
我們的問題主要是出於第2種情況,生成證書指定的CSP要支持SHA256,而windows上默認導出生成的pfx文件,卻沒有顯式指定CSP。
我用openssl命令生成pfx時,指定了-CSP "Microsoft Enhanced RSA and AES Cryptographic Provider",所以為什么網站上申請的證書導出的pfx不支持SHA256,根本差異就在這里。
可以通過注冊表查看系統支持的CSP,位置在HKEY_LOCAL_MACHINE\Software\Microsoft\Cryptography\Defaults\Provider,如圖

所以最終,我們的思路就是拿到證書后,用openssl命令來重新生成pfx證書,在命令中指定CSP。
在線申請證書及導出后,我們擁有test.cer和test.pfx兩個證書文件。
然后使用以下三個命令導出新的pfx證書文件。
1 //step1,pfx轉pem 2 openssl pkcs12 -in test.pfx -nodes -out test.pem 3 //step2,pem轉key 4 openssl rsa -in test.pem -out test.key 5 //step3,合成新的pfx 6 openssl pkcs12 -export -in test.cer -inkey test.key -CSP "Microsoft Enhanced RSA and AES Cryptographic Provider" -out test2.pfx
最終重新生成的test2.pfx,就可以使用SHA256算法做私鑰簽名了。
openssl命令詳解:
- step1,pfx是包含公鑰和私鑰的二進制格式證書文件,有口令保護,所以執行命令時,會要求輸入密碼,導出的pem為base64編碼格式的證書文件,同樣包括公鑰和私鑰;
- step2,pem導出key,key為base64編碼的私鑰證書文件,rsa為密鑰的加密算法,如果是dsa,就寫dsa;
- step3,將base64編碼格式的cer和key文件,就是公鑰和私鑰文件,合成二進制格式pfx文件,指定CSP。這里的cer文件要求必須是base64編碼格式的,否則會報錯提示“unable to load certificates”,也就是說你的cer文件是二進制格式的。當然,這里輸入的公鑰采用base64編碼格式的pem公鑰文件也是可以的。
三、基礎知識
為了更好的理解學習操作證書的openssl命令,需要了解證書格式的一些基本知識。
CA中心普遍采用的規范是X.509系列和PKCS(Public Key Cryptography Standards)系列(證書格式系列標准含義很豐富,具體標准可自行查詢),主要用的證書格式標准:
-
x509,公鑰證書
-
pcks#12,描述個人信息交換語法標准,包含公鑰和私鑰,有口令保護
編碼方式:
- DER(二進制)編碼
- BASE64(ASCII)編碼
證書文件格式:
- csr,用於向CA申請簽名的請求文件格式
- cer或crt,公鑰證書,編碼方式不定,多用於Windows
- key,公鑰或私鑰,編碼方式不定
- pem,公或私或公私鑰,BASE64編碼格式,多用於Linux
- pfx,包括公私鑰,DER編碼二進制格式,多用於Windows
openssl常用命令知識:
- cer公鑰證書為x509標准格式,pfx私鑰證書為PKCS#12標准格式
- 公鑰是由私鑰生成的,openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
- 查看base64編碼格式公鑰證書,openssl x509 -in test.cer -noout -text
- Linux下多用pem格式,cer轉pem,openssl x509 -in test.cer -out test.pem
- 查看pfx私鑰證書,應先轉為pem格式,即由PKCS#12格式DER二進制編碼轉換為BASE64編碼后查看,openssl pkcs12 -in test.pfx -nodes -out test.pem
- 查看pem證書,openssl rsa -in test.pem -text
- -noout 參數即無文件輸出,-nodes 參數即無算法加密
參考(查到這篇文章直接解決了本文的問題):https://hintdesk.com/2011/07/29/c-how-to-fix-invalid-algorithm-specified-when-signing-with-sha256/
-- End
