6  SSDF:合規框架其實是驗收標準

第一部收工時我說「工具都在手上了,我們去工地」。到了工地,第一個迎接你的通常不是機具, 是一疊文件——合規框架。對多數工程師,這是眼皮最重的時刻:NIST SSDF、各種標準、 一頁又一頁的「應」與「必須」。

先預測:你覺得「合規框架」本質上是什麼?一份「做了就打勾」的清單嗎?

這一章想說服你一個相反的讀法:合規框架不是清單,是驗收標準——它規定「產線的每一段, 該由第一部的哪個原語承重、驗收時要驗到什麼程度」。清單思維問「這項做了沒」; 驗收思維問「這項要求底下是哪個原語在承重、那個原語的能力邊界罩不罩得住這裡的威脅」。 讀懂這一層,合規文件會從「稽核要看的東西」變成「你設計 pipeline 時的規格書」。 第二部整卷都用這個讀法。

6.1 SSDF 長什麼樣:四大類

NIST SSDF(Secure Software Development Framework,安全軟體開發框架,SP 800-218) (National Institute of Standards and Technology 2022年) 把安全開發拆成四大類:

全名 管什麼
PO Prepare the Organization(備妥組織) 人、流程、工具鏈先到位
PS Protect the Software(保護軟體) 原始碼與成品不被竄改——本章主角
PW Produce Well-Secured Software(安全地產出) 設計審查、安全編碼、測試
RV Respond to Vulnerabilities(回應漏洞) 找到、修掉、追根因

四類裡,跟第一部三個原語直接對上的是 PS 群組——它底下三條實務(practice) 剛好是「碼 → 成品 → 溯源」三段,一段一個考點。本章逐條走。其餘三類當然重要, 但它們多半是流程與人的問題;這本書的鏡頭,對準密碼學能承重的那段。

6.2 PS.1:保護原始碼——hash 給不了的那一塊

PS.1 要求保護所有形式的 code(原始碼、設定、IaC、執行檔)不被未授權存取與竄改。 它有兩半:存取控制那半(最小權限、版本控管、稽核日誌)不是密碼學問題,治理工具管得好好的; 防竄改那半,才是簽章上場的地方——具體形式是 signed commits / signed tags

先預測:git 每個 commit 本來就有 hash,而且每個 commit 鏈著 parent 的 hash—— 整個 repo 根本是一條 hash 鏈。那為什麼還需要簽 commit?hash 鏈不是已經保證 「歷史沒被改」了嗎?

回到第 5 章那張能力邊界表的第一列:hash 給完整性,不給身分。git 的 hash 鏈保證的是 「這串歷史內部自洽」——但任何人都能製造一條完全自洽的假歷史,作者欄想填誰就填誰 (git commit 的 author 是自由文字,git 不驗)。hash 回答得了「內容有沒有被改」, 回答不了「這段 code 是不是這個人寫的」。要身分,就得上簽章:signed commit = 開發者用私鑰對 commit 內容簽名,任何人可拿公鑰驗出「這個 commit 出自這把鑰匙的持有者」。 PS.1 的防竄改要求,承重的原語就是第 2 章的數位簽章,一個零件都沒換。

6.2.1 那把開發者私鑰,憑什麼「算數」?

先破一個直覺:私鑰怎麼「產生」,跟它合不合法無關gpg --gen-key 一秒生一對, 人人能生——跟第 3 章「自簽 root 不等於可信」同一道理,生成本身給不了任何可信度。 「合法」問的是:憑什麼別人相信「這把公鑰=這位被授權的開發者」?這是身分綁定問題, 實務上有三種模型:

模型 做法 信任錨點
平台註冊型(GitHub/GitLab 等) 本地生 key,公鑰上傳到已認證的帳號 那個平台帳號(密碼+2FA)
組織 PKI 型(典型金融機構) 企業 CA 在入職、完成身分核實後核發 code-signing 憑證 組織 CA/企業身分系統
Keyless 型(Sigstore) OIDC/SSO 登入換短命憑證,簽完即丟 組織已經在信的 SSO

三條路殊途同歸:往下剝,鏈的底部都踩在身分核實(identity proofing)+到職程序 這個人為決定上。第 3 章的結論在產線第一站就現形了——密碼學只是把「這個人是我們的開發者」 這個授予動作固定下來,授予本身是 HR 和資安做的。

最後一哩是保管:一把「合法」的私鑰若外洩,別人就能冒充你簽。開發者端的最佳實務是讓 key 在硬體內生成、不可匯出——例如 YubiKey 這類硬體金鑰(私鑰永遠不出晶片)。 「簽章金鑰放哪」這個題目在產線端會更尖銳,整個第 8 章都在處理它。

6.2.2 地端平台的一個常見缺口

警告標註推論:依平台與版本而異

以我接觸過的環境歸納:不少典型金融機構的地端 DevOps 平台,git client 端簽 commit 沒問題,但平台 UI 不驗、也不顯示簽章驗證結果(不像某些雲端平台有 “Verified” 徽章)。 這代表「大家都有簽」跟「有人在驗」是兩回事——第 5 章的老話:簽了沒人驗,等於沒簽。 補法很樸素:在 pipeline 加一步 git verify-commitgit verify-tag,驗不過就 fail。 這段是經驗歸納,不是對任何產品的斷言——落地前,請對你手上的平台與版本實測。

6.3 PS.2:成品的完整性驗證——給下游一個「驗」的辦法

