只需驗證簽名,檢查簽名者的證書是否真實,並確保鏈接導致受信任的根目錄是不夠的。任何驗證碼也必須確保證書持有者有權爲特定目的執行簽名。獲得具有smimeSign
特權的證書的審覈要比對代碼簽名證書進行審查嚴格得多。
想象一下,一家軟件開發公司,每位員工都已獲得電子郵件簽名和加密證書。該公司還發佈一個軟件產品,並提供其產品的PKCS#7簽名分發包。如果PKCS#7驗證功能沒有檢查簽名證書的用途(在這種情況下,我們想要codesign
),那麼公司僱用的壞角色可能會創建一個受損的軟件產品版本,並用它們簽名電子郵件證書(其中只有目的smimesign
。)
在OpenSSL的pkcs7_verify()
的情況下,API設計的明確要求一個暗示一個目的,而不是要傳遞的,並smimeSign
被選爲默認。我猜測由於S/MIME是PKCS#7最常見的用途,它是有道理的,它允許某人在大多數使用情況下驗證PKCS#7,而無需瞭解extendedKeyUsage
。
[不如我原來的答覆,以解決您的預編輯的問題「我可以指定我想驗證一個PKCS7簽名反對其他目的」:]
證書可以包含(可選的)稱爲「擴展密鑰使用」的屬性。該屬性用於指示允許使用哪種證書。一些可能X509.v3用法是:
- serverAuthentication
- clientAuthentication
- 代碼簽名
- emailProtection
- ipSecEndSystem
- ipSecTunnel
- 時間戳
- ocspSigning
- smartCardLogin
- pkiPeerAuth
您可以檢查x509v3_config手冊頁鍵使用標誌即OpenSSL是知道的。
PKCS#7是一種通用容器格式,允許對容器的內容進行簽名和/或加密。 S/MIME使用PKCS#7簽署和/或加密電子郵件消息,在這種情況下,使用的證書應具有emailProtection用法。
如果您想分發一些代碼,並且您希望確保收件人可以驗證發行版是否來自您並且保持不變,那麼可以使用PKCS#7進行發佈,在這種情況下,您的證書應該具有codeSigning增強密鑰用法屬性。 證書有可能具有多個密鑰用法,但總的來說,對於不同的使用類型有一個單獨的密鑰(以及因此證書)是一個好主意。
在命令行中,Openssl支持在使用「openssl smime」命令時指定證書的所需目的。例如,
openssl smime -verify -in myfile.p7b -inform DER -out my-p7-content -purpose any
將驗證文件「我file.p7p」的簽名,它會返回PKCS#7容器的文件「我-P7內容」的內容,它將接受任何有效證書,無論其指示的目的是什麼。 (用於任何)。請注意,smime的openssl手冊頁沒有列出作爲選項的-purpose開關,但確實支持它。
由於您以編程方式引用了PKCS7_verify API文檔,因此您可以在設置X509_STORE對象時通過X509_VERIFY_PARAM_set_purpose方法指定用途。下面的片段應該給你一個流程的概念:
X509_STORE store;
int purpose;
store = X509_STORE_new();
verify_params = X509_Store_get0_param(store);
purpose = X509_PURPOSE_get_by_sname("sslclient");
X509_VERIFY_PARAM_set_purpose(verify_params, purpose)
...
PKCS7_verify(..., store, ...);
這將在驗證時將目的設置爲SSL客戶端。
謝謝你的詳細解答;但我的問題不是**如何更改**驗證目的。這是關於**爲什麼我應該這樣做**。 (我更新了這個問題,以便更具體地說明這一點)。我的用例實際上就是您所指的:PKCS#7用於簽名軟件,簽名證書具有'KeyUsage = critical,digitalSignature'和'ExtendedKeyUsage = codeSigning'。 'PKCS7_verify()'在使用此證書籤名時失敗(如果我添加'smimesign'目的,則成功)。爲什麼這個功能總是需要一個特定的「目的」? – user3608247
@ user3608247我已更新我的答案以解決您編輯的問題。我在「如何」中留下了原始答案,因爲對於臨時用戶來說,如何以編程方式來做這件事並不是太明顯,對某些人可能會有用。 –