三個管理課題#
前面討論安全通道與存取控制時,幾乎沒有觸及「金鑰是怎麼來的」這類問題。安全管理(security management)分成三個課題:
- 金鑰管理:密碼金鑰的一般管理,特別是公鑰如何發配——憑證(certificate)在此扮演要角。
- 安全群組管理:如何安全地管理一組伺服器,重點在於加入新成員時如何確保它獲得現有成員的信任——分散式與複寫服務一旦誤納惡意行程,安全就毀了。
- 授權管理:能力(capability)與屬性憑證(attribute certificate),以及行程之間如何安全地**委派(delegate)**部分或全部存取權——委派有它自己的微妙之處。
金鑰管理#
先前描述各種密碼協定時,我們(隱含地)假設金鑰唾手可得:公鑰系統假設傳送者已握有接收者的公鑰;KDC 驗證假設各方已與 KDC 共享秘密金鑰。但建立與發配金鑰絕非小事——透過不安全通道發配秘密金鑰是不可能的,很多情況只能訴諸頻外(out-of-band)手段;此外還需要**撤銷(revoke)**機制,讓已洩漏或失效的金鑰不能再被使用。
金鑰建立#
會談金鑰怎麼建立?若 Alice 與 Bob 已能用公鑰起始通訊,Bob 可以產生會談金鑰、用 Alice 的公鑰加密後回傳;雙方已共享秘密金鑰時做法類似。但這兩種方法都預設雙方已經具備建立安全通道的手段——也就是說,某種形式的金鑰建立與發配必須先發生過。靠 KDC 這類可信第三方建立共享金鑰時,同樣的論證也成立。
在不安全通道上建立共享金鑰的優雅且廣泛應用的方案,是 Diffie-Hellman 金鑰交換(Diffie and Hellman, 1976):
- Alice 與 Bob 先議定兩個大數 n 與 g(須滿足若干數學性質,此處不深究);n 和 g 都可以公開。
- Alice 挑一個保密的大亂數 x,Bob 挑一個保密的大亂數 y。
- Alice 把
g^x mod n(連同 n、g)送給 Bob——可以走明文,因為由g^x mod n反推 x 幾乎不可能。 - Bob 計算
(g^x mod n)^y = g^xy mod n,並把g^y mod n送給 Alice;Alice 計算(g^y mod n)^x = g^xy mod n。
現在 Alice 與 Bob(而且只有他們兩人)握有共享秘密金鑰 g^xy mod n,且雙方都不必把自己的私密數字(x、y)告訴對方。

圖 9-33:Diffie-Hellman 金鑰交換的原理。
Diffie-Hellman 可以視為一種公鑰密碼系統:以 Alice 為例,x 是她的私鑰,
g^x mod n是她的公鑰。而如下所述,公鑰的安全發配正是讓 Diffie-Hellman 在實務上可行的關鍵。
金鑰發配#
金鑰管理中較難的部分是初始金鑰的實際發配:
- 對稱系統:初始共享秘密金鑰必須經由同時提供驗證與機密性的安全通道傳遞。若 Alice 與 Bob 手上沒有任何可用來建立這種通道的金鑰,只能頻外發配——打電話、用平信寄磁片等等。
- 公鑰系統:公鑰本身可以走明文,但接收者必須能確定這把公鑰確實與所宣稱的私鑰配對——傳遞公鑰的通道必須提供驗證;私鑰則當然要走同時提供驗證與機密性的安全通道。

