PKCS#7 SignedData - 如何為 RSAES-PKCS-v1_5 建構“encryptedDigest”?
我需要使用 Azure Key Vault HSM 對 PKCS#7 CMS 中的任意數據進行簽名。如果你為它們提供私鑰,有很多庫和包可以做到這一點,但顯然我不想從 HSM 導出私鑰,所以我在 C# 中建構了我自己的 PKCS#7 對象作家。
我使用 ITU-T 規範作為參考:https ://www.itu.int/ITU-T/formal-language/itu-t/x/x420/1999/PKCS7.html#PKCS7.signed-data
一切都很順利,直到我到達 SignerInfo 的“encryptedDigest”部分。我需要知道它是如何構造的,以便我可以將它注入到我的 PKCS#7 中。
根據我對上述參考資料、相關 RFC 以及在此類論壇上發現的大量類似建議的理解,我嘗試了很多不同的方法來建構它,但我永遠無法創建“有效”簽名。
根據我的最新理解,摘要資訊的構造如下:
DigestInfo Sequence { DigestAlgorithm Sequence{ algorithm OID; } Digest Sequence { AlgorithmIdentifier Sequence { algorithm OID; } hashValue BitString; } }
其中 hashValue 是 authenticatedAttributes 的雜湊值(其中包括其自身要簽名的數據雜湊值(均在 SHA256 中進行雜湊處理))
整個 DigestInfo 對象經過 BER 編碼,然後根據 RSAES-PKCS-v1_5 使用私鑰加密,並在 PKCS#7 的末尾放入一個 OctetString。
當我將我的 PKCS#7 導入驗證工具時,它看起來都是正確的,並且 PKCS#7 的整個結構與我擁有的具有有效簽名的範例 PKCS#7 的結構相匹配。但是,當我嘗試驗證我的 PKCS#7 的簽名時,它返回無效。
我假設我的 hashValue 中的數據是錯誤的(我看過關於不包括 ASN1Tag 的文章
$$ 0 $$和這個authenticatedAttributes的長度,但這仍然不起作用)或者我上面的DigestInfo結構是錯誤的,也許我需要為算法中的可選參數寫入空字節? 任何見解將不勝感激! 編輯=================================================
戴夫,這是很多有用的資訊,非常感謝。但是我仍在生成無效簽名。我已經根據您引用的 RFC 修改了我的 DigestInfo 對象,包括參數值的 Null 字節,並將其設置為 DER:
Base64 of actual object with data: MDEwDQYJYIZIAWUDBAIBBQAEIFFbecM/Y/Kw1qRLyqJn4VfXLoHebSpj9bVSy2V77pdc DigestInfo Sequence { DigestAlgorithm Sequence{ algorithm OID (SHA256: 2.16.840.1.101.3.4.2.1); parameters NULL; } digest OctetString (bytes in base64 below hashed); }
我將 A0 字節換成了 SET 標籤的第 31 個字節,這是我正在散列的 ASN1 的基數 64(prehash):
MWkwGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMjIwOTEwMTExNjE4WjAvBgkqhkiG9w0BCQQxIgQg0dbdNJbW+Q5yalayQ0T4oBRhfvsTBtGEBLtSBf7C7PM=
因此,如果所有這些都是正確的,那麼這個問題就在於我實際上是如何簽名的,而且由於這發生在 Azure 上,我對它沒有太多的控制權。我目前要求 Azure 使用 RS256 對 ASN1 digestInfo(top base64)的字節進行簽名 - 使用 SHA-256 的 RSASSA-PKCS-v1_5。似乎 Azure 對 digestInfo 對象進行雜湊處理以使其成為 32 字節,然後使用儲存在 HSM 上的私鑰對其進行簽名。
ITU 可能會提供有關 PKCS(和 CMS)的資訊,但他們不是作者。PKCS7(與所有 PKCS 一樣)最初來自 RSALabs,現在仍可作為rfc2315 使用;CMS 的幾個版本 - 開始時幾乎但不完全相同,然後逐漸添加新功能 -只是RFC:rfc2630 rfc3369 rfc3852 rfc5652。
首先,“加密摘要”和“摘要加密”是用詞不當:簽名不是加密;在https://security.stackexchange.com/questions/159282/上查看我關於隔壁的連結列表。這個術語是在 PKCS1 v1 中試圖變得聰明,結果適得其反。它在 PKCS1 v2(2.0、2.1 和 2.2)中得到更正,但 PKCS7 已被 CMS 取代,CMS 也對其進行了更正。
特別是這裡沒有使用 RSAES-PKCS1-v1_5;而是 PKCS7 簽名在 PKCS1 v1 中使用所謂的“塊類型 1”——雖然在 rfc2315 中未引用,但也重新發佈為rfc2313——並在 PKCS1 v2(RFC 2437、3447、8017)中使用了改名 RSASSA-PKCS1-v1_5,用於現在大多數實現。(CMS 繼續為 RSA 使用 RSASSA-PKCS1-v1_5,但添加了其他非 RSA 算法,RSALabs 在負責時沒有這樣做的動機。)
DigestInfo 結構在 rfc2315 的第 9.4 節中有詳細規定;這是(並且說是)PKCS1 的副本,特別是 rfc2313 中的第 10.1.2 節,根本不是你所擁有的。PKCS1 v2 更改了此材料的呈現方式(不止一次!),例如rfc3447 第 9.2 節顯示 DigestInfo 的 DER(不僅僅是 BER)編碼實際上只是一個前綴,它僅取決於與雜湊值連接的雜湊算法。(由於簽名取決於具有完全相同的位,並且 DER 的全部目的是產生適合簽名的相同位,所以完全不清楚為什麼 v1 只為如此小的數據指定 BER,任何理智的人都不會想要無限期編碼. PKCS1 v2.0 僅在 PKCS7 更改為 DER 幾個月後,甚至沒有將其標記為更改。)
在 X.509 的整個生命週期中,沒有參數的算法的 AlgorithmIdentifier 是否應該忽略它們或顯式編碼 NULL 並沒有始終如一的明確,這導致了很多問題。對於 PKCS1 RSA 簽名中的 DigestInfo, rfc3447 et seq 將它們顯式顯示為 NULL,這就是每個人所做的。
我看過關於不包括 ASN1Tag 的文章
$$ 0 $$和authenticatedAttributes的長度$$ the hash input $$
正確的表述是你應該散列authenticatedAttributes(在CMS 中重命名為signedAttributes)的編碼,沒有’implicit context-0’ 標籤,但有’natural’ SET 標籤——即31而不是A0。也許您或某人對不包括標籤和長度的電子內容的散列感到困惑。比較(披露:我的)PKCS#7 CMS - 消息摘要計算過程。