Java的安全學習(包括加密,數字簽名,證書和認證)

(1)消息摘要: java

 

消息摘要(Message Digest)又稱爲數字摘要(Digital Digest)。它是一個惟一對應一個消息或文本的固定長度的值,它由一個單向Hash加密函數對消息進行做用而產生。若是消息在途中改變了,則接收者經過對收到消息的新產生的摘要與原摘要比較,就可知道消息是否被改變了。所以消息摘要保證了消息的完整性。       消息摘要採用單向Hash 函數將需加密的明文"摘要"成一串128bit的密文,這一串密文亦稱爲數字指紋(Finger Print),它有固定的長度,且不一樣的明文摘要成密文,其結果老是不一樣的,而一樣的明文其摘要一定一致。這樣這串摘要即可成爲驗證實文是不是"真身"的"指紋"了。 git

    這是一種與消息認證碼結合使用以確保消息完整性的技術。主要使用單向散列函數算法,可用於檢驗消息的完整性,和經過散列密碼直接以文本形式保存等,目前普遍使用的算法有MD四、MD五、SHA-1,在java中進行消息摘要很簡單:下面舉一個簡單的例子 算法

/**
*MessageDigestTest.java
*/
import java.security.MessageDigest;
/**
*單一的消息摘要算法,不使用密碼.能夠用來對明文消息(如:密碼)隱藏保存
*/
public class MessageDigestTest{
 public static void main(String[] args) throws Exception{ 編程


  String str="123";
  byte[] plainText=str.getBytes("UTF8");

  //使用getInstance("算法")來得到消息摘要,這裏使用SHA-1的160位算法
  MessageDigest messageDigest=MessageDigest.getInstance("SHA-1");

  System.out.println("/n"+messageDigest.getProvider().getInfo());
  //開始使用算法
  messageDigest.update(plainText);
  System.out.println("/nDigest:");
  //輸出算法運算結果
  System.out.println(new String(messageDigest.digest(),"UTF8"));
 }
} 

(還能夠經過消息認證碼來進行加密實現,javax.crypto.Mac提供了一個解決方案,有興趣者能夠參考相關API文檔,本文只是簡單介紹什麼是摘要算法。) windows

(2)私公鑰和私鑰: 瀏覽器

 

公鑰和私鑰就是俗稱的不對稱加密方式,是從之前的對稱加密(使用用戶名與密碼)方式的提升。用電子郵件的方式說明一下原理。 安全

  使用公鑰與私鑰的目的就是實現安全的電子郵件,必須實現以下目的: 服務器

  1.我發送給你的內容必須加密,在郵件的傳輸過程當中不能被別人看到。 網絡

  2.必須保證是我發送的郵件,不是別人冒充個人。 app

  要達到這樣的目標必須發送郵件的兩人都有公鑰和私鑰。

  公鑰,就是給你們用的,你能夠經過電子郵件發佈,能夠經過網站讓別人下載,公鑰實際上是用來加密/驗章用的。私鑰,就是本身的,必須很是當心保存,最好加上密碼,私鑰是用來解密/簽章,首先就Key的全部權來講,私鑰只有我的擁有。公鑰與私鑰的做用是:用公鑰加密的內容只能用私鑰解密,用私鑰加密的內容只能用公鑰解密。

  好比說,我要給你發送一個加密的郵件。首先,我必須擁有你的公鑰,你也必須擁有個人公鑰。

  首先,我用你的公鑰給這個郵件加密,這樣就保證這個郵件不被別人看到,並且保證這個郵件在傳送過程當中沒有被修改。你收到郵件後,用你的私鑰就能夠解密,就能看到內容。

  其次我用個人私鑰給這個郵件加密,發送到你手裏後,你能夠用個人公鑰解密。由於私鑰只有我手裏有,這樣就保證了這個郵件是我發送的。

  當A->B資料時,A會使用B的公鑰加密,這樣才能確保只有B能解開,不然普羅大衆都能解開加密的訊息,就是去了資料的保密性。驗證方面則是使用籤驗章的機制,A傳資料給你們時,會以本身的私鑰作簽章,如此全部收到訊息的人均可以用A的公鑰進行驗章,即可確認訊息是由A發出來的了。

 

I.私匙加密解密實例:

/**
*PrivateTest.java
*/
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import java.security.Key;