圖 9-34:(a) 秘密金鑰的發配。(b) 公鑰的發配。
公鑰的驗證式發配,實務上靠公鑰憑證(public-key certificate):
- 憑證內容是一把公鑰加上識別其所屬實體的字串(實體可以是使用者,也可以是主機或特殊裝置),兩者一起由**憑證中心(certification authority, CA)**以其私鑰
K-_CA簽署,簽章也放在憑證上(CA 的身分自然也是憑證的一部分)。CA 的公鑰K+_CA假定廣為人知——例如各大 CA 的公鑰已內建在多數瀏覽器裡隨執行檔出貨。 - 客戶端想確認憑證中的公鑰確實屬於所識別的實體時,用 CA 的公鑰驗證憑證簽章:簽章與(公鑰, 識別字)對相符,就接受。
接受憑證,實際上是信任憑證沒有被偽造——特別是必須假設
K+_CA真的屬於那個 CA。若有疑慮,應能透過另一個(可能更受信任的)CA 簽發的憑證來驗證K+_CA的有效性。這種「最高層 CA 必須被所有人信任」的階層式信任模型並不罕見:例如 Privacy Enhanced Mail(PEM)採三層模型,最底層 CA 由政策憑證中心(PCA)驗證,PCA 再由 Internet Policy Registration Authority(IPRA)驗證。使用者若不信任 IPRA,就不可能信任 PEM 寄出的郵件是安全的(Kent, 1993;其他信任模型見 Menezes et al., 1996)。
憑證的生命期#
憑證能撐多久是個重要問題。若 CA 發終身憑證,等於聲明這把公鑰對該實體永遠有效——顯然不是我們要的:若實體的私鑰洩漏,任何不知情的客戶端都不該再使用那把公鑰。因此需要撤銷機制,把「憑證不再有效」公諸於世。做法有幾種:
- 憑證撤銷清單(Certificate Revocation List, CRL):CA 定期發布。客戶端每次檢查憑證都得查最新的 CRL,也就是每次 CRL 更新都至少要連一次 CA。注意:若 CRL 一天發布一次,撤銷一張憑證也就要花上一天——期間洩漏的憑證仍可被冒用,所以發布間隔不能太長;而取得 CRL 本身也有開銷。
- 限制憑證壽命:類似第 6 章談過的租約(lease),憑證有效期一到自動過期。若須提前撤銷,CA 仍可把它登上 CRL——所以客戶端驗證憑證時照樣得查最新的 CRL。
- 壽命趨近於零的極端做法:等於不再使用憑證,客戶端每次都直接向 CA 查詢公鑰效力——代價是 CA 必須持續在線。
實務上憑證以受限壽命發出,網際網路應用的有效期常長達一年(Stein, 1998)。這種做法要求 CRL 定期發布且在檢查憑證時被查閱——但實際上客戶端應用幾乎從不查 CRL,直接假設憑證在過期前都有效。就這一點而言,網際網路安全的實務現況還有很大的改進空間。
安全群組管理#
許多安全系統仰賴 KDC、CA 這類特殊服務,它們凸顯了分散式系統的一個難題:
- 一方面它們必須被信任,需要對各種威脅提供高度保護——CA 一旦被攻破,公鑰有效性再也無從驗證,整個安全系統形同作廢。
- 另一方面許多安全服務又必須高可用——例如兩個行程要建安全通道,至少一方得連上 KDC 拿共享金鑰;KDC 不可用時,除非另有金鑰建立手段(如 Diffie-Hellman),否則安全通訊無法建立。
高可用的解法是複寫,但複寫又讓伺服器更容易受安全攻擊。前一節談過用秘密分享實現安全群組通訊——沒有任何單一成員能單獨破壞憑證,群組本身因此高度安全。剩下的問題是如何管理這樣一組複寫伺服器。Reiter et al. (1994) 提出以下方案,確保行程 P 請求加入群組 G 時,群組完整性不被破壞。
前提:群組 G 使用所有成員共享的秘密金鑰 CK_G 加密群組訊息,另有一對公私鑰 (K+_G, K-_G) 用於與非成員通訊。協定三步:
- 加入請求(JR):P 送出識別 G 與 P 的請求,附上 P 的本地時間 T、一個產生的回覆墊(reply pad)RP 與一把產生的秘密金鑰
K_P,G;RP 與K_P,G一起用群組公鑰K+_G加密。JR 由 P 簽署(記法[M]_A表示訊息 M 由主體 A 簽署),連同載有 P 公鑰的憑證一起送出。 - 群組審核與准入(GA):收到請求的成員 Q 先驗證 P——用時間戳 T 確認憑證在送出當時仍有效(當然也得確定時間沒被動過手腳),驗證 CA 的簽章、從憑證取出 P 的公鑰檢驗 JR 的有效性;接著透過群組特定的協定確認全體成員是否同意接納 P。若准入,Q 回覆群組准入訊息 GA:識別 P、含一個 nonce N,用 RP 加密群組通訊金鑰
CK_G,再用CK_G加密群組私鑰K-_G;GA 以金鑰K_P,G簽署。 - 確認:P 能驗證 Q 的身分——只有真正的群組成員能解出秘密金鑰
K_P,G。P 把 N 用K_P,G加密送回;此處的 nonce 不是為了安全,而是讓 Q 知道 P 已收到所有必要金鑰、確實入了群。

