程式扎記: [ Java 文章收集 ] Java密碼學

標籤

2012年3月23日 星期五

[ Java 文章收集 ] Java密碼學


轉載自 這裡
密碼學簡介 – 加密與解密 :
加密是一個將欲加密的資料用一些數學運算轉成一團令人看不懂的東西的過程; 解密則是將加密文轉換回原始 文字的過程。這個過程中,扮演原始文字與加密文字之間轉換的數學演算法稱為Cipher :


現代的Cipher多半會用Key來加密與解密資料。所謂Key是指一個機密值,我們可將它視為一通行密碼。加密文 字必需使用對映的Key才能解密為原始文字.
- 對稱型Cipher
對稱型Cipher在傳送端與接收端所用的Key是一樣的,如圖2所示,對稱型Cipher又叫Private Key Cipher,因為Key 的值只有傳送端和接收端知道。如果有第三者知道了Private Key值,也就能解開加密的資料 :


- 非對稱型Cipher
非對稱型的Cipher又叫Public Key Cipher,Cipher除了Private Key外,還會引進一可以隨意散發的Public Key。被 Public Key加密的資料只有相對映的Private Key可以解開,同樣的被Private Key加密的資料也只有相對映的Public Key 可以解開。如圖3所示,顯示了非對稱型Cipher的運作過程 :


- 訊息摘要 (Message Digest)
訊息摘要是從一組輸入資料計算所得的一個特別數字,其原理運作就如hash function一般。在密碼學的運用裡, 一般是用來驗證資料是否被竄改.

JCE下載 :
因為美國法規的限制,Sun在JDK裡只提供了少數的加密方法,其餘大部份則只在SunJCE裡提供,而且SunJCE的 API限制只有美國、加拿大地區可以下載。表1為Sun及SunJCE分別支援的加密演算法 :


雖然美國法規有這樣的限定,但是在美國境外也已經有廠商實作出JCE,並且可以在網路上直接下載,表2就是 下載網址的列表 :


JCE安裝 :
1. 解壓縮到JDK目錄下
2. Set ClassPath= C:\JDK\bin\cryptix-jce-api.jar;C:\JDK\bin\cryptix-jce-compat.jar;C:\JDK\bin\cryptix-jce-provider.jar …
3. 在JDK/lib/security/java.security中加入
security.provider.1=sun.security.provider.Sun (原來就有的)
security.provider.2=cryptix.jce.provider.Cryptix (加入)

程式範例 :
在舉例之前,我先完成一個公用類別,用來將字串轉成十六進位表示法 :
  1. public class Msg {  
  2.  public static String toHexString(byte[] b) {  
  3.   StringBuffer hexString = new StringBuffer();  
  4.   String plainText;  
  5.   
  6.   for (int i = 0; i < b.length; i++) {  
  7.    plainText = Integer.toHexString(0xFF & b[i]);  
  8.    if (plainText.length() < 2) {  
  9.     plainText = "0" + plainText;  
  10.    }  
  11.    hexString.append(plainText);  
  12.   }  
  13.   return hexString.toString();  
  14.  }  
  15. }  
- 訊息摘要 (message digest, 以SHA1為例) 
產生訊息摘要的步驟:
* 呼叫getInstance取得MessageDigest實體
* 呼叫update將資料餵給MessageDigest
* 呼叫digest產生訊息摘要

  1. import java.security.*;  
  2.   
  3. public class SHA extends Object {  
  4.  public static void main(String[] args) throws Exception  
  5.  {  
  6.   MessageDigest md = MessageDigest.getInstance("SHA");  
  7.   md.update(args[0].getBytes());  
  8.   byte[] digest = md.digest();  
  9.   System.out.println(Msg.toHexString(digest));  
  10.  }  
  11. }  
比較兩個訊息摘要是否相同時,可呼叫isEqual.

- 訊息認證碼 (MAC, 以HmacSHA1為例)
訊息認證碼只是在產生訊息摘要的過程裡,加進一把key做為保護,目的是使訊息摘要更難被破解. 產生訊息認證碼的步驟 :
* 利用密碼產生一把key
* 呼叫getInstance取得Mac實體
* 呼叫init,初始化Mac
* 呼叫update餵資料給Mac
* 呼叫doFinal產生訊息認證碼

  1. import java.security.*;  
  2. import javax.crypto.*;  
  3. import javax.crypto.spec.*;  
  4.   
  5. public class MacSHA {  
  6.  public static void main(String[] args)  
  7.  {  
  8.   SecureRandom sr = new SecureRandom();  
  9.   byte[] keyBytes = new byte[20];  
  10.   sr.nextBytes(keyBytes);  
  11.   SecretKey key = new SecretKeySpec(keyBytes, "HmacSHA");  
  12.   
  13.   try {  
  14.    Mac m = Mac.getInstance("HmacSHA");  
  15.    m.init(key);  
  16.    m.update(args[0].getBytes());  
  17.    byte[] mac = m.doFinal();  
  18.    System.out.println(Msg.toHexString(mac));  
  19.   }  
  20.   catch (Exception e) {  
  21.    System.out.println("Exception!!");  
  22.   }  
  23.  }  
  24. }  
