Java2的安全新特征下的Applet數字簽名具體完成方法
發表時間:2023-08-22 來源:明輝站整理相關軟件相關文章人氣:
[摘要]Java2的安全新特性下的Applet數字簽名具體實現方法北京阿費自從Java技術開始應用以來,人們對Java平臺的安全性以及由于部署Java技術所引發的安全問題給予了極大的關注。特別是在1998年...
Java2的安全新特性下的Applet數字簽名具體實現方法
北京阿費
自從Java技術開始應用以來,人們對Java平臺的安全性以及由于部署Java技術所引發的安全問題給予了極大的關注。特別是在1998年11月Java2發布后,Java的安全體系結構發生了根本的改進,對于終端用戶而言,它可以保護文件和私人數據不被惡意的程序或病毒感染和破壞,鑒別代碼提供者的身份。對于開發者而言,通過使用API方法,能夠將安全性功能集成到應用程序中,因為API的體系結構能夠定義和集成對特定的資源的使用權限、加密、安全性管理、策略管理,并提供了一些類來管理公鑰/密鑰對及信任用戶群的公鑰證書。同時系統管理員、開發者和用戶可以使用它提供的工具管理鑰匙庫,在JAR文件中生成數字簽名、簽名的完整性檢測、創建和修改策略文件。按照Java設計者的觀點,Java安全包括2個方面的內容,首先將Java作為一種安全的平臺提供給用戶,在此平臺上,可安全地運行Java程序;其次提供用Java編程語言實現的安全工具和服務,它使得諸如企業界這樣一些對安全非常敏感的領域也可應用Java技術。本文將就這二個方面介紹Java2的安全性新特性以及該新特性下的Applet數字簽名的具體實現方法。
Java2采用了如圖1所示的新的安全體系結構,并基于這種安全體系結構提供了很多新特性。
圖1 JDK1.2安全模式
1.1 密紋訪問控制
這種能力從一開始就在JDK中存在。但要使用它,應用程序的編寫者不得不做大量的編程工作例如,創建SecurityManager和Classloader類的子類并使其用戶化。HotJava1.0就是一個這樣的應用程序,它允許瀏覽器用戶在幾個不同的安全等級上進行選擇。然而,這種編程涉及非常敏感的安全問題,它要求程序員對計算機安全有精深的理解和純熟的技巧。新的安全體系結構將使這些變得簡單而安全。
1.2 易于配置的安全策略
與上述情況相似,這種能力在原來的JDK中也是存在的,但是不便于使用,而且編寫安全代碼也不是簡單明了的事情。于是,人們期望能夠允許應用程序的編寫者和用戶能夠不通過編程來設置安全策略。
1.3 便于擴展的訪問控制結構
一直到JDK1.1為止,為了創建1個新的訪問許可,你必須在SecurityManager類中增加1個新的check方法。新的安全體系結構則允許設置各類訪問許可(每個都表示對1個系統資源的訪問),并能對所有正確訪問許可(包括未定義的許可)進行自動處理。
1.4 安全檢查擴展至所有Java程序
那種所有本地代碼是可信的內置概念將不復存在,取而代之的將是本地代碼(例如非系統代碼,安裝在本地的應用程序包等)服從于與Applet相同的安全控制,但是可以聲明對本地代碼的政策是最寬容的,從而使這些代碼可被認為是完全可信而有效地運行。上述原則也可應用于已簽字的Applet和任何Java應用程序。
2 Java2安全體系的概念及運行機制
2.1 保護域
Java2安全體系結構中的一個基本的概念是保護域(Protected Domain)。1個域可通過對象集來劃分范圍,這些對象當前可由1個主體直接訪問。而主體是在計算機系統中被授予許可的實體。JDK1.0所利用的沙箱就是一個有著固定邊界的保護域實例。保護域的概念是一種在保護單元間起著分組和隔離作用的便利機制。例如,我們可以將保護域分開以避免它們之間的直接交互作用,于是,任何允許的交互作用必須通過可信系統代碼或被有關的域所明確允許。
保護域通常分為明確的2個類別,系統域和應用程序域。所有被保護的外部資源如:文件系統、網絡設施以及屏幕和鍵盤等僅能通過系統域來訪問。圖2中顯示了1個Java應用環境的域的組成。從概念上講,1個域包括1組類,這些類的實例被授予相同的一組許可。保護域是由現行策略所確定的。Java應用程序環境保持了來自代碼(類和實例)到它們的保護域然后再到它們的許可的映射,如圖3所示。1個線程的執行可能完全發生在1個單一的保護域中,也可能涉及1個應用程序域或是系統域。例如:1個打印消息的應用程序將不得不與系統域發生交互作用,因為系統域是唯一對輸出流的訪問點。在此種情況下的任何時候,應用程序域都不能通過調用系統域獲得除打印消息外的任何額外許可,否則將是一個嚴重的安全性隱患。在相反的情形下,1個系統域從1個應用程序域中調用1個方法,如當1個AWT系統域調用1個Applet的繪畫方法來顯示這個Applet時,有效訪問權限與應用程序域所允許的當前權限在任何時候都相同,這一點也是同樣至關重要的。換句話說,一個具有較低權限的域不能通過調用一個更高權限的域,或被一個更高權限的域所調用來獲得額外的許可。上述有關1個線程涉及2個保護域的討論自然地歸納為1個遍歷多重保護域的線程,計算許可的一個簡單而謹慎的經驗做法是:
圖2 Java應用環境的域的組成
圖3 類→保護域→權限的映射
(1)一個執行線程的許可集可被認為是由該線程所遍歷的所有保護域的許可的交集。
(2)當1條代碼調用doPrivileged方法時,執行線程的許可集被認為是包括所有代碼的保護域以及由它直接或間接調用的保護域的權限。即通過doPrivileged方法可使1條可信代碼能臨時訪問更多的資源,這在某些情況下是必要的。例如,1個應用程序可能不被允許直接訪問包含字體的文件,但是,顯示文本的系統實用程序必須代表用戶獲得那些字體。
在執行期間,當請求訪問1個關鍵系統資源(如文件I/O和網絡I/O)或者API方法需要執行1個敏感的操作時,例如讀1個文件,資源處理代碼直接或間接地調用1個特殊的稱為訪問控制(AccessController)類的方法,訪問控制類通過檢查調用棧來作出決定是否準予該請求或操作發生。在調用棧中是執行該操作需要調用的一些類的成員方法,因為每個類都屬于一些保護域,每個保護域都建立了一些策略,因此在調用棧的每個方法都被分配了1組權限。訪問控制類由棧頂開始,自頂向下檢查每個方法,看是否方法被所在的保護域所允許,如果發現一個方法權限沒有得到允許,訪問控制類就拋出安全性異常;反之,如果到達棧底仍未拋出異常,即說明調用棧中的所有方法均滿足保護域的權限要求,訪問控制允許操作發生。其中有一種特殊的情況,即當訪問控制遍歷調用棧時,將查找是否存在優先域(Privileged Domain),如果存在優先域,即使沒有到達棧底,訪問控制也將停止遍歷調用棧并允許操作發生。雖然新的安全機制初看上去增加了許多調用API方法的消耗,但是Java2確實使用了一些技術去加速檢查權限的過程,例如訪問控制將過濾掉重復的域并在遇到第一個優先域時停止檢查,這說明額外的操作將是一個本地的方法調用,SUN的基準測試顯示了新的安全檢查是相當快的。
最后,每個域包括系統或應用程序域可以對其域邊界內的內部資源進行附加保護。例如,一個銀行系統的應用程序可能需要支持并保護其內部的一些概念,如查帳、存款和取款等。由于此種保護的語義不像那些可預測的語義可以被JDK預置,因而,在這個層次上的保護最好留給系統或應用程序開發員來做。
目前,1個域單獨地由1個代碼來源(CodeSource)鑒別,它封裝了在該域中運行的代碼的2個特性:代碼基址和公共密鑰證書集,公共密鑰對應于在該域中為所有代碼簽字的私有密鑰。因而,由相同的密鑰簽字和來自相同URL的類被放在同一個域中。1個域還包含在該域中授予代碼的許可,它是由現行安全策略所決定的。
2.2 證書、鑰匙庫及其相關工具
在Java2的安全體系下,1個Applet開發和運行的過程如下:
在代碼的分發端:
(1)開發Java源程序并對其進行編譯。
(2)用JAR工具對類文件和資源文件進行封裝。
(3)用keytool創建公鑰和密鑰,生成X。509V1簽名證書,輸出證書。
(4)通過jarsigner工具用生成的密鑰對JAR文件進行數字簽名。
在代碼的接收端:
(1)用keytool輸入證書視其為可信任。
(2)用policytool創建和修改安全性策略配置文件,授權請求的訪問權限。
(3)從網絡取得字節碼,用公鑰驗證數字簽名證書和文檔代碼的完整性。
(4)驗證字節碼的合法性,根據策略文件分配相應權限。
(5)執行代碼,完成后被垃圾回收器回收內存。
在用公鑰驗證數字簽名證書之前,接收方需要確認公鑰自身的可靠性,因此通常情況是提供一個包含公鑰的證書而不是公鑰自身。1個證書包括:
(1)1個公鑰。
(2)1個唯一的名字實體(個人或公司),它是證書的所有者,包含用戶名字、公司、組織、城市、地址、國家代碼、省份等信息。
(3)數字簽名:1個證書被1個分發者的實體簽名,保證證書確實包含另1個實體(所有者)的公鑰。
(4)分發者的標識名信息。
對于接收者可以用分發者的公鑰來驗證他的數字簽名,檢查證書的合法性。然而公鑰可能包含在另一個證書中,而數字簽名需要用另一個證書的分發者的公鑰來驗證,這樣嵌套下去,直到一個公鑰被接收者確認是可信任的。如果接收者不能建立信任鏈,例如:1個分發者的證書不合法,那么可以用keytool-import命令來計算指紋,每個指紋是一個相關的短數字,它唯一可靠地標識證書(指紋是一個用信息摘要算法計算的證書信息的哈希值),接收者可以呼叫證書的所有者,并比較發出的證書和接收證書的指紋,如果指紋相同,則證書不同。因此能夠保證證書在傳遞的過程中未被修改。另一個潛在的問題是發送者身份的標識,有時一個證書是自簽名的,即使用證書中的公鑰相對應的密鑰進行簽名,如果接收者已經知道或信任發送者,那么就沒有任何問題。否則發送者需要從一個可信任的第3方得到證書,這個第3方通常是一個證書的授權機構CA,那么首先發送一個自簽名的證書簽名請求CSR給CA,由CA驗證CSR的簽名及發送CSR的身份、許可證以及其它信息。然后CA通過一個用CA的密鑰進行簽名的證書,授權CSR的發送者作為公鑰的所有者,任何人只要信任CA的公鑰,都可以用之來驗證證書的簽名,很多情況下CA自身有一個來自更高一級的CA的證書,從而構成證書鏈。所有信任的證書實體都可以作為信任證書被引入鑰匙庫,每個證書中的公鑰都可以用來驗證用相應的密鑰生成的簽名。
發送者在發送簽名的代碼和文檔時還相應提供包含與簽名的密鑰相應的公鑰證書。用keytool-export命令或API函數可以從鑰匙庫中輸出證書到文件中,然后將這個文件發送給需要的接收者,由接收者用keytool-import命令或API函數將其引入鑰匙庫中。如果用jarsigner工具為JAR文件生成簽名,他會從鑰匙庫中取出證書及證書鏈,并和簽名一起放入JAR文件。
密鑰和相應的公鑰證書存放在一個由口令保護的數據庫中,稱為鑰匙庫(keystore)。1個鑰匙庫包含2種類型的條目,可信任的證書條目,鑰匙和證書條目,每個都包含1個密鑰和與密鑰相應的公鑰證書,在鑰匙庫中的每個條目都有1個別名進行標識。1個鑰匙庫的所有者在鑰匙庫中可以有多個鑰匙,可以通過不同的別名進行訪問,每個別名通常是用鑰匙庫的所有者使用的鑰匙的特定角色來命名,別名也可以標識鑰匙的目的。例如:SignPersonalEmail可以被用來標識1個鑰匙庫的條目,它的密鑰用于簽名個人郵件,SignJarFiles用于標識1個條目,它的密鑰用于簽名JAR文件。
3 Applet的數字簽名認證實現的具體方法、步驟
3.1 結合我自己開發的基于JAVA2的Applet
我的項目是使用APPLET制作一個實時消息隊列監控程序,由于涉及到了本地資源,對APPLET一定要進行數字簽名和認證。我使用的環境是WINDOWS2000,應用服務器是WEBLOGIC6.0,開發環境是JBUILDER4.0。之前我提醒大家一定要注意服務器端和客戶端的概念。那些文件應該在服務器端,那些文件應該在客戶端。
首先在客戶端使用JRE1.3.0_01(JAVA運行環境1.3.0.1版本)以取代IE的JVM(JAVA虛擬機),可以到WWW.JAVA.SUN.COM網站上去下載,下載好了先在客戶端安裝好,安裝過程非常簡單。
在服務器端的調用APPLET的HTML文件中也需要將它包含進來,以便沒有事先安裝JRE的客戶端下載,具體的寫法,請接著往下看;
具體步驟如下:
服務器端:
1.將程序需要用到的各種包文件全部解壓(我這兒要用到WEBLOGIC的JMS包使用命令jarxfweblogicc.jar),然后使用JDK的打包命令將編譯好的監控程序.class和剛才解壓的包一起打包到一個包中。(前提我已經將監控程序和解開的包都放在同一個目錄下了),都是dos狀態下的命令,具體命令見jdk1.3(1.2)的bin目錄下,
命令如下:
jar cvfmonitor.jar *.class
此命令生成一個名為monitor.jar的包
2.為剛才創建的包文件(monitor.jar)創建keystore和keys。其中
keystore將用來存放密匙(private keys)和公共鑰匙的認證,alias別名這兒取為monitor。
命令如下:
keytool -genkey -keystore monitor.keystore –alias monitor
此命令生成了一個名為monitor.keystore的keystore文件,
接著這條命令,系統會問你好多問題,比如你的公司名稱,你
的地址,你要設定的密碼等等,都由自己的隨便寫。
3.使用剛才生成的鑰匙來對jar文件進行簽名
命令如下:
jarsigner-keystoremonitor.keystoremonitor.jar monitor
這個命令將對monitor.jar文件進行簽名,不會生成新文件。
4.將公共鑰匙導入到一個cer文件中,這個cer文件就是要拷貝到客戶端的唯一文件 。
命令如下:
keytool-export-keystoremonitor.keystore -alias monitor-filemonitor.cer
此條命令將生成monitor.cer認證文件,當然這幾步都有可能問你剛
才設置的密碼。
這樣就完成了服務器端的設置。這時你就可以將jar文件和keystore文件以及cer文件(我這兒是monitor.jar,monitor.keystore,monitor.cer)拷貝到服務器的目錄下了,我用的是weblogic6.0,所以就拷貝到C:\bea\wlserver6.0\config\mydomain\applications\DefaultWebApp_myserver下的自己建的一個目錄下了。
客戶端:
1.首先應該安裝jre1.3.0_01,然后將服務器端生成的monitor.cer
文件拷貝到jre的特定目錄下,我這兒是:
c:\program files\javasoft\jre\1.3.0_01\lib\security目錄下。
2.將公共鑰匙倒入到jre的cacerts(這是jre的默認keystore)
命令如下:
keytool-import-alias monitor -filemonitor.cer
-keystorecacerts
注意這兒要你輸入的是cacerts的密碼,應該是changeit,而不
是你自己設定的keystore的密碼。
3.修改policy策略文件,在dos狀態下使用命令policytool
系統會自動彈出一個policytool的對話框,如圖4所示,在這里面首先選擇file菜單的open項,
打開c:\program files\javasoft\jre\1.3.0_01\lib\security目錄下的java.poliy文件,然后在edit菜單中選擇Change keystore ,在對話框中new keystore url:中輸入
file:/c:/program files /javasoft/jre/1.3.0_01/lib/security/cacerts,
這兒要注意反斜杠,在new keystore type 中輸入JKS,這是cacerts的固定格式,然后單擊Add Policy Entry,在出現的對話框中CodeBase中輸入:
http://URL:7001/*
其中的URL是服務器的IP地址,7001是我的weblogic的端口,如果你是在別的應用服務器上比如說是apache,那端口號就可以省略掉。
在SignedBy中輸入(別名alias):這兒是Monitor
然后單擊add peimission按鈕,在出現的對話框中permission中選擇你想給這個applet的權限,這兒具體有許多權限,讀者可以自己找資料看看。我這兒就選用allpeimission,右邊的signedBy中輸入別名:monitor
最后保存,在file菜單的save項。
當然你可以看見我已經對多個包實現了簽名認證。
圖4-policytool的策略修改命令界面
這樣客戶端的設置就完成了。在客戶端用ie運行該applet程序時,會詢問你是不是對該簽名授權,選擇授權后,包會自動從服務器下載到本地計算機,而且ie會自動啟動jre,在右下欄中可以看見,相當于ie的java控制臺。
4.調用applet的html文件
大家都知道由于java2的安全性,對applet的正常調用的html文件已經不能再使用了,而改為ActiveX類型的調用。具體的又分ie和nescape的不同寫法,這一些在sun網上都能找到現成的教程。我就不多說了,只是將我的這個小程序為ie寫的的html給大家看看。
<html>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html;CHARSET=gb2312">
<center>
<h3>消息中心實時監控平臺</h3>
<hr>
<OBJECT classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"
width="900" height="520" align="baseline" codebase="http://192.168.2.217:7001/j2re-1_3_0_01-win-i.exe#Version=1,3,0,0">
<PARAM NAME="java_code" VALUE="wise.monitor.applet.monitorApplet">
<PARAM NAME="java_codebase" VALUE="monitor/classes">
<PARAM NAME="java_type" VALUE="application/x-java-applet;version=1.3">
<PARAM NAME="ARCHIVE" VALUE="monitor.jar" >
<PARAM NAME="scriptable" VALUE="true">
</OBJECT>
</center>
</html>
其中我要強調一點,因為applet每一次的改動都需要重新打包簽名,手續非常繁瑣,所以在具體的實現中要將一些會變化參數放到html文件中來,傳到applet中去,這一點網上文章好多,自己去看吧。
另外一個就是有朋友問我,那這樣不是太麻煩了,每一個客戶端都要進行復雜的dos命令操作,我只能說一目前我的水平只能將一個已經做好的客戶端文件cer文件和java.policy以及cacerts文件直接拷貝到客戶端,當然這也有缺陷,如果別人的計算機已經有了認證,就會丟失。就這些問題我們可以一起探討。
另外還有一點優化,就是在打包的時候,我這兒只講了把所有要用的涉及到安全性的包和源程序到要打到一個包中。這樣如果包非常大的話,會非常影響下載的速度,如果可以使用本地計算機的包就好了,這一點jre也做到了,具體的要到控制面板的jre控制臺上去設置。這個就留著讀者自己去摸索吧。
結束語
我發現網上java相關的資料非常少,中文的更少,所以希望自己能將一些小知識和大家共享,省掉許多重復的無用功。如果大家對這個問題還有不清楚的地方,或者就這問題相進一步展開討論的,請和我聯系,我的信箱是afeilb@163.net。希望我們能共同進步!
這篇文章也采納了一些別的文章的優點,在此要多謝
南京東南大學計算機科學與工程系的金勝昔、步俊杰、吉逸。
Afei
2001.6.11晚 北京