圖 9-35:安全地接納一位新的群組成員。
為什麼用一次性的回覆墊 RP 而不用 P 的公鑰加密
CK_G?因為 RP 只用這一次(只用於 GA 訊息中群組通訊金鑰的加密),更安全:若改用 P 的公鑰,將來 P 的私鑰一旦洩漏,CK_G就跟著曝光,全部群組通訊的機密性都毀了。
授權管理#
安全管理也包括存取權的管理:權利最初如何授予使用者或群組、之後又如何以不可偽造的方式維護。
- 在非分散式系統中相對容易:新使用者加入時給予初始權利(在特定目錄建檔案與子目錄、建立行程、使用 CPU 時間……),也就是在單一機器上開一個完整帳號,所有權利由系統管理者事先指定。
- 在分散式系統中,資源散在多台機器上。照搬舊方法就得在每台機器上為每位使用者開帳號——這正是網路作業系統的做法。稍微簡化一點的是在中央伺服器上開單一帳號,每次使用者存取資源或機器時查詢該伺服器。
能力與屬性憑證#
分散式系統中被廣泛採用、而且好得多的做法是能力(capability):針對特定資源的一種不可偽造的資料結構,精確指明持有者對該資源擁有哪些存取權。以下以 Amoeba 作業系統的實作為例(Tanenbaum et al., 1986)。
Amoeba 是最早的物件式分散式系統之一,採遠端物件模型:物件位於伺服器,客戶端透過代理(proxy)取得透明存取;呼叫物件操作時,客戶端把能力交給本地作業系統,由它定位伺服器所在機器並發出 RPC。Amoeba 的能力是一個 128 位元識別子:
- 伺服器埠(server port,48 位元):物件建立時由伺服器初始化,是伺服器的機器無關識別子;Amoeba 用廣播定位伺服器目前所在的機器。
- 物件識別子(24 位元):識別該伺服器上的物件。伺服器埠加物件識別子構成全系統唯一的 72 位元物件識別子。
- 權利欄(rights,8 位元):指明能力持有者的存取權。
- 檢查欄(check,48 位元):讓能力不可偽造的關鍵。

圖 9-36:Amoeba 中的一個能力。
防偽機制的運作:
- 物件建立時,伺服器挑一個隨機檢查欄值,存進能力、也存進自己的表格。新能力的所有權利位元全開,這個**擁有者能力(owner capability)**回傳給客戶端。之後能力隨請求送回伺服器時,檢查欄都會被驗證。
- 產生受限能力:客戶端把能力連同新權利的位元遮罩(必須是原能力權利的子集)交回伺服器。伺服器從表格取出原始檢查欄,與新權利做 XOR,再把結果丟進單向函數 f;新能力的物件欄不變、權利欄放新權利位元、檢查欄放 f 的輸出,回傳給呼叫者。客戶端可以把這個新能力轉交給其他行程。例如擁有者可以關掉其他所有權利,只留下讀取——受限能力就只允許讀物件。(權利欄的意義依物件型別而異,因為合法操作本來就因型別而不同。)
- 驗證受限能力:受限能力回到伺服器時,伺服器從權利欄看出它不是擁有者能力(至少有一個位元是關的),便從表格取出原始亂數、與能力的權利欄做 XOR、跑過單向函數——結果與檢查欄一致,能力才算有效。

