Java與數字簽名
sylilzy@163.com
版權所有,轉載請注明出處
關鍵字:Java 數字簽名 PKI Keystore 數字證書 keytool jarsigner
摘要:本文介紹了數字簽名的相關基礎知識,并介紹了如何用java實現數字簽名。
數字簽名作為一種電子身份的認證的手段,被普遍用于網上銀行,安全網絡通信等領域.數字簽名是電子簽名的一種特定形式.本文不對數字簽名的原理作介紹,只對相關概念作一些簡單的介紹,詳細講解了在java中如何對jar文件進行數字簽名.
數字簽名的相關概念
實際上數字簽名又稱作基于PKI的電子簽名, PKI的核心機構是電子認證服務提供者,即通稱的認證機構CA,PKI簽名的核心元素是由CA簽發的數字證書,數字證書就如同日常生活中的身份證一樣,用來標識網上實體的身份,CA就是對網上實體進行認證的第三方機構.數字證書就是CA機構對網上實體進行認證而產生的電子證書,它是數據簽名的基礎技術保障.CA機構對電子證書的有效性,有效期等提供查詢服務.數字證書所包含公鑰用來對使用對應的私鑰加密的數據信息進行驗證.
數字簽名實現的具體原理是:
1、 將報文按雙方約定的HASH算法計算得到一個固定位數的報文摘要。在數學上保證,只要改動報文中任何一位,重新計算出的報文摘要值就會與原先的值不相符。這樣就保證了報文的不可更改性。(詳見參考資料的"公鑰密碼技術原理"章節)
2、 將該報文摘要值用發送者的私人密鑰加密,然后連同原報文和數字證書(包含公鑰)一起發送給接收者而產生的報文即稱數字簽名。
3、接收方收到數字簽名后,用同樣的HASH算法對報文計算摘要值,然后與用發送者的公開密鑰進行解密解開的報文摘要值相比較,如相等則說明報文確實來自所稱的發送者。
4、同時通過證書頒發機構CA確認證書的有效性即可確認發送的真實身份。
數字證書的技術實現:
數字證書是公鑰的載體,是PKI的核心元素.數字證書符合X.509標準,現行的PIK機制一般為又證書,即一個實體一般有兩個證書,兩個密碼對,一個用于電子簽名,一個用于加密通信.按照X.509標準,一個標準和數字證書的格式為:
CA《A》=CA{V,SN,AI,CA,UCA,A,UA,Ap,Ta}
它將包含證書頒發機構和標識及用戶的標識,證書ID,有效期等信息(詳見參考資料),另外還包含CA對此證書內容的進行了數字簽名,以驗證此證書的有效性.在驗證一個數字證書的過程中,對數字證書的數字簽名的驗證將遞歸進行,只到找到雙方共同可信任的CA根證書為止.
如何獲取數字證書
數字證書可向專門的CA機構申請,有免費的數字證書和付費的數字證書.比如:中國數字認證網(http://www.ca365.com)、廣東省電子商務認證中心(http://www.cnca.net/)就可申請到有效期為一年的免費數字證書.注意申請的證書是以該CA的證書作為申請的個人證書的根證書,所以如果想要申請的證書有效,需要下載并安裝相應CA的根證書.另外,其它一些工具也可生成個人使用的數字證書,如微軟的makecert(下載地址http://www.microsoft.com/downloads/details.aspx?familyid=2b742795-d0f0-4a66-b27f-22a95fcd3425&displaylang=en)),JDK中包含的keytool工具(以下會詳細介紹如何使用)都可生成沒有經過認證的數字證書.
Java如何實現數字簽名
JDK有部分工具和API提供了對數字簽名的支持:keytool,jarsigner,policytool等.
KeyTool工具可生成,導入,導出數字證書,支持的證書的格式為當前流行的
生成證書:keytool -genkey -alias mykey -keystore mystore
導入證書:keytool -import -alias abc -file ABCCA.cer -keystore mystore
導出證書: keytool -export -alias mykey -file MJ.cer -keystore mystore
對jar文件進行簽名使用的工具是jarsigner:
格式如下:jarsigner -keystore keystoreFile jarfile alias
例如:jarsigner -keystore sylilzyKeystore.dat test.jar sylilzy
驗證一個jar文件如下:
jarsigner -verify jarfile
以下步驟演示了一個完整的由獲取數字證書到簽名jar文件,然后訪問該jar文件時顯示簽名信息的全過程:
上面提到,數字證書可由以下方式生成,第一,去http://www.ca365.com申請一個免費的數字證書,下載后為test.der
也可用keytool -genkey -alias mykey -keystore mystore生成,運行此命令后,提示相關信息,并填寫完畢,如下:
E:\temp>keytool -genkey -alias mykey -keystore mystore
輸入keystore密碼: 111111
您的名字與姓氏是什么?
[Unknown]: shi
您的組織單位名稱是什么?
[Unknown]: eshore
您的組織名稱是什么?
[Unknown]: de
您所在的城市或區域名稱是什么?
[Unknown]: gz
您所在的州或省份名稱是什么?
[Unknown]: gd
該單位的兩字母國家代碼是什么
[Unknown]: cn
CN=shi, OU=eshore, O=de, L=gz, ST=gd, C=cn 正確嗎?
[否]: y
輸入<mykey>的主密碼
(如果和 keystore 密碼相同,按回車):
到此,我們則生成了一個名為mystore的keystore文件,該文件中保存有別名為mykey的數字證書.輸入以下命令即可查看此數字證書:
E:\temp>keytool -list -alias mykey -keystore mystore
輸入keystore密碼: 111111
mykey, 2006-7-5, keyEntry,
認證指紋 (MD5): A1:A9:A7:C6:D8:E5:E5:20:EA:80:59:AF:C2:65:B4:17
或者帶上-v參數顯示詳細信息
E:\temp>keytool -list -alias mykey -keystore mystore -v
輸入keystore密碼: 111111
別名名稱: mykey
創建日期: 2006-7-5
輸入類型:KeyEntry
認證鏈長度: 1
認證 [1]:
Owner: CN=shi, OU=eshore, O=de, L=gz, ST=gd, C=cn
發照者: CN=shi, OU=eshore, O=de, L=gz, ST=gd, C=cn
序號: 44ab3fb8
有效期間: Wed Jul 05 12:27:36 CST 2006 至: Tue Oct 03 12:27:36 CST 2006
認證指紋:
MD5: A1:A9:A7:C6:D8:E5:E5:20:EA:80:59:AF:C2:65:B4:17
SHA1: AC:8D:AA:9D:A7:62:48:70:ED:F4:28:4C:DC:DE:56:CE:41:FE:52:C9
以上為創建的一個證書,我們可以將它從keystore文件中導出:
E:\temp>keytool -export -keystore mystore -alias mykey -file my.cer
輸入keystore密碼: 111111
保存在文件中的認證 <my.cer>
我們也可將前面從網上申請的電子證書導入keystore文件:
E:\temp>keytool -import -alias sily -file test.der -keystore mystore
輸入keystore密碼: 111111
Owner: CN=施祖陽, OU=develop, O=eshore, L=廣州, ST=廣東, C=CN
發照者: CN=CA365 Free Root Certificate, O=CA365, L=Beijing, ST=Beijing, C=CN
序號: 653e1a63bb003fb3
有效期間: Tue Jul 04 12:02:25 CST 2006 至: Wed Jul 04 12:02:25 CST 2007
認證指紋:
MD5: 4A:AA:63:2A:8A:E2:8D:76:4B:2B:73:E9:F3:03:CD:6F
SHA1: 02:B3:9E:D0:7E:BB:9E:C4:B3:B0:79:19:FA:89:B6:93:DB:0F:4A:88
信任這個認證? [否]: y
認證已添加至keystore中
現在查看mystore中已經存了兩個證書:
E:\temp>keytool -list -keystore mystore
輸入keystore密碼: 111111
Keystore 類型: jks
Keystore 提供者: SUN
您的 keystore 包含 2 輸入
sily, 2006-7-5, trustedCertEntry,
認證指紋 (MD5): 4A:AA:63:2A:8A:E2:8D:76:4B:2B:73:E9:F3:03:CD:6F
mykey, 2006-7-5, keyEntry,
認證指紋 (MD5): A1:A9:A7:C6:D8:E5:E5:20:EA:80:59:AF:C2:65:B4:17
現在,我們開始利用前面生成的數字證書給jar文件簽名.由于applet在瀏覽器中運行時的權限是受限的,不能對本地文件進行讀寫,但是如果applet所在的jar文件如果是經過數字簽名,并且用戶信任該簽名,那此applet則可對本地文件進行讀寫,下面給出一個寫本地文件的applet:
package ? com.applet;
import ? java.applet.Applet;
public ? class ? TestSecurity ? extends ? Applet ? {
???? /**
????? * ?
????? */
???? private ? static ? final ? long ? serialVersionUID ? = ? 1L;
???? public ? TestSecurity() ? {
???????? System. out .println( "this?is?good!?" );
???? }
???? public ? void ? init() ? {
???????? JButton ? button ? = ? new ? JButton( "Create?a?file" );
???????? button.addActionListener( new ? ActionListener() ? {
???????????? public ? void ? actionPerformed(ActionEvent ? evt) ? {
???????????????? File ? file ? = ? new ? File( "c:\\a.txt" );
???????????????? try ? {
???????????????????? file.createNewFile();
???????????????????? JOptionPane. showMessageDialog ( null , ? "?成功創建文件c:\\a.txt" , ? "消息" ,
???????????????????????????? JOptionPane. INFORMATION_MESSAGE );
???????????????? } ? catch ? (Exception ? ex) ? {
???????????????????? JOptionPane. showMessageDialog ( null , ? ex.getMessage(), ? "錯誤" , ? JOptionPane. ERROR_MESSAGE );
???????????????? }
???????????? }
???????? });
???????? add(button);
???? }
}
將此文件編譯后生成在com\applet生成兩個class文件,用jar打包:
E:\sylilzy\documents\project\tjava\classes>jar -cvf test.jar com
標明清單(manifest)
增加:com/(讀入= 0) (寫出= 0)(存儲了 0%)
...
會發現在當前目錄下會生成一個"test.jar"文件,將此文件copy到與mystore同一個目錄,準備對該文件進行電子簽名.
E:\temp>jarsigner -keystore mystore test.jar mykey
輸入密鑰庫的口令短語: 111111
警告: 簽名者證書將在六個月內過期。
則test.jar已經被簽名,編碼一個簡單的html文件對其進行訪問,html如下:
Created with Colorer-take5 Library. Type 'html' <html><head><metahttp-equiv="Content-Type"content="text/html; charset=GB2312"><title> HTML Test Page </title></head><body> test.Applet1 will appear below in a Java enabled browser.<br><appletcodebase="."code="com.applet.TestSecurity"name="TestApplet"width="400"height="300"hspace="0"vspace="0"align="middle"archive="test.jar"></applet></body></html>
將以上html文件與test.jar文件放在同一目錄,用IE打開,則可看到IE彈出安全警告: The application's digital signature is invalid.Do you want to run the application?
用戶可查看test.jar的簽名信息,如果選擇取消息,然后點擊create a file 按鈕,則提示:access denied(java.io.FilePermission c:\a.txt write)
如果在IE彈出安全警告選擇"始終信任此發行者的內容",然后點擊運行,再點擊create a file 按鈕,則提示:成功創建文件c:\a.txt
上面給test.jar簽名的數字證書是未經驗證的,現在我們使用從網上申請的經過驗證的數字證書給test.jar簽名,看會出現什么結果:
E:\temp>jarsigner -keystore mystore test.jar sily
輸入密鑰庫的口令短語: 111111
jarsigner: 找不到 sily 的證書鏈。sily 必須引用包含專用密鑰和相應的公共密鑰證書鏈的有效密鑰庫密鑰條目。
這是因為sily的證書鏈不存在導致的,我們需要導入sily的證書鏈才可形成完整的sily的證書鏈,可以通過keytool -certreq生成證書鏈的PKCS#10格式的請求,然后再導入請求的PKCS#7格式的回復即可,由于名為sily的key是從cer文件導入的,它在keystore中是以trusted certificate entries類型存儲的,沒有私鑰,所以不能生成證書鏈的請求.我們可以將前面名為mykey的key導出證書請求,或者導出mykey的證書,然后將此證書安裝至"受信任的根證書頒發機構",然后訪問用此證書簽名過的文件,則IE將不再彈出安全警告窗口.
公告
參考資料:
http://www.qqread.com/net-saft/z532114081.html 電子簽名的技術實現
http://www.qqread.com/java/w292768600.html JAVA對數字證書的常用操作
http://java.sun.com/j2se/1.5.0/docs/index.html JDK 5.0 Documentation