在上一篇中,我們已經學會如何透過私鑰與公鑰,為檔案產生「純簽章值」。然而,這種簽章方式並不會攜帶憑證資訊,驗簽者無法確定這把公鑰屬於誰。
因此,這一篇我們要進一步說明如何透過 PKCS#7 / CMS 格式 來產生 有封裝的數位簽章,讓簽章檔案同時包含憑證與簽章結果。
PKCS#7 (Public Key Cryptography Standards #7) 是一種常見的加密封裝格式,主要用來處理 數位簽章 和 加解密訊息。它在後續被標準化為 CMS (Cryptographic Message Syntax),並廣泛應用在:
與單純的「雜湊 + 私鑰簽章」不同,PKCS#7 不僅能保存簽章值,還能同時封裝簽章者的憑證,甚至包含中繼憑證、撤銷資訊等,讓驗簽更完整。
在 PKCS#7 中,常見的簽章封裝方式有兩種:
分離式 (Detached):簽章檔只存放簽章值與憑證,不包含原始檔案。驗簽時需要額外提供原始檔。適合需要保留原始檔案完整格式的情境,例如政府公文或合約。通常副檔名使用.p7s
。
內嵌式 (Attached):簽章檔同時包含原始檔案與簽章值。驗簽時只要有簽章檔就能驗證並還原原文,方便傳輸與歸檔。常見於 S/MIME 郵件簽章。通常副檔名使用.p7b
。
接下來,我們就來實作這兩種簽章模式。
在 PKCS#7 簽章裡,除了公私鑰之外,還需要一張憑證。這張憑證可以是由 CA 簽發的,也可以先用 自簽憑證 來練習。
# 產生私鑰 private.key
openssl genpkey -algorithm RSA -out private.key
# 產生公鑰 public.key
openssl rsa -pubout -in private.key -out public.key
# 產生憑證 cert.pem
openssl req -new -x509 -key private.key -out cert.pem -days 365
這張憑證 (cert.pem
) 會在簽章時附帶到 PKCS#7 檔案中。
假設我們要簽署的檔案是 document.txt
。
openssl smime -sign -in document.txt \
-signer cert.pem -inkey private.key \
-out document_detached.p7s -outform PEM
document_detached.p7s
只包含簽章與憑證,不包含原始檔。驗簽時需要額外提供 document.txt
。
openssl smime -sign -in document.txt \
-signer cert.pem -inkey private.key \
-out document_attached.p7m -outform PEM --nodetach
加上--nodetach
代表使用內嵌式,document_attached.p7m
同時包含原始檔與簽章內容。驗簽時不需要額外提供 document.txt
,只要有 .p7m
檔就能驗證並還原。
openssl smime -verify -in document_detached.p7s -inform PEM \
-content document.txt -noverify
由於分離式簽章不包含原始檔,驗證時候需要另外提供 document.txt
,由於使用自簽憑證,加上-noverify
,就不驗證憑證的有效性,但若是正式環境使用建議需驗證。
openssl smime -verify -in document_attached.p7m -inform PEM -noverify
使用內嵌式簽章,PKCS7就包含原始檔,因此驗簽時候不需要另外提供document.txt
驗證成功會回傳 Verification successful
如果文件被竄改或憑證不合法,OpenSSL 會回報錯誤。
產生的 .p7s
或 .p7m
檔案會長這樣:
-----BEGIN PKCS7-----
MIIG1QYJKoZIhvcNAQcCoIIGxjCCBsICAQExDzANBglghkgBZQMEAgMFADALBgkq
...
-----END PKCS7-----
這就是封裝後的簽章檔案,裡面包含簽章值與憑證。
這一篇我們學會了:
產生 私鑰、公鑰與自簽憑證
使用 OpenSSL 建立 PKCS#7 簽章
驗證簽章結果,確認文件完整性與憑證真實性
有了 PKCS#7 的封裝,我們就能把簽章與憑證綁在一起,提升數位文件的可攜性與安全性。
雙月食品社這家是立法院附近的美食,平日去就要大排長龍,知名的有滷肉飯與雞湯,雞湯太大碗,這次點瘦肉湯,湯真的超好喝,滷肉飯配上辣椒真是絕配,滷味也不錯