Java安全通信數(shù)字證書及數(shù)字證書應用實踐_第1頁
Java安全通信數(shù)字證書及數(shù)字證書應用實踐_第2頁
Java安全通信數(shù)字證書及數(shù)字證書應用實踐_第3頁
Java安全通信數(shù)字證書及數(shù)字證書應用實踐_第4頁
Java安全通信數(shù)字證書及數(shù)字證書應用實踐_第5頁
已閱讀5頁,還剩17頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、摘要: 在本文中,我用詳細的語言和大量的圖片及完整的程序源碼向你展示了在 JAVA中如何實現(xiàn)通過消息摘要、消息驗證碼達到安全通信、以及用Java的工具生成數(shù)字證書,和用程序給數(shù)字證書簽名、以及用簽名后的數(shù)學證書簽名applet突破applet的訪問權限的過程,給出了全部例子的詳細代碼。 通過本文中你可以學到以下知識: 程序間如何安全通信 什么是 及 如何生成消息摘要 什么是 及 如何生成消息驗證碼 如何使用 Java工具生成和維護數(shù)字證書庫 如何用程序給數(shù)字證書驗證簽名 如何利用數(shù)字證書給 applet簽名突破applet的訪問權限 關鍵字: 消息摘要、消息驗證碼、指紋、加密、安全、 Java

2、、數(shù)字簽名、applet、數(shù)字證書 一、基礎知識 計算機安全通信過程中,常使用消息摘要和消息驗證碼來保證傳輸?shù)臄?shù)據(jù)未曾被第三方修改。 消息摘要是對原始數(shù)據(jù)按照一定算法進行計算得到的結果,它主要檢測原始數(shù)據(jù)是否被修改過。消息摘要與加密不同,加密是對原始數(shù)據(jù)進行變換,可以從變換后的數(shù)據(jù)中獲得原始數(shù)據(jù),而消息摘要是從原始數(shù)據(jù)中獲得一部分信息,它比原始數(shù)據(jù)少得多,因此消息摘要可以看作是原始數(shù)據(jù)的指紋。 例:下面一段程序計算一段字符串的消息摘要 package com.messagedigest; import java.security.*; public class DigestPass publi

3、c static void main(String args) throws Exception String str=Hello,I sent to you 80 yuan.; MessageDigest md = MessageDigest.getInstance(MD5);/常用的有MD5,SHA算法等 md.update(str.getBytes(UTF-8);/傳入原始字串 byte re = md.digest();/計算消息摘要放入byte數(shù)組中 /下面把消息摘要轉換為字符串 String result = ; for(int i=0;ire.length;i+) result

4、+= Integer.toHexString(0 x000000ff&rei)|0 xffffff00).substring(6); System.out.println(result); 當我們有時需要對一個文件加密時,以上方式不再適用。 又例:下面一段程序計算從輸入(出)流中計算消息摘要。 package com.messagedigest; import java.io.*; import java.security.*; public class DigestInput public static void main(String args) throws Exception Stri

5、ng fileName = test.txt; MessageDigest md = MessageDigest.getInstance(MD5); FileInputStream fin = new FileInputStream(fileName); DigestInputStream din = new DigestInputStream(fin,md);/構造輸入流 /DigestOutputStream dout = new DigestOutputStream(fout,md); /使用輸入(出)流可以自己控制何時開始和關閉計算摘要 /也可以不控制,將全過程計算 /初始時是從開始即

6、開始計算,如我們可以開始時關閉,然后從某一部分開始,如下: /din.on(false); int b; while(b=din.read()!=-1) /做一些對文件的處理 /if(b=$) din.on(true); /當遇到文件中的符號$時才開始計算 byte re = md.digest();/獲得消息摘要 /下面把消息摘要轉換為字符串 String result = ; for(int i=0;ire.length;i+) result += Integer.toHexString(0 x000000ff&rei)|0 xffffff00).substring(6); System.

