XML 數(shù)字簽名規(guī)范
摘要:本文探討 XML 數(shù)字簽名規(guī)范,介紹其處理模型和某些功能。此外,還可以通過(guò)本文更加詳細(xì)、深入地了解有關(guān) WS-Security 規(guī)范如何實(shí)現(xiàn)其消息安全功能。
簡(jiǎn)介
數(shù)字簽名十分重要,因?yàn)樗梢蕴峁┒说蕉说南⑼暾员WC,還可以提供有關(guān)消息發(fā)件人的驗(yàn)證信息。為了達(dá)到較好的效果,簽名必須是應(yīng)用程序數(shù)據(jù)的一部分,這樣可以在創(chuàng)建消息時(shí)生成簽名,并可以在最終使用和處理消息時(shí)對(duì)簽名進(jìn)行驗(yàn)證。
除消息保密性功能以外,SSL/TLS 還提供消息完整性保障,但這項(xiàng)功能僅在傳送過(guò)程中有效。服務(wù)器(或更常見(jiàn)的對(duì)等接收方)接收消息后,必須“解除”SSL 保護(hù)才能處理消息。
更為有趣的是,SSL 只在通信端點(diǎn)之間起作用。如果在開(kāi)發(fā)新的 Web 服務(wù)時(shí)使用傳統(tǒng)的 HTTP 服務(wù)器(例如 IIS 或 Apache)作為網(wǎng)關(guān),或者與具有 SSL 加速器的大型企業(yè)進(jìn)行通信時(shí),消息完整性可以一直得到保障,直到 SSL 連接終止。
可以拿傳統(tǒng)信函進(jìn)行類(lèi)比說(shuō)明。當(dāng)將支票郵寄到電話(huà)公司時(shí),通常會(huì)在支票(即“消息”)上簽名,并將支票放入信封中以達(dá)到保密和郵寄的目的。收到消息后,電話(huà)公司會(huì)拆開(kāi)信封,將信封扔在一邊,然后處理支票。當(dāng)然,也可以讓消息成為信封的一部分,例如將付款貼在明信片上郵寄過(guò)去,但這樣做顯然很愚蠢。
XML 簽名可以定義一系列 XML 元素,這些元素可以?xún)?nèi)嵌或以其他方式附加在任何 XML 文檔中。這樣,收件人可以驗(yàn)證收到的消息與發(fā)件人原本發(fā)送的消息是否相同。
XML 簽名的語(yǔ)法和處理規(guī)范(本文中縮寫(xiě)為 XML DSIG)是由 W3C 和 IETF 聯(lián)合制定的。自 2002 年 2 月以來(lái),它一直是正式的 W3C 推薦規(guī)范,并得到了廣泛的應(yīng)用:.NET Framework 中的 System.Security.Cryptography.Xml 就應(yīng)用了此規(guī)范。在 WS-Security 具有的驗(yàn)證、內(nèi)容完整性和內(nèi)容保密性三種功能當(dāng)中,XML DSIG 可以提供完整性,并可用于進(jìn)行發(fā)件人驗(yàn)證。
不涉及復(fù)雜數(shù)學(xué)的數(shù)字簽名加密
在深入了解 XML DSIG 之前,需要了解一些基本加密算法。本節(jié)將探討這些概念,但是不要害怕:并不會(huì)涉及復(fù)雜數(shù)學(xué)。
數(shù)字簽名對(duì)某些內(nèi)容提供完整性檢查。如果原始內(nèi)容的某個(gè)字節(jié)已經(jīng)被修改(例如在價(jià)格上多加了個(gè)零,“2”改成了“4”,或者“否”改成了“是”等),那么簽名驗(yàn)證將失敗。下面是它的工作原理。
首先需要“散列”消息。加密散列使用的是任意字節(jié)流,并將其轉(zhuǎn)換為某個(gè)固定長(zhǎng)度的值,這個(gè)值稱(chēng)為“摘要”。摘要是一個(gè)單向過(guò)程:從計(jì)算角度來(lái)說(shuō),無(wú)法通過(guò)散列重新創(chuàng)建消息,也不可能找到可以產(chǎn)生相同摘要值的兩封不同消息。
最常用的散列機(jī)制是 SHA1,即“安全散列算法”。此算法由美國(guó)政府創(chuàng)建,并在 1995 年作為標(biāo)準(zhǔn)發(fā)布。SHA1 可以處理 2**64 字節(jié)以?xún)?nèi)的任何消息,并生成一個(gè) 20 字節(jié)的結(jié)果。(這意味著將有 2**160 個(gè)可能的摘要值;比較起來(lái),目前估計(jì)宇宙中的質(zhì)子數(shù)目大約是 2**250。)
所以,如果我生成消息 M 并創(chuàng)建摘要(用 H(M) 代表“M 的散列”),您將收到 M 和 H(M),您可以創(chuàng)建自己的摘要 H'(M),如果兩個(gè)摘要值匹配,表明您收到了我發(fā)送的消息。要保護(hù) M 使其不被修改,我只需要保護(hù) H(M),使它不被修改。
那該怎么做呢? 有兩種常用的方法:第一種是將共享密鑰混合在摘要中,即創(chuàng)建 H(S+M)。您收到消息后,可以使用自己的 S 副本來(lái)創(chuàng)建 H'(S+M)。新的摘要稱(chēng)為 HMAC,即“散列后的消息驗(yàn)證代碼”(Hashed Messsage Authentication Code)。
在使用 HMAC 時(shí),完整性保護(hù)的有效性取決于攻擊者計(jì)算出 S 的能力。因此,S 應(yīng)該不容易被猜出,并應(yīng)該經(jīng)常更改 S。符合以上要求的最好方法之一是使用 Kerberos。在 Kerberos 中,中央機(jī)構(gòu)將在兩個(gè)實(shí)體希望通信時(shí)分配包含臨時(shí)會(huì)話(huà)密鑰的“票”。此會(huì)話(huà)密鑰將用作共享密鑰。在要將簽名發(fā)送給您時(shí),我將得到一張票,以和你通信。我打開(kāi)票中的屬于我的那一部分來(lái)獲得 S,然后將消息、消息的 HMAC 和票中您的那一部分發(fā)送給您。您打開(kāi)票(使用原來(lái)通過(guò) Kerberos 注冊(cè)的密鑰),獲取 S 以及有關(guān)我身份的信息。您現(xiàn)在可以獲得消息 M,生成自己的 H'(S+M),并查看它們是否匹配。如果匹配,表明您原封不動(dòng)地收到了我的消息,并且 Kerberos 將通知您我是誰(shuí)。
另外一個(gè)保護(hù)摘要的方法是使用公鑰加密算法,例如 RSA。公鑰加密算法中有兩個(gè)密鑰:一個(gè)是只有持有者知道的私鑰,另一個(gè)是要與密鑰持有者通信的任何人都知道的公鑰。在公鑰加密算法中,使用私鑰加密的任何內(nèi)容都可以使用公鑰解密,反之亦然。
下面通過(guò)一個(gè)簡(jiǎn)單的示例來(lái)說(shuō)明公鑰加密算法的工作原理。在此示例中,我們將消息內(nèi)容限制為從 a 到 z 的字母,并給這些字母指派 0 到 26 的值。要對(duì)消息進(jìn)行加密,我們需要添加私鑰的值;在本示例中,此值為 +4:
字母 h e l l o
數(shù)值 8 5 12 12 15
私鑰 4 4 4 4 4
加密后的值 12 9 16 16 19
要對(duì)消息進(jìn)行解密,我們需要添加公鑰,值為 +22;如果結(jié)果超出了數(shù)字范圍,就加上或減去 26,直到值有效。(換句話(huà)說(shuō),要對(duì)消息進(jìn)行解密,我們需要添加公鑰,并用結(jié)果對(duì) 26 取模。)
加密后的值 12 9 16 16 19
公鑰 22 22 22 22 22
原始加密后的值 34 31 38 38 41
規(guī)范化的值 8 5 12 12 15
純文本 h e l l o
RSA 的工作原理與此相同,只是使用求冪的方法而不是加法,此外,數(shù)字的位數(shù)比較多。
使用 RSA 生成一個(gè)摘要:H(M),并使用我的私鑰進(jìn)行加密,則 {H(M)}private-key 就是我的簽名。您收到消息 M 后,可以生成摘要 H'(M),并使用我的公鑰來(lái)對(duì)簽名進(jìn)行解密,就得到我生成的 H(M)。如果 H(M) 和 H'(M) 相同,表明兩封消息 M 是相同的。而且,您會(huì)發(fā)現(xiàn)擁有私鑰的人,也就是“我”,是消息的發(fā)件人。