級別: 初級
Bilal Siddiqui, CEO
2002 年 3 月 01 日
XML
加密為需要結構化數據安全交換的應用程序提供了一種端到端安全性。XML 本身是對數據進行結構化最流行的技術,因此基于 XML
的加密成為處理數據互換應用程序中安全性的復雜需求的方法。在這個兩部分系列的第 1 部分中,Bilal 解釋了打算如何將 XML 和安全性集成到
W3C XML 加密工作草案中。
當前,傳輸層安全性
(Transport Layer Security(TLS))是因特網上安全通信的事實標準。TLS
是繼著名的安全套接字層(SSL)之后的端到端安全性協議。SSL 最初是由 Netscape
設計的,而且,之后國際工程任務小組(Internet Engineering Task Force (IETF))改編了它的 3.0
版本,同時他們還在設計 TLS。這是一個非常安全和可靠的協議,它提供了通信雙方之間的端到端安全性會話。XML 加密(XML
Encryption)無意替換或取代 SSL/TLS。相反,它提供了用于 SSL 未涵蓋的安全性需求的機制。以下是兩個 SSL
未涉及的重要領域:
- 加密交換數據的一部分
- 多方(不止兩方)之間的安全會話
使用 XML 加密,每一方都可以保持與任何通信方的安全或非安全狀態。可以在同一文檔中交換安全的和非安全的數據。
例如,考慮一個包含許多聊天室的安全聊天應用程序,其中每個聊天室都有幾個人。可以在聊天伙伴之間交換 XML 加密的文件,這樣一個聊天室中的數據對其它聊天室而言是不可見的。
XML 加密能夠處理 XML 和非 XML(例如二進制)數據。現在我們將演示一個簡單的數據交換,通過 XML 加密使它安全。然后我們將慢慢地增加安全性需求的復雜程度,并解釋 XML 加密模式及其不同元素的使用。
XML 數據安全交換的簡單示例
假設您希望將
清單 1中
的 XML
文件發送給出版公司。這個文件包含一本您要購買的書的詳細信息。此外,它還包含您付款的信用卡信息。自然地,您希望對這些敏感數據使用安全通信。一種選擇
是使用 SSL,它將保護整個通信的安全。備選方案是使用 XML 加密。正如已經提到的,XML 加密不是 SSL/TLS
的替代。如果應用程序要求整個通信是安全的,則您將使用
SSL。另一方面,如果應用程序需要安全和非安全通信的組合(這意味著部分數據將被安全地交換,而其它數據將按原樣交換),那么 XML
加密是最佳選擇。
清單 1. 要加密的樣本 XML 文件
<purchaseOrder> <Order> <Item>book</Item> <Id>123-958-74598</Id> <Quantity>12</Quantity> </Order> <Payment> <CardId>123654-8988889-9996874</CardId> <CardName>visa</CardName> <ValidDate>12-10-2004</ValidDate> </Payment> </purchaseOrder>
|
注意:我們故意使
清單 1
中的 XML 文件非常簡單。這有助于將我們的注意力集中在與加密相關的問題上。用于合作商業或 Web 服務的現實 XML
文件將有類似的結構,但更冗長。WSDL(Web 服務定義語言)和 SOAP(簡單對象訪問協議)是 B2B 集成中經常使用的基于 XML
的語法。WSDL 和 SOAP 都可使用 XML 加密來提供企業內的安全通信。
有關它們的詳細信息,請訪問 W3C(請參閱 參考資料)。
使用 XML 加密對整個文檔加密
XML 加密提供各種選項。
清單 2、
清單 3和
清單 4顯示了不同的加密結果。讓我們逐個仔細研究它們。
倘若您決定加密
清單 1中的整個 XML 文檔,則
清單 2 顯示最后所得到的 XML 加密的文件。請注意
<CipherData>
和
<CipherValue>
標記。實際加密的數據作為
<CipherValue>
標記的內容出現。整個
CipherData
元素出現在一個
EncryptedData
元素內。
EncryptedData
元素包含用于加密的 XML 名稱空間。例如,加密前的原始數據是 XML 并且 Internet Assigned Numbers
Authority(IANA)對 XML 的正式類型定義是
http://www.isi.edu/in-notes/iana/assignments/media-types/text/xml。
這作為 Type
屬性的值出現。XML 對各種流行的數據格式(如 RTF、PDF 和 JPG)使用 IANA 的類型定義。完整細節,請參閱它們的網站(請參閱
參考資料 )。如果有特殊的應用程序數據類型(可能是屬于您公司的內容管理系統特有的 DTD 或 XSD),可以在
EncryptedData
元素的
Type
屬性里指定它們。另一個屬性 xmlns 指定了用來加密 XML 數據的 XML 加密名稱空間。
使用 XML 加密對單個元素加密
您可能只想加密
清單 1 中的一個元素 ― 例如
Payment
元素。在這種情況下,
清單 3中闡明了其結果。比較
清單 2和
清單 3,您將發現下列差異:
-
清單 2只包含 XML 加密的模式,而
清單 3既包含 XML 加密模式又包含來自
清單 1中原始數據的元素。在
清單 3中,XML 加密被嵌入到用戶的 XML 中。
-
清單 3 的
<EncryptedData>
中也有一個
Type
屬性,但它的值是 http://www.w3.org/2001/04/xmlenc#Element。我們不再使用 IANA 類型;相反,我們使用 XML 加密已指定的類型。
- 請特別注意末尾的片段 #Element,它表示 EncryptedData ― 這代表一個元素。
加密元素的內容
如果您只要加密
清單 1 中元素
CardId
中的內容,
清單 4 就是其結果。這次,我們使用 http://www.w3.org/2001/04/xmlenc#Content 作為
Type
屬性的值。每當我們都僅須加密內容時都使用這個值。
加密非 XML 數據
假如您希望通過 XML 加密發送一個 JPEG 文件,那會怎么樣呢?
清單 5 是將產生的一個典型文件。按字節序列加密的整個 JPEG 文件將作為
CipherValue
元素的內容出現。
請注意,
清單 2和
清單 5 之間唯一的差異:
EncryptedData
元素的
Type
屬性。
清單 5包含了 JPEG 格式的 IANA 類型。類似地,可以通過提供 IANA 值(參考 IANA 網站,請參閱
參考資料)加密任何格式。
XML 加密的密鑰
在清單 1 到 5 中,我們已經演示了加密,而加密就不可能不使用密鑰(請參閱側欄
公鑰、私鑰和秘鑰)。使用 XML 加密,所有與密鑰相關的問題劃分成兩個部分:
- 密鑰的交換(非對稱加密)
- 使用預先交換的密鑰(對稱加密)
這樣,用戶可以交換密鑰并在以后使用它們。
用于交換秘鑰的非對稱密鑰
在這個方案中,一方將它的公鑰發送給另一方。另一方使用這個公鑰加密其秘鑰。
清單 6(請求)和
清單 7 (響應)中顯示了這種數據交換。我們假設 Imran 和 Ali 分別是相互通信的第一方和第二方。Imran 初始化了公鑰交換請求并在名為 KeyValue 的元素中發送了他的公鑰。
屬性
CarriedKeyName
表示所傳輸密鑰的名稱。請注意這個結構的根元素是
EncryptedKey
,它包含
ds:KeyInfo
和
ds:KeyValue
元素。
ds: KeyInfo
和
ds:KeyValue
元素屬于 XML 數字簽名(ds:)名稱空間。對于密鑰交換 XML 加密完全依賴于 XML 數字簽名規范。因此,
<ds:EncryptedKey>
和
<ds:KeyValue>
都屬于 XML 數字簽名規范名稱空間。
清單 7是 Ali 發送的響應。
清單 7 中的
CipherValue
元素包含一個新生成的秘鑰,它是用第一方的公鑰加密的。仔細看清單 6 和清單 7,您將注意到請求和響應都包含
EncryptedKey
元素。
EncryptedKey
元素內的
ds:KeyInfo
和
ds:KeyValue
元素攜帶著公鑰(
清單 6 )。另一方面,
EncryptedKey
元素內的
CipherData
和
CipherValue
元素(
清單 7 )將傳輸(加密的)秘鑰。還請注意
EncryptedKey
元素總是包含一個
CarriedKeyName
屬性來指定其所攜帶密鑰的名稱。
使用我們過去已經交換的密鑰
在前一節中,我們交換了一個秘鑰。現在我們將使用那個密鑰來加密數據。我們將假定 Imran 發送了一條 XML 消息(
清單 8)來響應
清單 7(請回憶
清單 7包含一個名為“Imran Ali”的加密的秘鑰)。Imran 將使用他的(Imran 自己的)私鑰來解密這個秘鑰(因為 Ali 用 Imran 的公鑰加密了這個秘鑰)。Imran 可以使用這個秘鑰并將它放在
清單 8 中的
CipherValue
元素中來加密他打算發送給 Ali 的數據。
清單 8 中的
ds:KeyInfo
元素包含一個
KeyName
元素。這個組合引用了 Imran 用于數據加密的密鑰名稱。
圖 1 是顯示用于安全數據交換的 XML 文件的這種交換的可視圖。
圖 1. 使用 XML 加密進行密鑰與數據交換的順序
在
清單 5和
7 中,
CipherData
元素可以出現在
EncryptedData
元素或
EncryptedKey
元素中。我們使用
CipherData
元素來引用加密數據(當它出現在
EncryptedData
元素中時)或加密密鑰(當它出現在
EncryptedKey
元素中時)。在清單
5和
7 中,包含實際加密數據的
CipherData
元素中都有一個
CipherValue
子元素。
我們也可以引用外部加密數據或加密密鑰。這意味著實際加密數據或密鑰將出現在別的地方(可能是因特網上的某個地方),而不是在 XML 加密文件內。在這種情況下,我們將在
CipherData
中使用
CipherReference
而不是
CipherValue
子元素。我們將通過 URI 引用實際加密數據。這在
清單 9中顯示。
引用外部 XML 文件中的特定元素
清單 10 說明了引用外部 XML 文件的一個變體。這里我們只引用了 URI 所指向的外部文件的一部分。
CipherReference
元素中有一個
Transforms
子元素。這個
Transforms
元素可以包含許多
Transform
元素,其中每個都將包含單個 XPath 元素。這個 XPath 元素指定一個 XPath 表達式,該表達式引用外部 XML 文檔的特定節點。
我們的 API 的 DOM 結構
我們已經演示了如何創建 XML 加密文件以及交換加密數據。現在我們將推薦用于 XML 加密的 Java API 并提供一個樣本實現。為達到這個目的,我們將使用 DOM。
我們的 DOM 實現由一組類組成(清單 11 到 16)。
XmlEncryption
類(
清單 11)是其余類的封裝器,這意味著我們的 API 用戶將只需要與這個類交互。在內部它使用其它類的功能。
清單 11是一個能夠生成完整 XML 加密文件的封裝器類。
清單 12 創建
EncryptedData
元素。
清單 13 創建
EncryptionMethod
元素。
清單 14 創建
KeyInfo
元素。
清單 15 創建
CipherData
元素。
清單 16包含作為靜態整數的算法名稱及其作為字符串的相應名稱空間。
XmlEncryption
類(
清單 11)包含各種公用 Get/Set 方法。用戶將調用 Set 方法來指定加密參數,包括下列:
- 要加密的文件名稱
- 所產生的 XML 加密文件的名稱
- 加密算法的名稱
- 將用于加密的密鑰名稱
- 用于
<EncryptedData>
結構標識的 ID
我們已經通過
main ()
方法演示了
XmlEncryption
類(
清單 11 )的使用。我們在
main ()
方法中創建了這個類的實例。構造器實例化了 DOM,因此所有基本類都將使用同一個對象。
|
公鑰、私鑰和秘鑰
我們使用了三個與密鑰相關的術語(公鑰、私鑰和秘鑰)。盡管這些術語對從事端到端安全性的開發人員而言是眾所周知的,但 XML 開發人員可能并不熟悉它們。讓我們闡明這些術語:
公鑰和私鑰:我們成對使用它們。有些算法生成一對公鑰和私鑰。我們將公鑰發送給任何希望與我們交換加密數據的人。使用公鑰,我們只能加密有限大小的數據。通信伙伴使用我們的公鑰加密數據,然后將加密的數據發送給我們。接著,我們用私鑰解密數據。這是非對稱加密。
秘鑰: 我們使用公鑰和私鑰來交換秘鑰。通常隨機生成秘鑰。一旦使用非對稱加密與通信伙伴交換了秘鑰,我們就可以在兩端都使用這個秘鑰加密數據了。這是對稱加密。
|
|
如
清單 2 中所示,這個實現只支持整個文件的加密。
EncryptCompleteXmlFile ()
方法將通過按序列調用下列方法完成這個任務:
-
GetEncryptedDataDoc()
返回
EncryptedData
類(
清單 12 )的對象。它包含
EncryptedData
元素的結構。
-
GetEncryptionMethodDoc()
返回 Document 對象,該對象包含對應于
EncryptionMethod
元素的 XML 結構。
GetEncryptionMethodDoc()
使用
EncryptionMethod
類(
清單 13)來創建 XML。
-
GetKeyInfoDoc()
返回
Document
對象,該對象包含對應于 KeyInfo 元素的 XML 結構。
GetKeyInfoDoc()
使用
GenericKeyInfo
類(
清單 14 )的對象來創建 XML。這個類僅提供最小的必需功能(對
KeyName
和
KeyValue
元素的支持),您將通過對
GenericKeyInfo
類的繼承來提供完整的功能,其中包含對 X509 證書、PGP 數據等的支持。
-
ReadFile()
取得我們希望加密的數據(整個 XML 文件)。
-
GetEncryptedData()
暫時不做任何事情。我們將在本文的下一部分實現這個方法。它應該創建在步驟 4 中取得的 XML 數據的加密格式。在上一節(Java 密碼體系結構)中,我們已經簡要地討論了我們的加密策略。
-
GetCipherDataDoc()
將加密數據作為參數,然后返回包含
CipherData
元素的 Document 對象。
GetCipherDataDoc()
使用
CipherData
類(
清單 12)的對象來創建 XML。
- 最后,三次調用
EncryptedData
(
清單 15 )對象的
addChild()
方法,該方法將獲得步驟 2、3 和 6 的 Document 對象,然后將它們添加到
<EncryptedData>
結構,這是它們所有對象的父類。
-
SaveEncryptedFile()
保存完整的 XML 加密文件。
AlgoNames
(
清單 16)是一個只指定 XML 加密所需要的名稱空間聲明的助手類。
XmlEncryption
類(
清單 11)也可以作為服務器端組件使用。在本系列的下一部分中,我們將演示它在獨立應用程序中以及在服務器端應用程序中的使用。
我們已開發的這組類只執行基于 DOM 的 XML 創建。我們還需要實現密碼功能。現在我們將嘗試形成一個用于密碼支持的策略。出于這個目的,我們需要研究 Java 密碼體系結構(Java Cryptographic Architecture(JCA))。
Java 密碼體系結構(JCA)
Java 提供對密碼術的完整支持。出于這個目的,J2SE 中有幾個包,它們涵蓋了安全性體系結構的主要特性,如訪問控制、簽名、證書、密鑰對、密鑰存儲和消息摘要等。
JCA 設計的主要原理是將密碼概念從算法實現中分離出來,以便不同的供應商可以在 JCA 框架內提供他們的工具。
JCA 引擎類
JCA 定義了一系列引擎(Engine)類,其中每個引擎提供一種密碼功能。例如,MD(消息摘要)算法有幾種不同的標準。這些標準的實現各不相同,但在引擎 API 級別,它們都是相同的。不同的供應商可以自由地提供特定算法的實現。
Java 密碼擴展(JCE)
所有獨立(第三方)供應商的密碼算法實現都稱為 Java 密碼擴展(Java Cryptographic Extension
(JCE))。Sun Microsystems 也提供了 JCE 的一種實現。無論何時使用 JCE,都必需將它和 JCA
一起配置。為此,我們需要執行如下操作:
1. 添加 jar 文件的地址以在
CLASSPATH
環境變量中配置供應商(將所有 JCE 實現稱為供應商)。
2. 通過編輯 java.security 文件,在您認可的供應商列表中配置供應商。這個文件位于 JavaHome/jre/lib/security 文件夾。下列是指定優先級的語法:
security.provider.<n>=<masterClassName>
。這里 n 是優先級號(1、2、3 等等)。
MasterClassName
是引擎類將為特定算法實現調用的主類的名稱。供應商文檔將指定其主類名稱。例如,考慮 java.security 文件中的下列項:
-
security.provider.1=sun.security.provider.Sun
-
security.provider.2=com.sun.rsajca.Provider
-
security.provider.3=com.sun.net.ssl.internal.ssl.Provider
這些項意味著引擎類將按上面提到的順序搜索任何算法實現。它將執行最先找到的實現。完成這些簡單步驟之后,我們完全準備好開始在 XML 加密應用程序中使用 JCA/JCE。
在我們的 XML 加密實現中使用 JCA 和 JCE
封裝器類
XmlEncryption
(
清單 11 )中的
GetEncryptedData()
函數是處理所有與 JCA/JCE 相關問題的所在。目前,這個方法僅返回字符串“This is Cipher Data”。我們還沒有編寫與
JCA/JCE 相關的類。這個方法獲得未加密數據,然后將它作為加密字符串返回。在編寫了用于 JCA/JCE
的封裝器類之后,我們將在這個方法中處理所有與算法和密鑰相關的問題。
下一次:在這一系列文章的下一部分中,我們將討論并實現密碼術的細節。我們將演示加密和解密類的工作方式以及它們使用解析邏輯的交互,并展示 Web 服務中 XML 加密的應用程序。
參考資料
關于作者
|
|
|
XML
顧問 Bilal Siddiqui 于 1995
年從巴基斯坦的拉合爾工程與技術大學獲得電子工程學學位。然后他開始設計用于工業控制系統的軟件解決方案。后來,他轉向 XML 并運用他在 C++
方面的編程經驗來構建基于 Web 和 WAP 的 XML 處理工具、服務器端解析解決方案和服務應用程序。您可以通過向 Bilal
發電子郵件索取本文包含的代碼文件的工作副本,他的電子郵箱是 wap_monster@yahoo.com 。
|