7、out.println(result); 當 A和B通信時,A將數(shù)據(jù)傳給B時,同時也將數(shù)據(jù)的消息摘要傳給B,B收到后可以用該消息摘要驗證A傳的消息是否正確。這時會產(chǎn)生問題,即若傳遞過程中別人修改了數(shù)據(jù)時,同時也修改了消息摘要。B就無法確認數(shù)據(jù)是否正確。消息驗證碼可以解決這一問題。 使用消息驗證碼的前提是 A和B雙方有一個共同的密鑰,這樣A可以將數(shù)據(jù)計算出來的消息摘要加密后發(fā)給B,以防止消息摘要被改。由于使用了共同的密鑰,所以稱為“驗證碼”。 例、下面的程序即可利用共同的密鑰來計算消息摘要的驗證碼 package com.mac; import java.io.*; import java.se

8、curity.*; import javax.crypto.*; import javax.crypto.spec.*; public class MyMac public static void main(String args) throws Exception /這是一個消息摘要串 String str=TestString; /共同的密鑰編碼,這個可以通過其它算法計算出來 byte kb=11,105,-119,50,4,-105,16,38,-14,-111,21,-95,70,-15,76,-74, 67,-88,59,-71,55,-125,104,42; /獲取共同的密鑰 Se

9、cretKeySpec k = new SecretKeySpec(kb,HMACSHA1); /獲取Mac對象 Mac m = Mac.getInstance(HmacMD5); m.init(k); m.update(str.getBytes(UTF-8); byte re = m.doFinal();/生成消息碼 /下面把消息碼轉換為字符串 String result = ; for(int i=0;ikeytool -genkey -alias abnerCA -keyalg RSA -keysize 1024 -keystore abnerCALib -validity 3650 如

10、下圖所示: 上圖中最后一步,我們輸入的是 CN,代表中國的縮寫,也可以直接輸入“中國”兩個字。 三、證書的操作方法 證書的顯示 如: keytool list keystore abnerCALib 將顯示 abnerCALib證書庫的的所有證書列表:如下圖示: 又如: keytool -list -alias abnerCA -keystore abnerCALib 將顯示 abnerCALib證書庫中別名為abnerCA的證書的信息。如下圖所示: 又如: keytool -list -v -alias abnerCA -keystore abnerCALib 將顯示證書的詳細信息( -v參

11、數(shù))如下圖所示: 將證書導出到證書文件 如: keytool -export -alias abnerCA -file abnerCA.cer -keystore abnerCALib 將把證書庫 abnerCALib中的別名為abnerCA的證書導出到abnerCA.cer證書文件中, 它包含證書主體的信息及證書的公鑰,不包括私鑰,可以公開,如下圖所示 : 上面導出的證書文件是以二進制編碼文件,無法用文本編輯器正確顯示,因此不利用公布證書,可以加上 -rfc參數(shù)以一種可打印的編者編碼輸出。 如: keytool -export -alias abnerCA -file abnerCA.cer

12、 -keystore abnerCALib -storepass 100200 rfc 這個命令在命令行中指定了證書庫的訪問密碼,同時指定以可查看編碼的方式輸出。 3、通過證書文件查看證書的信息 通過命令 :keytool printcert file abnerCA.cer可以查看證書文件的信息。 也可以在 windows中雙擊產(chǎn)生的證書文件直接查看。 證書條目的刪除 keytool的命令行參數(shù)-delete可以刪除密鑰庫中的條目,如: keytool -delete -alias abnerCA -keystore abnerCALib 這條命令將 abnerCALib庫中的abnerCA

13、這一條證書刪除了。 證書條目口令的修改 如: keytool keypasswd alias abnerCA keystore abnerCALib 可以以交互的方式修改 abnerCALib證書庫中的條目為abnerCA的證書。 Keytool keypasswd alias abnerCA keypass 123456 new 200100 storepass 1002 00 keystore abnerCALib 這一行命令以非交互式的方式修改庫中別名為 abnerCA的證書的密碼為新密碼123456,行中的200100是指該條證書的原密碼, 1002 00是指證書庫的密碼。 三、數(shù)字證

14、書的簽發(fā)(簽名) 我們在上面創(chuàng)建好了數(shù)字證書,但這些數(shù)字證書還沒有經(jīng)過權威 CA的證實(即簽名)。一般情況下,我們需要將這些證書發(fā)送給權威的CA,并申請其簽名以確認數(shù)字證書讓客戶信任。 下面我們將模仿自己是一個權威的數(shù)字證書認證機構 CA,這個機構將采用自己的私鑰來簽發(fā)其它的證書。這個簽發(fā)過程是這樣的:我們自己是CA,我們自己有一個自簽的數(shù)字證書存入數(shù)字證書庫中。在數(shù)字證書庫中的這個我們的CA數(shù)字證書,它含有私鑰,公鑰和我們這個CA的主體信息。下面這一個指令可以創(chuàng)建一個CA的自簽的數(shù)字證書: keytool genkey dname “CN=美森系統(tǒng)軟件有限公司,OU=美森系統(tǒng)軟件有限公司,O

15、=美森系統(tǒng)軟件有限公司,L=成都市,ST=四川省,C=中國” alias MissionCA keyalg RSA keysize 1024 keystore abnerCALib keypass 200100 storepass 100200 validity 3650 上面,我們在 abnerCALib這個數(shù)字證書庫中創(chuàng)建了一個別名為:missionCA、有效期為3650天、算法為RSA且密鑰長度為1024的數(shù)字證書,這條證書的私鑰密碼為:200100,證書庫的訪問密碼為:100200。這條別名為missionCA的證書代表我們自己的權威CA即:美森系統(tǒng)軟件有限公司這個權威CA。以后我們將

16、用這個證書來簽名其它的數(shù)字證書。 現(xiàn)在我要給自己申請一個數(shù)字證書,我可以這么做:先在數(shù)字證書庫中創(chuàng)建一條證書: keytool genkey dname “CN=柴政,OU=美森系統(tǒng)軟件有限公司,O=美森系統(tǒng)軟件有限公司,L=成都市,ST=四川省,C=中國” alias abnerCA keyalg RSA keysize 1024 keystore abnerCALib keypass 200100 storepass 100200 validity 3650 這樣創(chuàng)建了一個別名為 abnerCA的數(shù)字證書,我們可以將它導出為cer文件(見前)。 接著,我們可以用上一步生成的 CA的自簽證書

17、來簽名我這個數(shù)字證書了。 CA簽名數(shù)字證書的過程需用以下程序來進行,這個程序是自解釋的: package com.security; import java.io.*; import java.security.*; import java.security.cert.*; import java.util.*; import java.math.*; import sun.security.x509.*; /* * Description: 該程序根據(jù)簽發(fā)者(CA)的證書信息(即CA的私鑰)來對被簽發(fā)者 * 的證書進行簽名,過程即是使用CA的證書和被簽證書來重構形成一個新的證書 * auth

18、or abnerchai * version 1.0 */ public class SignCert public static void main(String args) throws Exception char storepass = 100200.toCharArray();/存放CA證書和被簽證書的證書庫的訪問密碼 char cakeypass = 200100.toCharArray();/CA數(shù)字證書條目的訪問密碼 String alias = missionCA;/CA證書在證書庫中的別名,這個CA的證書用來簽名其它的證書 String name = abnerCALib;

19、/存放CA證書和被簽證書的證書庫的名字 String newLib = SignedLib;/新證書庫的名字,如果需要將簽名后的證書放入新庫,這是新庫的名字 char newLibPass = 100200.toCharArray();/設置新庫的訪問密碼 String cerFileName = abnerCA.cer;/被簽證書的證書文件名 String aliasName = abnerCA;/被簽證書在證書庫中的alias別名 char namePass = 200100.toCharArray();/被簽證書的條目在證書庫的私鑰密碼 int n =3; /被簽證書的有效期,以年為單位

20、,以當前時間開始計算 int sn = 200406001;/序列號可自己定義,這里定義的意義為2004年6月簽發(fā),是本年度CA簽發(fā)的第多少個以001計算,要求唯一 String afteraliasName = abnerCA_Signed; /簽名后新產(chǎn)生的被簽過名的證書在庫中的別名 char afterNewPass = 200100.toCharArray(); /簽名后新產(chǎn)生的被簽過名的證書在庫的條目的私鑰的密碼 /裝載證書庫 FileInputStream in = new FileInputStream(name); KeyStore ks = KeyStore.getInsta

21、nce(JKS);/JKS為證書庫的類型 ks.load(in,storepass); /從證書庫中讀出簽發(fā)者(CA)的證書 java.security.cert.Certificate cl = ks.getCertificate(alias);/讀出一個CA證書,這里的l是字母l不是數(shù)據(jù)字1 PrivateKey privateKey = (PrivateKey)ks.getKey(alias,cakeypass);/根據(jù)別名和證書密碼讀出CA證書的私鑰 in.close(); /從證書庫中讀出的簽發(fā)者(CA)的證書中提取簽發(fā)者的信息 byte encodl = cl.getEncoded

22、();/提取證書的編碼,這里是字母l不是數(shù)據(jù)字1 X509CertImpl cimpl = new X509CertImpl(encodl);/這里是字母l不是數(shù)據(jù)字1,根據(jù)證書的編碼創(chuàng)建X509CertImpl類型的對象 /根據(jù)上面的對象獲得X509CertInfo類型的對象,該對象封裝了證書的全部內容。 X509CertInfo cinfo_first = (X509CertInfo)cimpl.get(X509CertImpl.NAME+.+X509CertImpl.INFO); /然后獲得X500Name類型的簽發(fā)者信息 X500Name issuer = (X500Name) cin

23、fo_first.get(X509CertInfo.SUBJECT+.+CertificateIssuerName.DN_NAME); /獲取待簽發(fā)的證書,即獲取被簽發(fā)者的證書 /可從密鑰庫中獲取,也可從導出的證書文件中獲取,這里給出兩種方式 / /方式一、采用從導出的cer文件中獲取 start / /* CertificateFactory cf = CertificateFactory.getInstance(X.509);/X.509是使用最多的一種數(shù)字證書標準 FileInputStream in2 = new FileInputStream(cerFileName);/被簽證書文件

24、 java.security.cert.Certificate c2 = cf.generateCertificate(in2);/生成需要被簽的證書 in2.close(); byte encod2 = c2.getEncoded(); X509CertImpl cimp2 = new X509CertImpl(encod2); /獲得被簽證書的詳細內容,然后根據(jù)這個證書生成新證書 X509CertInfo cinfo_second = (X509CertInfo)cimp2.get(X509CertImpl.NAME+.+X509CertImpl.INFO); */ / /end 方式一

25、/ / /方式二、從證書庫中讀出被簽的證書 start / java.security.cert.Certificate c3 = ks.getCertificate(aliasName);/從證書庫中讀出被簽證書,然后生成新的證書 byte encod3 = c3.getEncoded(); X509CertImpl cimp3 = new X509CertImpl(encod3); X509CertInfo cinfo_second = (X509CertInfo)cimp3.get(X509CertImpl.NAME+.+X509CertImpl.INFO); / /end方式二 / /

26、設置新證書的有效期,使之為當前向后n年有效,新證書的 /截止日期不能超過CA證書的有效日期 Date beginDate = new Date(); Calendar cal = Calendar.getInstance(); cal.setTime(beginDate); cal.add(cal.YEAR,n); Date endDate = cal.getTime(); CertificateValidity cv = new CertificateValidity(beginDate,endDate); cinfo_second.set(X509CertInfo.VALIDITY,cv)

27、; /設置新證書的序列號 CertificateSerialNumber csn = new CertificateSerialNumber(sn); cinfo_second.set(X509CertInfo.SERIAL_NUMBER,csn); /設置新證書的簽發(fā)者 cinfo_second.set(X509CertInfo.ISSUER+.+CertificateIssuerName.DN_NAME, issuer); /新的簽發(fā)者是CA的證書中讀出來的 /設置新證書的算法,指定CA簽名該證書所使用的算法為md5WithRSA AlgorithmId algorithm = new A

28、lgorithmId(AlgorithmId.md5WithRSAEncryption_oid); cinfo_second.set(CertificateAlgorithmId.NAME+.+ CertificateAlgorithmId.ALGORITHM,algorithm); /創(chuàng)建新的簽名后的證書 X509CertImpl newcert = new X509CertImpl(cinfo_second); /簽名,使用CA證書的私鑰進行簽名,簽名使用的算法為MD5WithRSA newcert.sign(privateKey,MD5WithRSA);/這樣便得到了經(jīng)過CA簽名后的證書

29、 /把新證書存入證書庫 /把新生成的證書存入一個新的證書庫,也可以存入原證書庫, /存入新證書庫,則新證書庫中不僅包含原證書庫中的所有條目, /而且新增加了一個這次產(chǎn)生的條目。注意,這時,新產(chǎn)生的簽名后的證書只 /包括公鑰和主體信息及簽名信息,不包括私鑰信息。這里給出兩種方式。 / /方式一:存入新密鑰庫 / /* ks.setCertificateEntry(afteraliasName,newcert); FileOutputStream out = new FileOutputStream(newLib); /存入新庫signedLib,并設置新庫的庫訪問密碼 ks.store(out,

30、newLibPass); out.close(); */ / /end 方式一 / /也可以采用另外一種方式,存入原證書庫中 /存入原庫中,即在原證書庫中增加一條證書,這個證書是原證書經(jīng)過簽名后的證書 /這個新證書含有私鑰和私鑰密碼 / /方式二,存入原密鑰庫 / /先在原庫中讀出被簽證書的私鑰 PrivateKey prk = (PrivateKey)ks.getKey(aliasName,namePass); java.security.cert.Certificate cchain = newcert; /存入原來的庫,第二個參數(shù)為原證書的私鑰,第三個參數(shù)為新證書的私鑰密碼,第三個參數(shù)為

31、新證書 ks.setKeyEntry(afteraliasName,prk,afterNewPass,cchain); /用新密鑰替代原來的沒有簽名的證書的密碼 FileOutputStream out2 = new FileOutputStream(name); ks.store(out2,storepass);/存入原來的庫中,第二個參數(shù)為該庫的訪問密碼 / /end 方式二 / 運行以上程序,即可運用 MissionCA證書來簽發(fā)abnerCA證書,運行后在abnerCALib中增加一條別名為abnerCA_Signed的數(shù)字證書,我們將它導出為cer文件(導出方法見前)。 至此,我們己

32、經(jīng)用 CA的證書以我們的數(shù)字證書簽名了。在windows中,雙擊導出的abnerCA_Signend.cer文件,出現(xiàn)如下圖所示: 上圖中證書信息一欄顯示“不能驗證該證書”,原因是因為,我們的這個數(shù)字證書的簽發(fā)者 missionCA證書沒有安裝到系統(tǒng)中。我們可以將證書庫中別名為missionCA的自簽數(shù)字證書導出為cer文件,然后安裝到系統(tǒng)中。再次查雙擊看此證書,如下圖所示: 到此,我們己經(jīng)獲得了一個由我們自己的 CA簽名頒發(fā)的個人數(shù)字證書。并且將我們自己的CA證書安裝到系統(tǒng)中成為系統(tǒng)信任的根證書。于是,以后只要是由我們的這個CA證書簽名頒發(fā)的數(shù)字證書都會受到系統(tǒng)的信任。 四、利用數(shù)字證書給

33、applet簽名 現(xiàn)在假設我們公司給 xx公司做一個項目,這個項目中需要用到applet,且這些applet需要特權以實現(xiàn)一些特殊的功能(如讀出客戶端用戶系統(tǒng)中C:winNTsystem.ini文件中的內容并顯示)。那么我們可以頒發(fā)一個數(shù)字證書,并給這個數(shù)字證書簽名,然后用簽名后的這個數(shù)字證書來簽名我們的applet,使客戶信任。具體過程如下: 一、生成一個用于此項目簽名 applet 的數(shù)字證書,別名定為: mission_water 生成一個用于此項目簽名的數(shù)字證書如下: keytool genkey dname “CN=美森軟件-水公司項目,OU=美森系統(tǒng)軟件有限公司,O=美森系統(tǒng)軟件有

34、限公司,L=成都市,ST=四川省,C=中國” alias Mission_Water keyalg RSA keysize 1024 keystore abnerCALib keypass 200100 storepass 100200 validity 3650 二、用我們的 CA(missinCA) 來簽發(fā)這個數(shù)字證書 然后,運行我們在前面第三節(jié)中給定的程序,注意:運行此程序前,請修改以下參數(shù): String cerFileName = Mission_Water.cer; String aliasName = Mission_Water; String afteraliasName =

35、Mission_Water_Signed; 然后運行,程序會在 abnerCALib證書庫中產(chǎn)生一個別名為:Mission_Water_Signed的數(shù)字證書,這個證書是經(jīng)過我們的CA(MissionCA)簽發(fā)的。 下面,我們用以下指令導出這個證書: keytool -export -alias Mission_Water_Signed -file Mission_Water_Signed.cer -keystore abnerCALib -rfc 會生成一個 Mission_Water_Signed.cer 文件。 三、用簽發(fā)后的數(shù)字證書來簽名我們的 applet 我們現(xiàn)在來做一個簡單的 a

36、pplet,它的代碼如下: package com.applet; import java.awt.*; import java.awt.event.*; import java.applet.*; import javax.swing.*; import java.io.*; public class ShowFileApplet extends JApplet private boolean isStandalone = false; private String content = 文件的內容是:; /自定義的提示信息 private String fileName = C:WINNTs

37、ystem.ini;/讀出這個文件的內容 private TextArea ta = new TextArea(10,80);/自定義的輸出框 public String getParameter(String key, String def) return isStandalone ? System.getProperty(key, def) : (getParameter(key) != null ? getParameter(key) : def); public ShowFileApplet() public void init() try jbInit(); myInit();/自己

38、定義的方法 catch(Exception e) e.printStackTrace(); private void jbInit() throws Exception this.setSize(new Dimension(400,300); /* * 自定義的初始化方法,讀入系統(tǒng)中的一個文件的內容并保存起來,然后,增加一個 * 可視化的輸出框 */ private void myInit() String s; BufferedReader in; try in = new BufferedReader(new FileReader(fileName); while ( (s = in.re

39、adLine() != null) content +=s + n; catch (IOException ex) ex.printStackTrace(); System.out.println(content); ta.setText(content); getContentPane().add(ta); /* *重載的方法,輸出內容 */ public void paint(Graphics g) ta.setText(content); public String getAppletInfo() return Applet Information; public String getParameterInfo() return null; /static initializer for setting look & feel static try catch(Exception e) 好了,這個 applet寫好了,下面我們來把這個applet編譯打包成jar文件。 編譯此 applet文件,會在當前目錄(當前目錄為classes目錄)下生成一個com

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論