PS.2 要求:對外發布的每個成品(release artifact),要提供下游驗證其完整性的機制。 注意措辭——不是「你自己保護好」,是「給下游一個驗的辦法」。這幾乎是第一部工具箱的 直接應用:

  • hash/checksum(SHA-256)=完整性:下游比對,確認拿到的跟發布的是同一包 bytes。 但別忘了第 5 章的警告:跟成品擺在同一個網頁上的 hash 只防傳輸壞掉,不防掉包—— hash 要有安全意義,必須經由另一條可信通道到達,而那條通道講到底就是簽章。
  • 數位簽章(例如 cosign 簽 container image)=真實性+不可否認:下游用你的公鑰驗。
  • 下游憑什麼信你的公鑰?——第 3 章整章的問題原封不動回來:驗到哪個錨點? 企業內部通常是「組織 CA 發的憑證」或「公鑰經由受控通道預先散佈」。

PS.2 還埋著一個容易被讀成套話、其實是硬規格的要求:下游要能確認「拿到的=當初發布的 那份」。這句話展開,就是下一章的主戰場——同一包 bytes 用 digest(雜湊值)定址, 從測試環境一路晉級到正式環境都不重新 build,四個環境看到同一個 digest。這裡先掛個牌子, 第 7 章實作。

6.4 PS.3:封存與溯源——To: Bob 的產線版

PS.3 要求:封存每個發布版本,並保存其來源證明(provenance)。兩個關鍵字:

  • SBOM(Software Bill of Materials,軟體物料清單):這個成品由哪些成分組成、 各來自哪裡——序章 Log4Shell 那個「我們到底哪裡用了 log4j」的問題,SBOM 就是答案的載體。
  • Provenance/attestation(來源證明/簽章聲明),如 SLSA provenance、in-toto attestation (Torres-Arias 等 2019年):一份被簽章的聲明——「這個成品是由這份原始碼、 這個 builder、這條 pipeline,在這個時間建出來的」。

先預測:provenance 用到的是哪個原語?有沒有新魔法?

沒有。它就是簽章——只是被簽的內容不是成品本身,而是建置的情境(metadata)。 認出這個結構了嗎?第 4 章的教訓:光簽 msg 不夠,要把 From: Alice, To: Bob 簽進去。 產線上的對應:光簽「artifact 的 hash」不夠,要把「哪個 commit、哪條 pipeline、何時 build」 一起綁進被簽的內容。PS.3 是 To: Bob 教訓的產線版——密碼學只保護你餵給它的 bytes, 你要它保證的情境,就得寫進被簽的內容裡。

封存則是把「簽章+hash+SBOM+provenance」整包存下來,讓多年後仍能重驗歷史版本—— 稽核場景裡這叫證據鏈,密碼學視角裡這叫「驗章所需的全部輸入都要留著」。

6.5 收束:PS 群組一張表

保護對象 承重的原語 原語管不到的(人為決定)
PS.1 原始碼 簽章(signed commits)——hash 鏈只給完整性,身分要簽章 開發者身分核實與 onboarding;存取控制;有沒有人在驗
PS.2 成品 hash(digest 定址)+簽章(成品簽章) 公鑰散佈走哪條可信通道;錨點是誰
PS.3 溯源與封存 簽章(簽的是建置 metadata)+hash 聲明的內容涵蓋哪些情境;封存保多久、誰能動

一句話收束:SSDF 的 PS 群組沒有新魔法——它是把「hash=完整性」×「簽章=真實性+ 不可否認」×「PKI=信任分發」套到「碼(PS.1)→ 成品(PS.2)→ 溯源(PS.3)」一路綁上去。 你在第 5 章畫的能力邊界表,就是讀懂它的解碼器。而每一列的右欄都在提醒:條文寫「應驗證」, 沒寫「誰來驗、驗到哪個錨點」——那些是你的組織要自己下的信任決定。合規框架給的是驗收標準, 不是免下決定的豁免。

6.6 誠實邊界

重要這章是讀法,不是合規指引

本章是我把 SSDF「讀成驗收標準」的重構,聚焦 PS 群組與密碼學原語的對應;SSDF 原文 比這裡廣得多(PO/PW/RV 三類幾乎沒展開),做合規對齊請讀原文 (National Institute of Standards and Technology 2022年)。 文中對地端平台行為的描述是標註過的經驗歸納,不對應任何特定產品或機構。


本章帶走的東西:合規框架=把原語套到產線的驗收標準,不是打勾清單;PS.1 靠簽章補上 hash 鏈給不了的身分,而開發者金鑰的合法性剝到底是身分核實;PS.2 要求給下游驗的辦法—— hash 定址+簽章+錨點;PS.3 是 To: Bob 的產線版,把建置情境簽進聲明裡。

往下一章的橋:PS.2 那句「提供下游驗證機制」,落到鍵盤上到底是什麼指令?簽章工具 長什麼樣、簽的對象是什麼、「四環境同 digest」憑什麼成為驗收點?下一章從 cosign 開始, 把成品簽章真的做一遍——照慣例,附一支你可以親手跑壞的腳本。

National Institute of Standards and Technology. 2022年. Secure Software Development Framework (SSDF) Version 1.1: Recommendations for Mitigating the Risk of Software Vulnerabilities. NIST Special Publication Nos. 800-218. National Institute of Standards; Technology. https://doi.org/10.6028/NIST.SP.800-218.
Torres-Arias, Santiago, Hammad Afzali, Trishank Karthik Kuppusamy, Reza Curtmola, 和 Justin Cappos. 2019年. 《in-toto: Providing Farm-to-Table Guarantees for Bits and Bytes》. Proceedings of the 28th USENIX Security Symposium, 1393~410.