圖 9-37:由擁有者能力產生受限能力。
使用者若想擅自加上自己沒有的權利,只會讓能力失效;由受限能力的檢查欄反推函數引數也不可能,因為 f 是單向函數。能力靠這個密碼技巧防篡改——f 做的事本質上就是計算訊息摘要:原始內容動了任何一點(哪怕翻一個位元)都會立刻被偵測。
現代分散式系統有時採用能力的一般化形式——屬性憑證(attribute certificate)。不同於前面用來驗證公鑰有效性的憑證,屬性憑證列出適用於某識別實體的(屬性, 值)對,特別可用來列出憑證持有者對所識別資源的存取權。屬性憑證由特殊的**屬性憑證中心(attribute certification authority)**簽發(對照 Amoeba,這個中心對應物件的伺服器;但一般而言,簽發中心與管理該實體的伺服器不必是同一個),憑證上列的存取權由該中心簽署。
委派#
考慮這個問題:使用者對一個大檔案只有唯讀權,想請列印伺服器在凌晨兩點後印它。為了不麻煩別人,他不傳整個檔案,只把檔名交給印表機,讓它需要時自行複製到緩衝目錄。方案看似完美,卻有個大問題:列印伺服器通常沒有那個檔案的存取權限——伺服器要讀檔時會被系統拒絕。若使用者能把自己對該檔案的存取權暫時委派給列印伺服器,問題就解決了。
存取權的委派是實作保護的重要技術,對分散式系統尤其如此:把某些存取權從一個行程傳給另一個行程,工作就能分散給多個行程而不損及資源保護;行程可能跑在不同機器、甚至不同行政網域(如 Globus 的情形),委派讓保護多半能在本地處理,省下大量開銷。
實作委派的一般做法(Neuman, 1993)是使用代理(proxy)——此處的 proxy 是安全脈絡下的權杖(token):持有者可以用授予權杖的主體之同等或受限的權利與特權運作(與作為客戶端 stub 同義詞的 proxy 是不同概念;因為這個用法太普遍,只好接受一詞多義)。行程建立的代理,權利至多與自己相同;由既有代理衍生新代理,衍生者至少帶有原代理的全部限制,可能更多。
先看兩個簡單情境:
- Alice 認識所有人:要委派權利 R 給 Bob,她造一張憑證「Alice 說 Bob 擁有權利 R」(如
[A,B,R]_A)。Bob 想把部分權利轉給 Charlie 時,得請 Charlie 去找 Alice 要一張相應的憑證。 - 不記名憑證:Alice 造一張「持有本憑證者擁有權利 R」的憑證——但這就得防憑證被非法複製,如同行程間安全傳遞能力的問題。
Neuman 的方案同時處理了不記名憑證的保護問題,也免除了「Alice 必須認識每個被委派者」的限制。代理分成兩部分:
- 憑證部分
C = {R, S+_proxy}:由建立代理的行程 A 簽署(sig(A, C)),內含委派的權利集合 R,加上一個用來驗證持有者的秘密之公開部分S+_proxy。 - 秘密部分
S-_proxy:委派給另一行程時,這部分必須防止洩漏。

圖 9-38:用於委派的代理之一般結構。
直觀的理解:Alice 要委派權利給 Bob 時,列一張 Bob 可行使的權利清單並簽名(防 Bob 竄改)。但光有簽過名的清單不夠——Bob 行使權利時可能得證明清單真的是 Alice 給他的,不是從別人那裡偷來的。於是 Alice 想出一道只有她知道答案的刁鑽問題(S+_proxy),答案是 S-_proxy;給定問題,任何人都能輕易驗證答案對不對。問題附在清單後、一起簽名。委派時 Alice 把簽好的清單(含問題)交給 Bob,並以無人能攔截的方式把答案也給他。Bob 之後把清單交給 Charlie 時,Charlie 拿清單底下那道問題考他——Bob 答得出來,Charlie 就確知 Alice 確實把清單上的權利委派給了 Bob。
這個方案的重要性質是 Alice 不必被諮詢:Bob 可以自行決定把清單上的(部分)權利轉交給 Dave,同時把答案告訴 Dave,讓 Dave 能證明清單是由有資格的人轉交給他的。Alice 從頭到尾不需要知道 Dave 的存在。
委派與行使權利的協定:
- 假設 Alice 與 Bob 共享秘密金鑰
K_A,B。Alice 送給 Bob 簽好的憑證[R, S+_proxy]_A——這部分可走明文;只有秘密部分需要加密,即K_A,B(S-_proxy)。 - Bob 想對某伺服器上的物件執行操作(Alice 有權執行且已委派給他)時,把簽章憑證
[R, S+_proxy]_A交給伺服器。伺服器能驗證 C 沒被竄改(權利清單或問題被改動都會被發現,因為兩者由 Alice 聯合簽署),但還不知道 Bob 是不是憑證的正當持有者。 - 伺服器用 C 附帶的秘密驗證持有者。例如
S+_proxy是公鑰、S-_proxy是對應私鑰時:伺服器用S+_proxy加密一個 nonce N 作為挑戰,Bob 解密並回傳 N,即證明他知道秘密、是憑證的正當持有者。

圖 9-39:使用代理來委派存取權並證明其擁有權。
安全委派還有其他實作方式,但基本想法始終相同:證明你知道那個秘密。