/**
*私鈅加密,保證消息機密性
*/
public class PrivateTest{
 public static void main(String[] args) throws Exception{

       String str="123";
   byte[] plainText=str.getBytes("UTF8");
    
  //經過KeyGenerator造成一個key
  System.out.println("/nStart generate AES key");
  KeyGenerator keyGen=KeyGenerator.getInstance("AES");
  keyGen.init(128);
  Key key=keyGen.generateKey();
  System.out.println("Finish generating DES key");

  //得到一個私鈅加密類Cipher,ECB是加密方式,PKCS5Padding是填充方法
  Cipher cipher=Cipher.getInstance("AES/ECB/PKCS5Padding");
  System.out.println("/n"+cipher.getProvider().getInfo());

  //使用私鈅加密
  System.out.println("/nStart encryption:");
  cipher.init(Cipher.ENCRYPT_MODE,key);
  byte[] cipherText=cipher.doFinal(plainText);
  System.out.println("Finish encryption:");
  System.out.println(new String(cipherText,"UTF8"));

 

     //使用私鈅解密

  System.out.println("/nStart decryption:");
  cipher.init(Cipher.DECRYPT_MODE,key);
  byte[] newPlainText=cipher.doFinal(cipherText);
  System.out.println("Finish decryption:");

  System.out.println(new String(newPlainText,"UTF8"));

 }
} 

II.公匙加密,私匙解密實例:

 

/**
*PublicTest.java
*/
import java.security.Key;
import javax.crypto.Cipher;
import java.security.KeyPairGenerator;
import java.security.KeyPair;
/**
*一個簡單的公鈅加密例子,Cipher類使用KeyPairGenerator生成的公鈅和私鈅
*/
public class PublicTest{
 public static void main(String[] args) throws Exception{
     String str="123";
   byte[] plainText=str.getBytes("UTF8");
  //構成一個RSA密鑰
  System.out.println("/nStart generating RSA key");
  KeyPairGenerator keyGen=KeyPairGenerator.getInstance("RSA");
  keyGen.initialize(1024);
  KeyPair key=keyGen.generateKeyPair();
  System.out.println("Finish generating RSA key");

  //得到一個RSA的Cipher類,使用公鈅加密
  Cipher cipher=Cipher.getInstance("RSA/ECB/PKCS1Padding");
  System.out.println("/n"+cipher.getProvider().getInfo());

  System.out.println("/nStart encryption");
  cipher.init(Cipher.ENCRYPT_MODE,key.getPublic());
  byte[] cipherText=cipher.doFinal(plainText);
  System.out.println("Finish encryption:");
  System.out.println(new String(cipherText,"UTF8"));

  //使用私鈅解密
  System.out.println("/nStart decryption");
  cipher.init(Cipher.DECRYPT_MODE,key.getPrivate());
  byte[] newPlainText=cipher.doFinal(cipherText);
  System.out.println("Finish decryption:");
  System.out.println(new String(newPlainText,"UTF8"));
 }
}

 

 (3)數字簽名:
I.電子商務中數據傳輸的幾個安全性需求

     1. 數據的保密性:用於防止非法用戶進入系統及合法用戶對系統資源的非法使用;經過對一些敏感的數據文件進行加密來保護系統之間的數據交換,防止除接收方以外的第三方截獲數據及即便獲取文件也沒法獲得其內容。如在電子交易中,避免遭到黑客的襲擊使信用卡信息丟失的問題。

  2. 數據的完整性:防止非法用戶對進行交換的數據進行無心或惡意的修改、插入,防止交換的數據丟失等。

  3. 數據的不能否認性:對數據和信息的來源進行驗證,以確保數據由合法的用戶發出;防止數據發送方在發出數據後又加以否定;同時防止接收方在收到數據後又否定曾收到過此數據及篡改數據。

  上述需求對應於防火牆、加密、數字簽名、身份認證等技術,但其關鍵在於數字簽名技術。

II. 數字簽名的含義

  數字簽名是經過一個單向函數對要傳送的報文進行處理獲得的用以認證報文來源並覈實報文是否發生變化的一個字母數字串。

III.數字簽名的實現方法

    實現數字簽名有不少方法,目前數字簽名採用較多的是公鑰加密技術,如基於RSA Date Security 公司的PKCS( Public Key Cryptography Standards )、Digital Signature Algorithm、x.50九、PGP(Pretty Good Privacy). 1994年美國標準與技術協會公佈了數字簽名標準(DSS)而使公鑰加密技術普遍應用。&127;公鑰加密系統採用的是非對稱加密算法 
IIII.實例

**
*DigitalSignatureTest.java
*/
import java.security.Signature;
import java.security.KeyPairGenerator;
import java.security.KeyPair;
import java.security.SignatureException;

