[摘要]XML數字簽名技術可以在無線Web服務應用程序提供輕量級且靈活的安全解決方案。本文討論了XML數字簽名及其應用程序的重要性,并提供了Bouncy Castle密碼包的數字簽名API,最后給出了在J2ME/MIDP無線客戶端和JSP頁后臺之間的安全XML消息傳遞環境中的實現示例。
[關鍵詞]J2ME XML 數字簽名
一、引言
基于Java的Web服務和無線Java開發是JavaOne的兩個最突出的主題。它們代表普及計算領域中未來的后端和前端Java技術。
Java 平臺可以在無線 Web 服務應用程序開發中扮演幾個重要角色。在無線端,Java 2 Micro Edition(J2ME)為所有無線設備(從蜂窩電話到復雜的家用無線信息家電)提供了跨設備的兼容性、高級語言功能和大量庫。J2ME的一個關鍵組件是移動信息設備框架(Mobile Information Device Profile:MIDP),它在蜂窩電話和低端PDA上定義Java API和運行時環境。由于龐大數量的低端設備,期望在將來能夠廣泛部署MIDP。
從Web服務端,Java2Enterprise Edition(J2EE)已經具有所有必需的API和庫存處理Web服務XML消息。通過Web服務接口或網關,可以方便地將用 EJB技術實現的核心J2EE功能、JDBC API和RMI API用于外部世界。為了將這些特性集合起來并啟用無線Web服務應用程序,還提出了J2MEWeb服務規范,目前它應用在JavaCommunityProcess中。
雖然無線Web服務在普及移動商業世界中應用廣泛,但當前技術仍不成熟。安全性仍是剩下待解決的問題之一。本文將討論一種常用的安全性技術——數字簽名,研究如何在 XML 消息中使用數字簽名來保證端對端的數據完整性,以及在當前 MIDP 設備上使用數字簽名的可行性。
二、使用數字簽名保證數據完整性
數據完整性是通信安全性的最重要方面之一。數據通信在無線因特網上特別容易受到攻擊,而一種及時出現的援救工具是公鑰基礎設施(Public Key Infrastructure:PKI)和數字簽名。在 PKI 數字簽名模式中,每一方都有兩個密碼術密鑰:公鑰可以被任何人使用;而私鑰是保密的,只有某個人本身可以使用。用私鑰加密的消息只能由相應的公鑰正確解密。當發送方發送消息時,他可以將相同消息的私鑰加密版及他的公鑰與該消息一起發送。接收方使用發送方的公鑰來解密加密版本。如果它與明文消息匹配,那么接收方可以知道該消息確實可信。該消息的私鑰加密版用作完整性驗證記號,我們將它稱為“數字簽名”。
因為原始消息可能相當長,而且生成和驗證數字簽名的公鑰算法計算復雜度是指數級的,所以發送方通常計算稱為“摘要”的原始消息的短版本并且僅對該版本進行數字形式的簽署。摘要具有固定長度,它是任何長度的輸入消息的單向散列;其計算速度非常快。接收方首先驗證接收的消息是否產生正確摘要。如果該摘要不匹配,則在執行任何公鑰算法之前拒絕該消息。這可以有助于防止攻擊造成堵塞,在這種攻擊中,攻擊者通過用偽造的公鑰請求填斥服務器,以耗盡它的計算資源。
在大多數實際應用程序中,公鑰本身由可信的權威部門進行數字簽名,并成為“數字證書”來驗證發送方的標識。不過,數字證書的處理不在本文范圍內,所以在下列示例中,將假設發送方是可信的并使用未簽署的公鑰來說明方法。
三、對XML進行數字簽名
XML正成為Web服務世界中一個主要的數據交換協議。驅動 Web服務的XML消息在到達目的地之前,通常需要經過多個中間環節。因此,保護從端到端的通信內容是重要的。完成這一任務的最好方法是,將XML文檔及其安全性信息(如簽名、摘要和密鑰等等)都裝運在一起,作為單個文檔。
XML數字簽名是將數字簽名添加到XML文檔的W3C規范。發送方可以選擇對整個文檔或者僅它的一部分進行數字簽名。數字簽名、摘要和公鑰被格式化成XML元素。那些安全性信息的額外元素可以封裝整個原始XML消息,或者可以將它們嵌入原始消息。為方便起見,將在本文中使用封裝格式。另外,將密鑰分成幾個參數并將那些參數傳遞到公鑰元素KeyInfo下的單獨XML元素中,以代替使用編碼的公鑰證書。這在密鑰和處理它們的Java代碼之間建立了更明顯的連接。
四、使用Bouncy Castle Crypto API進行數字簽名和驗證的完整實現步驟
由于篇幅有限,本文將簡略地論述XML數字簽名規范,以及Bouncy Castle密鑰生成器、編碼引擎、數字簽名簽名引擎和摘要引擎的用法。Bouncy Castle是一種用于 Java 平臺的開放源碼的輕量級密碼術包。它支持大量的密碼術算法,并提供JCE 1.2.1的實現。因為 Bouncy Castle 被設計成輕量級的,所以它都可以在從J2SE 1.4到J2ME的各平臺運行。它是在MIDP上運行的惟一完整的密碼術包。
Bouncy Castle Crypto API對J2ME應用程序中XML文檔進行數字簽名和驗證的完整實現過程,如步驟圖所示:
五、具體實現代碼分析
Bouncy Castle Crypto包提供幾個使用DSA、RSA 和 ECC算法的簽名引擎類來簽署和驗證消息。本文將詳細討論如何使用RSA 簽名引擎來簽署并驗證數字簽名。那些簽名引擎使用不同的算法和不同的密鑰,并且需要不同的參數。本文還將討論如何將安全性信息(簽名、摘要和公鑰)嵌入XML文檔,以及比較三個簽名引擎并提出今后的改進建議。
在上述生成“隨機的密鑰對”代碼中,RSASigUtil.generateKeys()方法使用 Exponent 生成隨機的密鑰對,這個步驟通常由中央認證中心在脫機狀態下完成。公鑰以參數 Modulus 來描述,并且用 pubKey.getModulus() 方法來檢索它。下面的代碼說明了 RSAUtil 類中的方法。這些方法檢索 Exponent 和 Modulus模型及密鑰參數,它們是重新構造公鑰對象所必需的。
通過使用生成的私鑰,實用程序類 RSASigUtil 可以從摘要獲取一個字節數組 RSA 簽名:
服務器將摘要、簽名和密鑰參數編碼成ASCII文本格式并以XML數字簽名格式嵌入該文本:
驗證MIDP應用程序從 XML 文檔解析出摘要、密鑰參數和簽名,重新構造公鑰并使用下列方法來驗證簽名:
以上測試說明了無線設備上的 XML 解析和摘要生成都非常快。其主要的性能瓶頸是公鑰算法的速度很慢。Bouncy Castle Crypto 包提供幾個使用 DSA、RSA 和 ECC 算法的簽名引擎類來簽署和驗證消息。但在實際設備中,它們并不都是實用的,因為 Bouncy Castle Crypto 包完全基于Java 語言,所以它在沒有特殊優化的情況下依靠很慢的 JVM 來執行甚至是最密集的大整數數學運算。結果只有 RSA 算法提供了一個合理的性能,而且是可以接受的。它只要花很少的時間就可以在16MHz Palm VII 設備上驗證具有1024位公鑰的簡單數字簽名。雖然如此,驗證進程在任何實際的應用程序中還是必須作為后臺線程運行,以避免用戶界面鎖定。
DSA和ECC算法性能在其當前實現中是不可接受的。具有 1024位密鑰的DSA簽名和具有192位密鑰的ECC簽名要花大量時間在標準的Palm VII MIDP上進行驗證。性能問題強烈需要我們需要為大整數數學運算和公鑰算法對JVM 進行優化。JVM 還必須利用可用的特殊硬件和底層的OS功能來促進與安全性相關的數學運算。公鑰算法用于安全連接(如 HTTPS)中的信息交換。許多當前的 MIDP VM 可以用合理的性能來支持 HTTPS 協議。MIDP4Palm VM 可以利用 Palm OS 的底層的 inethttps 協議來建立安全連接。可以想象未來的VM和核心語言庫不僅優化與安全連接相關的公鑰操作,而且還使優化可用于一般安全性功能(如數字簽名)。
六、結束語
在 Bouncy Castle 提供的所有算法中,只有 RSA 算法提供了無線設備上可以接受的性能。然而,未來在 MIDP 運行環境上的進步可以使數字簽名更易于移動用戶使用。
參考文獻:
[1] Alfred J. Menezes、Paul C. Van Oorschot、Scott A. Vanstone. Handbook of Applied Cryptography[M]. CRC Press. 1996
[2]http://www.w3.org/TR/xmldsig-core/ XML-Signature Syntax and Processing. W3C 2002
注:本文中所涉及到的圖表、注解、公式等內容請以PDF格式閱讀原文。