Java安全通信、數字證書及應用實踐
摘要:
在本文中,我用詳細的語言和大量的圖片及完整的程序源碼向你展示了在 JAVA中如何實現通過消息摘要、消息驗證碼達到安全通信、以及用Java的工具生成數字證書,和用程序給數字證書簽名、以及用簽名后的數學證書簽名applet突破applet的訪問權限的過程,給出了全部例子的詳細代碼。
通過本文中你可以學到以下知識:
● 程序間如何安全通信
● 什么是 及 如何生成消息摘要
● 什么是 及 如何生成消息驗證碼
● 如何使用 Java工具生成和維護數字證書庫
● 如何用程序給數字證書驗證簽名
● 如何利用數字證書給 applet簽名突破applet的訪問權限
關鍵字:
消息摘要、消息驗證碼、指紋、加密、安全、 Java、數字簽名、applet、數字證書
一、基礎知識
計算機安全通信過程中,常使用消息摘要和消息驗證碼來保證傳輸的數據未曾被第三方修改。
消息摘要是對原始數據按照一定算法進行計算得到的結果,它主要檢測原始數據是否被修改過。消息摘要與加密不同,加密是對原始數據進行變換,可以從變換后的數據中獲得原始數據,而消息摘要是從原始數據中獲得一部分信息,它比原始數據少得多,因此消息摘要可以看作是原始數據的指紋。
例:下面一段程序計算一段字符串的消息摘要
當我們有時需要對一個文件加密時,以上方式不再適用。
又例:下面一段程序計算從輸入(出)流中計算消息摘要。
當A和B通信時,A將數據傳給B時,同時也將數據的消息摘要傳給B,B收到后可以用該消息摘要驗證A傳的消息是否正確。這時會產生問題,即若傳遞過程中別人修改了數據時,同時也修改了消息摘要。B就無法確認數據是否正確。消息驗證碼可以解決這一問題。
使用消息驗證碼的前提是 A和B雙方有一個共同的密鑰,這樣A可以將數據計算出來的消息摘要加密后發給B,以防止消息摘要被改。由于使用了共同的密鑰,所以稱為“驗證碼”。
例、下面的程序即可利用共同的密鑰來計算消息摘要的驗證碼
使用以上兩種技術可以保證數據沒有經過改變,但接收者還無法確定數據是否確實是某個人發來的。盡管消息碼可以確定數據是某個有同樣密鑰的人發來的,但這要求雙方具有共享的密鑰,若有一組用戶共享,我們就無法確定數據的來源了。
數字簽名可以解決這一問題。數字簽名利用非對稱加密技術,發送者使用私鑰加密數據產生的消息摘要(簽名),接收者使用發送者的公鑰解密消息摘要以驗證簽名是否是某個人的。由于私鑰只有加密者才有,因此如果接收者用某個公鑰解密了某個消息摘要,就可以確定這段消息摘要必然是對應的私鑰持有者發來的。
使用數字簽名的前提是接收數據者能夠確信驗證簽名時(用發送者的私鑰加密消息摘要)所用的公鑰確實是某個人的 (因為有可能有人假告公鑰)。數字證書可以解決這個問題。
數字證書含有兩部分數據:一部分是對應主體(單位或個人)的信息,另一部分是這個主體所對應的公鑰。即數字證書保存了主體和它的公鑰的一一對應關系。同樣,數字證書也有可能被假造,如何判定數字證書的內容的真實性呢?所以,有效的數字證書必須經過權威 CA的簽名,即權威CA驗證數字證書的內容的真實性,然后再在數字證書上使用自己的私鑰簽名(相當于在證書加章確認)。
這樣,當用戶收到這樣的數字證書后,會用相應的權威 CA的公鑰驗證該證書的簽名(因為權威的CA的公鑰在操作系統中己經安裝)。根據非對稱加密的原理,如果該證書不是權威CA簽名的,將不能通過驗證,即該證書是不可靠的。
若通過驗證,即可證明此證書含的信息(發信人的公鑰和信息)是無誤的。于是可以信任該證書,便可以通過該證書內含的公鑰來確認數據確實是發送者發來的。
于是,雙方通信時, A把數據的消息摘要用自己的私鑰加密(即簽名),然后把自己的數字證書和數據及簽名后的消息摘要一起發送給B,B處查看A的數字證書,如果A的數字證書是經過權威CA驗證可靠的,便信任A,便可使用A的數字證書中附帶的A的公鑰解密消息摘要(這一過程同時確認了發送數據的人又可以解密消息摘要),然后通過解密后的消息摘要驗證數據是否正確無誤沒被修改。
利用這一原理,我們可以突破 java的applet小程序在瀏覽器中的權限,由于默認的applet權限控制不允許它訪問操作系統級的一切。于是我們可以用我們數字證書來給applet簽名,然后客戶端收到該applet時,系統會自動查看給該applet簽名的數字證書并提供給終端用戶判定是否信認該數字證書,如果用戶信認,則該applet便有了訪問系統的權限。
在本文中,我用詳細的語言和大量的圖片及完整的程序源碼向你展示了在 JAVA中如何實現通過消息摘要、消息驗證碼達到安全通信、以及用Java的工具生成數字證書,和用程序給數字證書簽名、以及用簽名后的數學證書簽名applet突破applet的訪問權限的過程,給出了全部例子的詳細代碼。
通過本文中你可以學到以下知識:
● 程序間如何安全通信
● 什么是 及 如何生成消息摘要
● 什么是 及 如何生成消息驗證碼
● 如何使用 Java工具生成和維護數字證書庫
● 如何用程序給數字證書驗證簽名
● 如何利用數字證書給 applet簽名突破applet的訪問權限
關鍵字:
消息摘要、消息驗證碼、指紋、加密、安全、 Java、數字簽名、applet、數字證書
一、基礎知識
計算機安全通信過程中,常使用消息摘要和消息驗證碼來保證傳輸的數據未曾被第三方修改。
消息摘要是對原始數據按照一定算法進行計算得到的結果,它主要檢測原始數據是否被修改過。消息摘要與加密不同,加密是對原始數據進行變換,可以從變換后的數據中獲得原始數據,而消息摘要是從原始數據中獲得一部分信息,它比原始數據少得多,因此消息摘要可以看作是原始數據的指紋。
例:下面一段程序計算一段字符串的消息摘要
| package com.messagedigest; import java.security.*; public class DigestPass { public 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數組中 //下面把消息摘要轉換為字符串 String result = ""; for(int i=0;i<re.length;i++){ result += Integer.toHexString((0x000000ff&re[i])|0xffffff00).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{ String 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); //使用輸入(出)流可以自己控制何時開始和關閉計算摘要 //也可以不控制,將全過程計算 //初始時是從開始即開始計算,如我們可以開始時關閉,然后從某一部分開始,如下: //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;i<re.length;i++){ result += Integer.toHexString((0x000000ff&re[i])|0xffffff00).substring(6); } System.out.println(result); } } |
當A和B通信時,A將數據傳給B時,同時也將數據的消息摘要傳給B,B收到后可以用該消息摘要驗證A傳的消息是否正確。這時會產生問題,即若傳遞過程中別人修改了數據時,同時也修改了消息摘要。B就無法確認數據是否正確。消息驗證碼可以解決這一問題。
使用消息驗證碼的前提是 A和B雙方有一個共同的密鑰,這樣A可以將數據計算出來的消息摘要加密后發給B,以防止消息摘要被改。由于使用了共同的密鑰,所以稱為“驗證碼”。
例、下面的程序即可利用共同的密鑰來計算消息摘要的驗證碼
| package com.mac; import java.io.*; import java.security.*; 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}; //獲取共同的密鑰 SecretKeySpec 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;i<re.length;i++){ result += Integer.toHexString((0x000000ff&re[i])|0xffffff00).substring(6); } System.out.println(result); } } |
使用以上兩種技術可以保證數據沒有經過改變,但接收者還無法確定數據是否確實是某個人發來的。盡管消息碼可以確定數據是某個有同樣密鑰的人發來的,但這要求雙方具有共享的密鑰,若有一組用戶共享,我們就無法確定數據的來源了。
數字簽名可以解決這一問題。數字簽名利用非對稱加密技術,發送者使用私鑰加密數據產生的消息摘要(簽名),接收者使用發送者的公鑰解密消息摘要以驗證簽名是否是某個人的。由于私鑰只有加密者才有,因此如果接收者用某個公鑰解密了某個消息摘要,就可以確定這段消息摘要必然是對應的私鑰持有者發來的。
使用數字簽名的前提是接收數據者能夠確信驗證簽名時(用發送者的私鑰加密消息摘要)所用的公鑰確實是某個人的 (因為有可能有人假告公鑰)。數字證書可以解決這個問題。
數字證書含有兩部分數據:一部分是對應主體(單位或個人)的信息,另一部分是這個主體所對應的公鑰。即數字證書保存了主體和它的公鑰的一一對應關系。同樣,數字證書也有可能被假造,如何判定數字證書的內容的真實性呢?所以,有效的數字證書必須經過權威 CA的簽名,即權威CA驗證數字證書的內容的真實性,然后再在數字證書上使用自己的私鑰簽名(相當于在證書加章確認)。
這樣,當用戶收到這樣的數字證書后,會用相應的權威 CA的公鑰驗證該證書的簽名(因為權威的CA的公鑰在操作系統中己經安裝)。根據非對稱加密的原理,如果該證書不是權威CA簽名的,將不能通過驗證,即該證書是不可靠的。
若通過驗證,即可證明此證書含的信息(發信人的公鑰和信息)是無誤的。于是可以信任該證書,便可以通過該證書內含的公鑰來確認數據確實是發送者發來的。
于是,雙方通信時, A把數據的消息摘要用自己的私鑰加密(即簽名),然后把自己的數字證書和數據及簽名后的消息摘要一起發送給B,B處查看A的數字證書,如果A的數字證書是經過權威CA驗證可靠的,便信任A,便可使用A的數字證書中附帶的A的公鑰解密消息摘要(這一過程同時確認了發送數據的人又可以解密消息摘要),然后通過解密后的消息摘要驗證數據是否正確無誤沒被修改。
利用這一原理,我們可以突破 java的applet小程序在瀏覽器中的權限,由于默認的applet權限控制不允許它訪問操作系統級的一切。于是我們可以用我們數字證書來給applet簽名,然后客戶端收到該applet時,系統會自動查看給該applet簽名的數字證書并提供給終端用戶判定是否信認該數字證書,如果用戶信認,則該applet便有了訪問系統的權限。