/**
*數字簽名,使用RSA私鑰對對消息摘要簽名,而後使用公鈅驗證 測試
*/
public class DigitalSignatureTest{
 public static void main(String[] args) throws Exception{
     String str="123";
   byte[] plainText=str.getBytes("UTF8");
  //造成RSA公鑰對
  System.out.println("/nStart generating RSA key");
  KeyPairGenerator keyGen=KeyPairGenerator.getInstance("RSA");
  keyGen.initialize(1024);

  KeyPair key=keyGen.generateKeyPair();
  System.out.println("Finish generating RSA key");
  //使用私鈅簽名
  Signature sig=Signature.getInstance("SHA1WithRSA");
  sig.initSign(key.getPrivate());
  sig.update(plainText);
  byte[] signature=sig.sign();
  System.out.println(sig.getProvider().getInfo());
  System.out.println("/nSignature:");
  System.out.println(new String(signature,"UTF8"));

  //使用公鈅驗證
  System.out.println("/nStart signature verification");
  sig.initVerify(key.getPublic());
  sig.update(plainText);
  try{
   if(sig.verify(signature)){
    System.out.println("Signature verified");
   }else System.out.println("Signature failed");
   }catch(SignatureException e){
    System.out.println("Signature failed");
   }
  }
} 
(4)數字證書

I.概念:是數字形式的標識,與護照或駕駛員執照十分類似。數字證書是數字憑據,它提供有關實體標識的信息以及其餘支持信息。數字證書是由成爲證書頒發機構(CA)的權威機構頒發的。因爲數字證書有證書權威機構頒發,所以由該權威機構擔保證書信息的有效性。此外,數字證書只在特定的時間段內有效。

  數字證書包含證書中所標識的實體的公鑰(就是說你的證書裏有你的公鑰),因爲證書將公鑰與特定的我的匹配,而且該證書的真實性由頒發機構保證(就是說可讓你們相信你的證書是真的),所以,數字證書爲如何找到用戶的公鑰並知道它是否有效這一問題提供瞭解決方案。

II.數字證書的原理

     數字證書採用公鑰體制,即利用一對互相匹配的密鑰進行加密、解密。每一個用戶本身設定一把特定的僅爲本人所知的私有密鑰(私鑰),用它進行解密和簽名;同時設定一把公共密鑰(公鑰)並由本人公開,爲一組用戶所共享,用於加密和驗證簽名。當發送一份保密文件時,發送方使用接收方的公鑰對數據加密,而接收方則使用本身的私鑰解密,這樣信息就能夠安全無誤地到達目的地了。經過數字的手段保證加密過程是一個不可逆過程,即只有用私有密鑰才能解密.在公開密鑰密碼體制中,經常使用的一種是RSA體制。

  用戶也能夠採用本身的私鑰對信息加以處理,因爲密鑰僅爲本人全部,這樣就產生了別人沒法生成的文件,也就造成了數字簽名。採用數字簽名,可以確認如下兩點:

  (1)保證信息是由簽名者本身簽名發送的,簽名者不可否認或難以否定;

  (2)保證信息自簽發後到收到爲止不曾做過任何修改,簽發的文件是真實文件。
III.java實例操做:

 

     密鑰庫:java平臺爲你提供了密鑰庫,用做密鑰和證書的資源庫。從物理上講,密鑰庫是缺省名稱爲 .keystore 的文件(有一個選項使它成爲加密文件)。密鑰和證書能夠擁有名稱(稱爲別名),每一個別名都由惟一的密碼保護。密鑰庫自己也受密碼保護;您能夠選擇讓每一個別名密碼與主密鑰庫密碼匹配。 

  使用工具keytool,進行自我認證:

  一、建立密鑰庫keytool -genkey -v -alias YourKeyName -keyalg RSA 默認在本身的home目錄下(windows系統是c:/documents and settings/<你的用戶名> 目錄下的.keystore文件),建立咱們用 RSA 算法生成別名爲 feiUserKey 的自簽名的證書,若是使用了-keystore mm 就在當前目錄下建立一個密鑰庫mm文件來保存密鑰和證書。

  二、查看證書:keytool -list 列舉了密鑰庫的全部的證書 

  也能夠在dos下輸入keytool -help查看幫助。