- 加密與解密 (以DES為例)
這裡舉的加密/解密是屬對稱型Cipher; 在金融交易裡,常用對稱型Cipher來加/解密資料. 加密/解密的步驟 :
* 利用密碼產生一把key
* 呼叫getInstance產生一個Cipher物件
* 呼叫init設定為加密或解密
* 加密/解密

  1. import java.io.*;  
  2. import java.security.*;  
  3. import javax.crypto.*;  
  4.   
  5. public class PwdDES {  
  6.  public static final int kBufferSize = 8192;  
  7.   
  8.  public static void main(String[] args) throws Exception {  
  9.   if (args.length < 4) {  
  10.    System.out.println("Usage: java PwdDES -e|-d passwd inputfile outputfile");  
  11.    return;  
  12.   }  
  13.   
  14.   //Get or create key.  
  15.   
  16.   Key key;  
  17.   
  18.   KeyGenerator generator = KeyGenerator.getInstance("DES");  
  19.   generator.init(new SecureRandom(args[1].getBytes()));  
  20.   key = generator.generateKey();  
  21.   
  22.   //Get a cipher object  
  23.   Cipher cipher = Cipher.getInstance("DES/ECB/PKCS#5");  
  24.   
  25.   //Encrypt or decrypt  
  26.   if (args[0].indexOf("e") != -1)  
  27.    cipher.init(Cipher.ENCRYPT_MODE, key);  
  28.   else  
  29.    cipher.init(Cipher.DECRYPT_MODE, key);  
  30.   
  31.   FileInputStream in = new FileInputStream(args[2]);  
  32.   FileOutputStream fileOut = new FileOutputStream(args[3]);  
  33.   CipherOutputStream out = new CipherOutputStream(fileOut, cipher);  
  34.   byte[] buffer = new byte[kBufferSize];  
  35.   int length;  
  36.   while ((length = in.read(buffer)) != -1)  
  37.    out.write(buffer, 0, length);  
  38.   in.close();  
  39.   out.close();  
  40.  }  
  41.   
  42. }  
- 產生簽章與認證 (以DSA為例)
數位簽章常用在網路上做個人身份確認. 產生簽章的步驟 :
* 呼叫getInstance取得一個Signature實體
* 呼叫initSign初始化Signature
* 呼叫sign產生簽章

認證的步驟 :
* 呼叫getInstance取得一個Signature實體
* 呼叫initVerify初始化Signature
* 呼叫verify認證

Sample1: 產生Private/Public Key
  1. import java.security.*;  
  2. import java.security.KeyPairGenerator;  
  3. import java.security.KeyPair;  
  4. import java.io.*;  
  5.   
  6. public class KeyPair1 {  
  7.   
  8.  public static void main(String[] args)  
  9.  {  
  10.   try {  
  11.    KeyPairGenerator genKeyPair = KeyPairGenerator.getInstance("DSA");  
  12.    genKeyPair.initialize(1024new SecureRandom());   
  13.    KeyPair kpKey = genKeyPair.genKeyPair();  
  14.    PrivateKey prKey = kpKey.getPrivate();  
  15.    PublicKey puKey = kpKey.getPublic();  
  16.   
  17.    ObjectOutputStream osPrivate = new ObjectOutputStream(new FileOutputStream("D:\\Private.Key"));  
  18.    ObjectOutputStream osPublic = new ObjectOutputStream(new FileOutputStream("D:\\Public.Key"));  
  19.    osPrivate.writeObject(prKey);  
  20.    osPublic.writeObject(puKey);  
  21.   
  22.    osPrivate.close();  
  23.    osPublic.close();  
  24.   }  
  25.   catch (Exception e) {  
  26.    System.out.println("Error");  
  27.   }  
  28.  }  
  29. }  
Sample2: 產生簽章與認證
  1. import java.io.*;  
  2. import java.security.*;  
  3. import java.security.Signature;  
  4. import java.security.cert.*;  
  5.   
  6. public class GenSign {  
  7.   
  8.  public static void main(String[] args) throws Exception {  
  9.   String options = args[0];  
  10.   String messagefile = args[1];  
  11.   String signaturefile = args[2];  
  12.   
  13.   Signature signature = Signature.getInstance("DSA");  
  14.   if (options.indexOf("s") != -1) {  
  15.    ObjectInputStream is = new ObjectInputStream(new FileInputStream("D:\\Private.key"));  
  16.    PrivateKey priKey = (PrivateKey) is.readObject();  
  17.    signature.initSign(priKey);  
  18.    is.close();  
  19.   }  
  20.   else {  
  21.    ObjectInputStream is = new ObjectInputStream(new FileInputStream("D:\\Public.key"));  
  22.    PublicKey pubKey = (PublicKey) is.readObject();  
  23.    signature.initVerify(pubKey);  
  24.    is.close();  
  25.   }  
  26.   
  27.   FileInputStream in = new FileInputStream(messagefile);  
  28.   byte[] buffer = new byte[8192];  
  29.   int length;  
  30.   while ((length = in.read(buffer))!= -1)  
  31.    signature.update(buffer, 0, length);  
  32.   in.close();  
  33.   
  34.   if (options.indexOf("s") != -1) {  
  35.    FileOutputStream out = new FileOutputStream(signaturefile);  
  36.    byte[] raw = signature.sign();  
  37.    out.write(raw);  
  38.    out.close();  
  39.   }  
  40.   else {  
  41.    FileInputStream sigIn = new FileInputStream(signaturefile);  
  42.    byte[] raw = new byte[sigIn.available()];  
  43.    sigIn.read(raw);  
  44.    sigIn.close();  
  45.    if (signature.verify(raw))  
  46.     System.out.println("The signature is good.");  
  47.    else  
  48.     System.out.println("The signature is bad.");  
  49.   }  
  50.  }  
  51. }  
This message was edited 4 times. Last update was at 01/04/2011 23:47:49

沒有留言:

張貼留言

網誌存檔

關於我自己

我的相片
Where there is a will, there is a way!