(5)JAR的簽名

    前面咱們已將講了怎樣建立本身的證書了,如今能夠開始瞭解怎樣對JAR文件簽名,JAR文件在Java中至關於 ZIP 文件,容許將多個 Java 類文件打包到一個具備 .jar 擴展名的文件中,而後能夠對這個jar文件進行數字簽名,以證明其來源和真實性。該 JAR 文件的接收方能夠根據發送方的簽名決定是否信任該代碼,並能夠確信該內容在接收以前沒有被篡改過。同時在部署中,能夠經過在策略文件中放置訪問控制語句根據簽名者的身份分配對機器資源的訪問權。這樣,有些Applet的安全檢驗訪問就得以進行。

  使用jarsigner工具能夠對jar文件進行簽名:

  如今假設咱們有個Test.jar文件(可使用jar命令行工具生成):

  jarsigner Test.jar YourKeyName (這裏咱們上面建立了該別名的證書) ,詳細信息能夠輸入jarsigner查看幫助

  驗證其真實性:jarsigner -verify Test.jar(注意,驗證的是jar是否被修改了,但不檢驗減小的,若是增長了新的內容,也提示,但減小的不會提示。)

  使用Applet中::<applet code="Test.class" archive="Test.jar" width="150" height="100"></applet>而後瀏覽器就會提示你:准許這個會話-拒絕-始終准許-查看證書等。

(6)安全套接字層(SSL Secure Sockets Layer)和傳輸層安全性(TLS Transport Layer Security)  

I.簡介:      

 安全套接字層 (SSL):一種由 Netscape Communications 開發的提議開放式標準,用以創建安全通信通道,以防止如信用卡號等這樣的重要信息被截獲。

安全套接字層是用於服務器之上的一個加密系統,它能夠確保在客戶機與服務器之間傳輸的數據仍然是安全與隱密的。要使服務器和客戶機使用 SSL 進行安全的通訊,服務器必須有兩樣東西:

  密鑰對(Key pair) —— 一個密鑰對包括一個公鑰和一個私鑰。這兩個密鑰用來對消息進行加密和解密,以確保在因特網上傳輸時的隱密性和機密性。

  證書(Certificate) —— 證書用來進行身份驗證或者身份確認。證書能夠是自籤(self-signed)證書,也能夠是頒發(issued)證書。自簽證書是爲本身私有的 Web 網絡建立的證書。頒發證書是認證中心(certificate authority,CA)或者證書籤署者提供(頒發)給您的證書。

  SSL 使用安全握手來初始化客戶機與服務器之間的安全鏈接。在握手期間,客戶機和服務器對它們將要爲此會話使用的密鑰及加密方法達成一致。客戶機使用服務器證書驗證服務器。握手以後,SSL 被用來加密和解密 HTTPS(組合 SSL 和 HTTP 的一個獨特協議)請求和服務器響應中的全部信息,包括:

  客戶機正在請求的 URL。

  提交的表單的內容。

  訪問受權信息(好比用戶名和密碼)。

  全部在客戶機與服務器之間發送的數據。

 

 II.總結:

安全套接字層和傳輸層安全性是用於在客戶機和服務器之間構建安全的通訊通道的協議。它也用來爲客戶機認證服務器,以及(不太經常使用的)爲服務器認證客戶機。該協議在瀏覽器應用程序中比較常見,瀏覽器窗口底部的鎖代表 SSL/TLS 有效:   1)當使用 SSL/TLS(一般使用 https:// URL)向站點進行請求時,從服務器向客戶機發送一個證書。客戶機使用已安裝的公共 CA 證書經過這個證書驗證服務器的身份,而後檢查 IP 名稱(機器名)與客戶機鏈接的機器是否匹配。   2)客戶機生成一些能夠用來生成對話的私鑰(稱爲會話密鑰)的隨機信息,而後用服務器的公鑰對它加密並將它發送到服務器。服務器用本身的私鑰解密消息,而後用該隨機信息派生出和客戶機同樣的私有會話密鑰。一般在這個階段使用 RSA 公鑰算法。   3)客戶機和服務器使用私有會話密鑰和私鑰算法(一般是 RC4)進行通訊。使用另外一個密鑰的消息認證碼來確保消息的完整性。   java中javax.net.ssl.SSLServerSocketFactory類提供了一個很好的SSLServerSocker的工廠類,熟悉Socket編程的讀者能夠去練習。當編寫完服務器端以後,在瀏覽器上輸入https://主機名:端口 就會經過SSL/TLS進行通話了。注意:運行服務端的時候要帶系統環境變量運行:javax.net.ssl.keyStore=密鑰庫(建立證書時,名字應該爲主機名,好比localhost)和javax.net.ssl.keyStorePassword=你的密碼

相關文章
相關標籤/搜索