Java加密算法

轉自:http://www.open-open.com/lib/view/open1397274257325.html

總結:

 如基本的單向加密算法:  

  • BASE64 嚴格地說,屬於編碼格式,而非加密算法

  • MD5(Message Digest algorithm 5,信息摘要算法)

  • SHA(Secure Hash Algorithm,安全散列算法)

  • HMAC(Hash Message Authentication Code,散列消息鑑別碼)


    複雜的對稱加密(DES、PBE)、非對稱加密算法: 

  • DES(Data Encryption Standard,數據加密算法)

  • PBE(Password-based encryption,基於密碼驗證)

  • RSA(算法的名字以發明者的名字命名:Ron Rivest, AdiShamir 和Leonard Adleman)

  • DH(Diffie-Hellman算法,**一致協議)

  • DSA(Digital Signature Algorithm,數字簽名)

  • ECC(Elliptic Curves Cryptography,橢圓曲線密碼編碼學)


原文:

 如基本的單向加密算法:  

  • BASE64 嚴格地說,屬於編碼格式,而非加密算法

  • MD5(Message Digest algorithm 5,信息摘要算法)

  • SHA(Secure Hash Algorithm,安全散列算法)

  • HMAC(Hash Message Authentication Code,散列消息鑑別碼)


    複雜的對稱加密(DES、PBE)、非對稱加密算法: 

  • DES(Data Encryption Standard,數據加密算法)

  • PBE(Password-based encryption,基於密碼驗證)

  • RSA(算法的名字以發明者的名字命名:Ron Rivest, AdiShamir 和Leonard Adleman)

  • DH(Diffie-Hellman算法,**一致協議)

  • DSA(Digital Signature Algorithm,數字簽名)

  • ECC(Elliptic Curves Cryptography,橢圓曲線密碼編碼學)



    本篇內容簡要介紹BASE64、MD5、SHA、HMAC幾種方法。 
    MD5、SHA、HMAC這三種加密算法,可謂是非可逆加密,就是不可解密的加密方法。我們通常只把他們作爲加密的基礎。單純的以上三種的加密並不可靠。 

BASE64 
按 照RFC2045的定義,Base64被定義爲:Base64內容傳送編碼被設計用來把任意序列的8位字節描述爲一種不易被人直接識別的形式。(The Base64 Content-Transfer-Encoding is designed to represent arbitrary sequences of octets in a form that need not be humanly readable.) 
常見於郵件、http加密,截取http信息,你就會發現登錄操作的用戶名、密碼字段通過BASE64加密的。 

各種Java加密算法 

通過java代碼實現如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
      * BASE64解密
     
      * @param key
      * @return
      * @throws Exception
      */
     public  static  byte [] decryptBASE64(String key)  throws  Exception {
         return  ( new  BASE64Decoder()).decodeBuffer(key);
     }
 
     /**
      * BASE64加密
     
      * @param key
      * @return
      * @throws Exception
      */
     public  static  String encryptBASE64( byte [] key)  throws  Exception {
         return  ( new  BASE64Encoder()).encodeBuffer(key);
     }


主要就是BASE64Encoder、BASE64Decoder兩個類,我們只需要知道使用對應的方法即可。另,BASE加密後產生的字節位數是8的倍數,如果不夠位數以=符號填充。 

MD5 
MD5 -- message-digest algorithm 5 (信息-摘要算法)縮寫,廣泛用於加密和解密技術,常用於文件校驗。校驗?不管文件多大,經過MD5後都能生成唯一的MD5值。好比現在的ISO校驗,都 是MD5校驗。怎麼用?當然是把ISO經過MD5後產生MD5的值。一般下載linux-ISO的朋友都見過下載鏈接旁邊放着MD5的串。就是用來驗證文 件是否一致的。 

各種Java加密算法 

通過java代碼實現如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
      * MD5加密
     
      * @param data
      * @return
      * @throws Exception
      */
     public  static  byte [] encryptMD5( byte [] data)  throws  Exception {
 
         MessageDigest md5 = MessageDigest.getInstance(KEY_MD5);
         md5.update(data);
 
         return  md5.digest();
 
     }



通常我們不直接使用上述MD5加密。通常將MD5產生的字節數組交給BASE64再加密一把,得到相應的字符串。 

SHA 
SHA(Secure Hash Algorithm,安全散列算法),數字簽名等密碼學應用中重要的工具,被廣泛地應用於電子商務等信息安全領域。雖然,SHA與MD5通過碰撞法都被**了, 但是SHA仍然是公認的安全加密算法,較之MD5更爲安全。 

各種Java加密算法 

通過java代碼實現如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
      * SHA加密
     
      * @param data
      * @return
      * @throws Exception
      */
     public  static  byte [] encryptSHA( byte [] data)  throws  Exception {
 
         MessageDigest sha = MessageDigest.getInstance(KEY_SHA);
         sha.update(data);
 
         return  sha.digest();
 
     }
}



HMAC 
HMAC(Hash Message Authentication Code,散列消息鑑別碼,基於**的Hash算法的認證協議。消息鑑別碼實現鑑別的原理是,用公開函數和**產生一個固定長度的值作爲認證標識,用這個 標識鑑別消息的完整性。使用一個**生成一個固定大小的小數據塊,即MAC,並將其加入到消息中,然後傳輸。接收方利用與發送方共享的**進行鑑別認證 等。 

各種Java加密算法 

通過java代碼實現如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/**
      * 初始化HMAC**
     
      * @return
      * @throws Exception
      */
     public  static  String initMacKey()  throws  Exception {
         KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_MAC);
 
         SecretKey secretKey = keyGenerator.generateKey();
         return  encryptBASE64(secretKey.getEncoded());
     }
 
     /**
      * HMAC加密
     
      * @param data
      * @param key
      * @return
      * @throws Exception
      */
     public  static  byte [] encryptHMAC( byte [] data, String key)  throws  Exception {
 
         SecretKey secretKey =  new  SecretKeySpec(decryptBASE64(key), KEY_MAC);
         Mac mac = Mac.getInstance(secretKey.getAlgorithm());
         mac.init(secretKey);
 
         return  mac.doFinal(data);
 
     }



給出一個完整類,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import  java.security.MessageDigest;
 
import  javax.crypto.KeyGenerator;
import  javax.crypto.Mac;
import  javax.crypto.SecretKey;
 
import  sun.misc.BASE64Decoder;
import  sun.misc.BASE64Encoder;
 
/**
  * 基礎加密組件
 
  * @author 樑棟
  * @version 1.0
  * @since 1.0
  */
public  abstract  class  Coder {
     public  static  final  String KEY_SHA =  "SHA" ;
     public  static  final  String KEY_MD5 =  "MD5" ;
 
     /**
      * MAC算法可選以下多種算法
     
      * <pre>
      * HmacMD5 
      * HmacSHA1 
      * HmacSHA256 
      * HmacSHA384 
      * HmacSHA512
      * </pre>
      */
     public  static  final  String KEY_MAC =  "HmacMD5" ;
 
     /**
      * BASE64解密
     
      * @param key
      * @return
      * @throws Exception
      */
     public  static  byte [] decryptBASE64(String key)  throws  Exception {
         return  ( new  BASE64Decoder()).decodeBuffer(key);
     }
 
     /**
      * BASE64加密
     
      * @param key
      * @return
      * @throws Exception
      */
     public  static  String encryptBASE64( byte [] key)  throws  Exception {
         return  ( new  BASE64Encoder()).encodeBuffer(key);
     }
 
     /**
      * MD5加密
     
      * @param data
      * @return
      * @throws Exception
      */
     public  static  byte [] encryptMD5( byte [] data)  throws  Exception {
 
         MessageDigest md5 = MessageDigest.getInstance(KEY_MD5);
         md5.update(data);
 
         return  md5.digest();
 
     }
 
     /**
      * SHA加密
     
      * @param data
      * @return
      * @throws Exception
      */
     public  static  byte [] encryptSHA( byte [] data)  throws  Exception {
 
         MessageDigest sha = MessageDigest.getInstance(KEY_SHA);
         sha.update(data);
 
         return  sha.digest();
 
     }
 
     /**
      * 初始化HMAC**
     
      * @return
      * @throws Exception
      */
     public  static  String initMacKey()  throws  Exception {
         KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_MAC);
 
         SecretKey secretKey = keyGenerator.generateKey();
         return  encryptBASE64(secretKey.getEncoded());
     }
 
     /**
      * HMAC加密
     
      * @param data
      * @param key
      * @return
      * @throws Exception
      */
     public  static  byte [] encryptHMAC( byte [] data, String key)  throws  Exception {
 
         SecretKey secretKey =  new  SecretKeySpec(decryptBASE64(key), KEY_MAC);
         Mac mac = Mac.getInstance(secretKey.getAlgorithm());
         mac.init(secretKey);
 
         return  mac.doFinal(data);
 
     }
}



再給出一個測試類:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import  static  org.junit.Assert.*;
 
import  org.junit.Test;
 
/**
 
  * @author 樑棟
  * @version 1.0
  * @since 1.0
  */
public  class  CoderTest {
 
     @Test
     public  void  test()  throws  Exception {
         String inputStr =  "簡單加密" ;
         System.err.println( "原文:\n"  + inputStr);
 
         byte [] inputData = inputStr.getBytes();
         String code = Coder.encryptBASE64(inputData);
 
         System.err.println( "BASE64加密後:\n"  + code);
 
         byte [] output = Coder.decryptBASE64(code);
 
         String outputStr =  new  String(output);
 
         System.err.println( "BASE64解密後:\n"  + outputStr);
 
         // 驗證BASE64加密解密一致性
         assertEquals(inputStr, outputStr);
 
         // 驗證MD5對於同一內容加密是否一致
         assertArrayEquals(Coder.encryptMD5(inputData), Coder
                 .encryptMD5(inputData));
 
         // 驗證SHA對於同一內容加密是否一致
         assertArrayEquals(Coder.encryptSHA(inputData), Coder
                 .encryptSHA(inputData));
 
         String key = Coder.initMacKey();
         System.err.println( "Mac**:\n"  + key);
 
         // 驗證HMAC對於同一內容,同一**加密是否一致
         assertArrayEquals(Coder.encryptHMAC(inputData, key), Coder.encryptHMAC(
                 inputData, key));
 
         BigInteger md5 =  new  BigInteger(Coder.encryptMD5(inputData));
         System.err.println( "MD5:\n"  + md5.toString( 16 ));
 
         BigInteger sha =  new  BigInteger(Coder.encryptSHA(inputData));
         System.err.println( "SHA:\n"  + sha.toString( 32 ));
 
         BigInteger mac =  new  BigInteger(Coder.encryptHMAC(inputData, inputStr));
         System.err.println( "HMAC:\n"  + mac.toString( 16 ));
     }
}



控制檯輸出:

原文:
簡單加密
BASE64加密後:
566A5Y2V5Yqg5a+G

BASE64解密後:
簡單加密
Mac**:
uGxdHC+6ylRDaik++leFtGwiMbuYUJ6mqHWyhSgF4trVkVBBSQvY/a22xU8XT1RUemdCWW155Bke
pBIpkd7QHg==

MD5:
-550b4d90349ad4629462113e7934de56
SHA:
91k9vo7p400cjkgfhjh0ia9qthsjagfn
HMAC:
2287d192387e95694bdbba2fa941009a



注意 
編譯時,可能會看到如下提示: 

引用


警告:sun.misc.BASE64Decoder 是 Sun 的專用 API,可能會在未來版本中刪除 

import sun.misc.BASE64Decoder; 
               ^ 
警告:sun.misc.BASE64Encoder 是 Sun 的專用 API,可能會在未來版本中刪除 

import sun.misc.BASE64Encoder; 
               ^ 



BASE64Encoder 和BASE64Decoder是非官方JDK實現類。雖然可以在JDK裏能找到並使用,但是在API裏查不到。JRE 中 sun 和 com.sun 開頭包的類都是未被文檔化的,他們屬於 java, javax 類庫的基礎,其中的實現大多數與底層平臺有關,一般來說是不推薦使用的。 


    BASE64的加密解密是雙向的,可以求反解。 
    MD5、SHA以及HMAC是單向加密,任何數據加密後只會產生唯一的一個加密串,通常用來校驗數據在傳輸過程中是否被修改。其中HMAC算法有一個**,增強了數據傳輸過程中的安全性,強化了算法外的不可控因素。 
    單向加密的用途主要是爲了校驗數據在傳輸過程中是否被修改。

    接下來我們介紹對稱加密算法,最常用的莫過於DES數據加密算法。 
DES 
DES-Data Encryption Standard,即數據加密算法。是IBM公司於1975年研究成功並公開發表的。DES算法的入口參數有三個:Key、Data、Mode。其中 Key爲8個字節共64位,是DES算法的工作**;Data也爲8個字節64位,是要被加密或被解密的數據;Mode爲DES的工作方式,有兩種:加密 或解密。 
        DES算法把64位的明文輸入塊變爲64位的密文輸出塊,它所使用的**也是64位。 


通過java代碼實現如下:Coder類見

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import  java.security.Key;
import  java.security.SecureRandom;
 
import  javax.crypto.Cipher;
import  javax.crypto.KeyGenerator;
import  javax.crypto.SecretKey;
import  javax.crypto.SecretKeyFactory;
import  javax.crypto.spec.DESKeySpec;
 
 
/**
  * DES安全編碼組件
 
  * <pre>
  * 支持 DES、DESede(TripleDES,就是3DES)、AES、Blowfish、RC2、RC4(ARCFOUR)
  * DES                  key size must be equal to 56
  * DESede(TripleDES)     key size must be equal to 112 or 168
  * AES                  key size must be equal to 128, 192 or 256,but 192 and 256 bits may not be available
  * Blowfish          key size must be multiple of 8, and can only range from 32 to 448 (inclusive)
  * RC2                  key size must be between 40 and 1024 bits
  * RC4(ARCFOUR)      key size must be between 40 and 1024 bits
  * 具體內容 需要關注 JDK Document http://.../docs/technotes/guides/security/SunProviders.html
  * </pre>
 
  * @author 樑棟
  * @version 1.0
  * @since 1.0
  */
public  abstract  class  DESCoder  extends  Coder {
     /**
      * ALGORITHM 算法 <br>
      * 可替換爲以下任意一種算法,同時key值的size相應改變。
     
      * <pre>
      * DES                  key size must be equal to 56
      * DESede(TripleDES)     key size must be equal to 112 or 168
      * AES                  key size must be equal to 128, 192 or 256,but 192 and 256 bits may not be available
      * Blowfish          key size must be multiple of 8, and can only range from 32 to 448 (inclusive)
      * RC2                  key size must be between 40 and 1024 bits
      * RC4(ARCFOUR)      key size must be between 40 and 1024 bits
      * </pre>
     
      * 在Key toKey(byte[] key)方法中使用下述代碼
      * <code>SecretKey secretKey = new SecretKeySpec(key, ALGORITHM);</code> 替換
      * <code>
      * DESKeySpec dks = new DESKeySpec(key);
      * SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
      * SecretKey secretKey = keyFactory.generateSecret(dks);
      * </code>
      */
     public  static  final  String ALGORITHM =  "DES" ;
 
     /**
      * 轉換**<br>
     
      * @param key
      * @return
      * @throws Exception
      */
     private  static  Key toKey( byte [] key)  throws  Exception {
         DESKeySpec dks =  new  DESKeySpec(key);
         SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
         SecretKey secretKey = keyFactory.generateSecret(dks);
 
         // 當使用其他對稱加密算法時,如AES、Blowfish等算法時,用下述代碼替換上述三行代碼
         // SecretKey secretKey = new SecretKeySpec(key, ALGORITHM);
 
         return  secretKey;
     }
 
     /**
      * 解密
     
      * @param data
      * @param key
      * @return
      * @throws Exception
      */
     public  static  byte [] decrypt( byte [] data, String key)  throws  Exception {
         Key k = toKey(decryptBASE64(key));
 
         Cipher cipher = Cipher.getInstance(ALGORITHM);
         cipher.init(Cipher.DECRYPT_MODE, k);
 
         return  cipher.doFinal(data);
     }
 
     /**
      * 加密
     
      * @param data
      * @param key
      * @return
      * @throws Exception
      */
     public  static  byte [] encrypt( byte [] data, String key)  throws  Exception {
         Key k = toKey(decryptBASE64(key));
         Cipher cipher = Cipher.getInstance(ALGORITHM);
         cipher.init(Cipher.ENCRYPT_MODE, k);
 
         return  cipher.doFinal(data);
     }
 
     /**
      * 生成**
     
      * @return
      * @throws Exception
      */
     public  static  String initKey()  throws  Exception {
         return  initKey( null );
     }
 
     /**
      * 生成**
     
      * @param seed
      * @return
      * @throws Exception
      */
     public  static  String initKey(String seed)  throws  Exception {
         SecureRandom secureRandom =  null ;
 
         if  (seed !=  null ) {
             secureRandom =  new  SecureRandom(decryptBASE64(seed));
         else  {
             secureRandom =  new  SecureRandom();
         }
 
         KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM);
         kg.init(secureRandom);
 
         SecretKey secretKey = kg.generateKey();
 
         return  encryptBASE64(secretKey.getEncoded());
     }
}


延續上一個類的實現,我們通過MD5以及SHA對字符串加密生成**,這是比較常見的**生成方式。 
再給出一個測試類:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import  static  org.junit.Assert.*;
 
 
import  org.junit.Test;
 
/**
 
  * @author 樑棟
  * @version 1.0
  * @since 1.0
  */
public  class  DESCoderTest {
 
     @Test
     public  void  test()  throws  Exception {
         String inputStr =  "DES" ;
         String key = DESCoder.initKey();
         System.err.println( "原文:\t"  + inputStr);
 
         System.err.println( "**:\t"  + key);
 
         byte [] inputData = inputStr.getBytes();
         inputData = DESCoder.encrypt(inputData, key);
 
         System.err.println( "加密後:\t"  + DESCoder.encryptBASE64(inputData));
 
         byte [] outputData = DESCoder.decrypt(inputData, key);
         String outputStr =  new  String(outputData);
 
         System.err.println( "解密後:\t"  + outputStr);
 
         assertEquals(inputStr, outputStr);
     }
}


得到的輸出內容如下:

原文:	DES
**:	f3wEtRrV6q0=

加密後:	C6qe9oNIzRY=

解密後:	DES


    由控制檯得到的輸出,我們能夠比對加密、解密後結果一致。這是一種簡單的加密解密方式,只有一個**。 
    其實DES有很多同胞兄弟,如DESede(TripleDES)、AES、Blowfish、RC2、RC4(ARCFOUR)。這裏就不過多闡述了,大同小異,只要換掉ALGORITHM換成對應的值,同時做一個代碼替換SecretKey secretKey = new SecretKeySpec(key, ALGORITHM);就可以了,此外就是**長度不同了。 

1
2
3
4
5
6
7
8
/**
  * DES          key size must be equal to 56
  * DESede(TripleDES) key size must be equal to 112 or 168
  * AES          key size must be equal to 128, 192 or 256,but 192 and 256 bits may not be available
  * Blowfish     key size must be multiple of 8, and can only range from 32 to 448 (inclusive)
  * RC2          key size must be between 40 and 1024 bits
  * RC4(ARCFOUR) key size must be between 40 and 1024 bits
  **/

    除了DES,我們還知道有DESede(TripleDES,就是3DES)、AES、Blowfish、RC2、RC4(ARCFOUR)等多種對稱加密方式,其實現方式大同小異,這裏介紹對稱加密的另一個算法——PBE 
PBE 
    PBE——Password-based encryption(基於密碼加密)。其特點在於口令由用戶自己掌管,不借助任何物理媒體;採用隨機數(這裏我們叫做鹽)雜湊多重加密等方法保證數據的安全性。是一種簡便的加密方式。 
通過java代碼實現如下:Coder類見 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
import  java.security.Key;
import  java.util.Random;
  
import  javax.crypto.Cipher;
import  javax.crypto.SecretKey;
import  javax.crypto.SecretKeyFactory;
import  javax.crypto.spec.PBEKeySpec;
import  javax.crypto.spec.PBEParameterSpec;
  
/**
  * PBE安全編碼組件
 
  * @author 樑棟
  * @version 1.0
  * @since 1.0
  */
public  abstract  class  PBECoder  extends  Coder {
     /**
      * 支持以下任意一種算法
     
      * <pre>
      * PBEWithMD5AndDES 
      * PBEWithMD5AndTripleDES 
      * PBEWithSHA1AndDESede
      * PBEWithSHA1AndRC2_40
      * </pre>
      */
     public  static  final  String ALGORITHM =  "PBEWITHMD5andDES" ;
  
     /**
      * 鹽初始化
     
      * @return
      * @throws Exception
      */
     public  static  byte [] initSalt()  throws  Exception {
         byte [] salt =  new  byte [ 8 ];
         Random random =  new  Random();
         random.nextBytes(salt);
         return  salt;
     }
  
     /**
      * 轉換**<br>
     
      * @param password
      * @return
      * @throws Exception
      */
     private  static  Key toKey(String password)  throws  Exception {
         PBEKeySpec keySpec =  new  PBEKeySpec(password.toCharArray());
         SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
         SecretKey secretKey = keyFactory.generateSecret(keySpec);
  
         return  secretKey;
     }
  
     /**
      * 加密
     
      * @param data 數據
      * @param password 密碼
      * @param salt  鹽
      * @return
      * @throws Exception
      */
     public  static  byte [] encrypt( byte [] data, String password,  byte [] salt)
             throws  Exception {
  
         Key key = toKey(password);
  
         PBEParameterSpec paramSpec =  new  PBEParameterSpec(salt,  100 );
         Cipher cipher = Cipher.getInstance(ALGORITHM);
         cipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
  
         return  cipher.doFinal(data);
  
     }
  
     /**
      * 解密
     
      * @param data  數據
      * @param password 密碼
      * @param salt  鹽
      * @return
      * @throws Exception
      */
     public  static  byte [] decrypt( byte [] data, String password,  byte [] salt)
             throws  Exception {
  
         Key key = toKey(password);
  
         PBEParameterSpec paramSpec =  new  PBEParameterSpec(salt,  100 );
         Cipher cipher = Cipher.getInstance(ALGORITHM);
         cipher.init(Cipher.DECRYPT_MODE, key, paramSpec);
  
         return  cipher.doFinal(data);
  
     }
}



再給出一個測試類: 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import  static  org.junit.Assert.*;
  
import  org.junit.Test;
  
/**
 
  * @author 樑棟
  * @version 1.0
  * @since 1.0
  */
public  class  PBECoderTest {
  
     @Test
     public  void  test()  throws  Exception {
         String inputStr =  "abc" ;
         System.err.println( "原文: "  + inputStr);
         byte [] input = inputStr.getBytes();
  
         String pwd =  "efg" ;
         System.err.println( "密碼: "  + pwd);
  
         byte [] salt = PBECoder.initSalt();
  
         byte [] data = PBECoder.encrypt(input, pwd, salt);
  
         System.err.println( "加密後: "  + PBECoder.encryptBASE64(data));
  
         byte [] output = PBECoder.decrypt(data, pwd, salt);
         String outputStr =  new  String(output);
  
         System.err.println( "解密後: "  + outputStr);
         assertEquals(inputStr, outputStr);
     }
  
}



控制檯輸出: 

原文: abc
密碼: efg
加密後: iCZ0uRtaAhE=
 
解密後: abc


    後續我們會介紹非對稱加密算法,如RSA、DSA、DH、ECC等。 

    接下來我們介紹典型的非對稱加密算法——RSA 

RSA 
    這種算法1978年就出現了,它是第一個既能用於數據加密也能用於數字簽名的算法。它易於理解和操作,也很流行。算法的名字以發明者的名字命名:Ron Rivest, AdiShamir 和Leonard Adleman。 
    這種加密算法的特點主要是**的變化,上文我們看到DES只有一個**。相當於只有一把鑰匙,如果這把鑰匙丟了,數據也就不安全了。RSA同時有兩把鑰 匙,公鑰與私鑰。同時支持數字簽名。數字簽名的意義在於,對傳輸過來的數據進行校驗。確保數據在傳輸工程中不被修改。 

流程分析: 

  1. 甲方構建**對兒,將公鑰公佈給乙方,將私鑰保留。

  2. 甲方使用私鑰加密數據,然後用私鑰對加密後的數據簽名,發送給乙方簽名以及加密後的數據;乙方使用公鑰、簽名來驗證待解密數據是否有效,如果有效使用公鑰對數據解密。

  3. 乙方使用公鑰加密數據,向甲方發送經過加密後的數據;甲方獲得加密數據,通過私鑰解密。



按如上步驟給出序列圖,如下: 

  1. 各種Java加密算法

  2. 各種Java加密算法

  3. 各種Java加密算法



通過java代碼實現如下:Coder類見

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
import  java.security.Key;
import  java.security.KeyFactory;
import  java.security.KeyPair;
import  java.security.KeyPairGenerator;
import  java.security.PrivateKey;
import  java.security.PublicKey;
import  java.security.Signature;
import  java.security.interfaces.RSAPrivateKey;
import  java.security.interfaces.RSAPublicKey;
import  java.security.spec.PKCS8EncodedKeySpec;
import  java.security.spec.X509EncodedKeySpec;
 
import  java.util.HashMap;
import  java.util.Map;
 
import  javax.crypto.Cipher;
 
/**
  * RSA安全編碼組件
 
  * @author 樑棟
  * @version 1.0
  * @since 1.0
  */
public  abstract  class  RSACoder  extends  Coder {
     public  static  final  String KEY_ALGORITHM =  "RSA" ;
     public  static  final  String SIGNATURE_ALGORITHM =  "MD5withRSA" ;
 
     private  static  final  String PUBLIC_KEY =  "RSAPublicKey" ;
     private  static  final  String PRIVATE_KEY =  "RSAPrivateKey" ;
 
     /**
      * 用私鑰對信息生成數字簽名
     
      * @param data
      *            加密數據
      * @param privateKey
      *            私鑰
     
      * @return
      * @throws Exception
      */
     public  static  String sign( byte [] data, String privateKey)  throws  Exception {
         // 解密由base64編碼的私鑰
         byte [] keyBytes = decryptBASE64(privateKey);
 
         // 構造PKCS8EncodedKeySpec對象
         PKCS8EncodedKeySpec pkcs8KeySpec =  new  PKCS8EncodedKeySpec(keyBytes);
 
         // KEY_ALGORITHM 指定的加密算法
         KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
 
         // 取私鑰匙對象
         PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);
 
         // 用私鑰對信息生成數字簽名
         Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
         signature.initSign(priKey);
         signature.update(data);
 
         return  encryptBASE64(signature.sign());
     }
 
     /**
      * 校驗數字簽名
     
      * @param data
      *            加密數據
      * @param publicKey
      *            公鑰
      * @param sign
      *            數字簽名
     
      * @return 校驗成功返回true 失敗返回false
      * @throws Exception
     
      */
     public  static  boolean  verify( byte [] data, String publicKey, String sign)
             throws  Exception {
 
         // 解密由base64編碼的公鑰
         byte [] keyBytes = decryptBASE64(publicKey);
 
         // 構造X509EncodedKeySpec對象
         X509EncodedKeySpec keySpec =  new  X509EncodedKeySpec(keyBytes);
 
         // KEY_ALGORITHM 指定的加密算法
         KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
 
         // 取公鑰匙對象
         PublicKey pubKey = keyFactory.generatePublic(keySpec);
 
         Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
         signature.initVerify(pubKey);
         signature.update(data);
 
         // 驗證簽名是否正常
         return  signature.verify(decryptBASE64(sign));
     }
 
     /**
      * 解密<br>
      * 用私鑰解密
     
      * @param data
      * @param key
      * @return
      * @throws Exception
      */
     public  static  byte [] decryptByPrivateKey( byte [] data, String key)
             throws  Exception {
         // 對**解密
         byte [] keyBytes = decryptBASE64(key);
 
         // 取得私鑰
         PKCS8EncodedKeySpec pkcs8KeySpec =  new  PKCS8EncodedKeySpec(keyBytes);
         KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
         Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
 
         // 對數據解密
         Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
         cipher.init(Cipher.DECRYPT_MODE, privateKey);
 
         return  cipher.doFinal(data);
     }
 
     /**
      * 解密<br>
      * 用私鑰解密
     
      * @param data
      * @param key
      * @return
      * @throws Exception
      */
     public  static  byte [] decryptByPublicKey( byte [] data, String key)
             throws  Exception {
         // 對**解密
         byte [] keyBytes = decryptBASE64(key);
 
         // 取得公鑰
         X509EncodedKeySpec x509KeySpec =  new  X509EncodedKeySpec(keyBytes);
         KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
         Key publicKey = keyFactory.generatePublic(x509KeySpec);
 
         // 對數據解密
         Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
         cipher.init(Cipher.DECRYPT_MODE, publicKey);
 
         return  cipher.doFinal(data);
     }
 
     /**
      * 加密<br>
      * 用公鑰加密
     
      * @param data
      * @param key
      * @return
      * @throws Exception
      */
     public  static  byte [] encryptByPublicKey( byte [] data, String key)
             throws  Exception {
         // 對公鑰解密
         byte [] keyBytes = decryptBASE64(key);
 
         // 取得公鑰
         X509EncodedKeySpec x509KeySpec =  new  X509EncodedKeySpec(keyBytes);
         KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
         Key publicKey = keyFactory.generatePublic(x509KeySpec);
 
         // 對數據加密
         Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
         cipher.init(Cipher.ENCRYPT_MODE, publicKey);
 
         return  cipher.doFinal(data);
     }
 
     /**
      * 加密<br>
      * 用私鑰加密
     
      * @param data
      * @param key
      * @return
      * @throws Exception
      */
     public  static  byte [] encryptByPrivateKey( byte [] data, String key)
             throws  Exception {
         // 對**解密
         byte [] keyBytes = decryptBASE64(key);
 
         // 取得私鑰
         PKCS8EncodedKeySpec pkcs8KeySpec =  new  PKCS8EncodedKeySpec(keyBytes);
         KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
         Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
 
         // 對數據加密
         Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
         cipher.init(Cipher.ENCRYPT_MODE, privateKey);
 
         return  cipher.doFinal(data);
     }
 
     /**
      * 取得私鑰
     
      * @param keyMap
      * @return
      * @throws Exception
      */
     public  static  String getPrivateKey(Map<String, Object> keyMap)
             throws  Exception {
         Key key = (Key) keyMap.get(PRIVATE_KEY);
 
         return  encryptBASE64(key.getEncoded());
     }
 
     /**
      * 取得公鑰
     
      * @param keyMap
      * @return
      * @throws Exception
      */
     public  static  String getPublicKey(Map<String, Object> keyMap)
             throws  Exception {
         Key key = (Key) keyMap.get(PUBLIC_KEY);
 
         return  encryptBASE64(key.getEncoded());
     }
 
     /**
      * 初始化**
     
      * @return
      * @throws Exception
      */
     public  static  Map<String, Object> initKey()  throws  Exception {
         KeyPairGenerator keyPairGen = KeyPairGenerator
                 .getInstance(KEY_ALGORITHM);
         keyPairGen.initialize( 1024 );
 
         KeyPair keyPair = keyPairGen.generateKeyPair();
 
         // 公鑰
         RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
 
         // 私鑰
         RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
 
         Map<String, Object> keyMap =  new  HashMap<String, Object>( 2 );
 
         keyMap.put(PUBLIC_KEY, publicKey);
         keyMap.put(PRIVATE_KEY, privateKey);
         return  keyMap;
     }
}


再給出一個測試類:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import  static  org.junit.Assert.*;
 
import  org.junit.Before;
import  org.junit.Test;
 
import  java.util.Map;
 
/**
 
  * @author 樑棟
  * @version 1.0
  * @since 1.0
  */
public  class  RSACoderTest {
     private  String publicKey;
     private  String privateKey;
 
     @Before
     public  void  setUp()  throws  Exception {
         Map<String, Object> keyMap = RSACoder.initKey();
 
         publicKey = RSACoder.getPublicKey(keyMap);
         privateKey = RSACoder.getPrivateKey(keyMap);
         System.err.println( "公鑰: \n\r"  + publicKey);
         System.err.println( "私鑰: \n\r"  + privateKey);
     }
 
     @Test
     public  void  test()  throws  Exception {
         System.err.println( "公鑰加密——私鑰解密" );
         String inputStr =  "abc" ;
         byte [] data = inputStr.getBytes();
 
         byte [] encodedData = RSACoder.encryptByPublicKey(data, publicKey);
 
         byte [] decodedData = RSACoder.decryptByPrivateKey(encodedData,
                 privateKey);
 
         String outputStr =  new  String(decodedData);
         System.err.println( "加密前: "  + inputStr +  "\n\r"  "解密後: "  + outputStr);
         assertEquals(inputStr, outputStr);
 
     }
 
     @Test
     public  void  testSign()  throws  Exception {
         System.err.println( "私鑰加密——公鑰解密" );
         String inputStr =  "sign" ;
         byte [] data = inputStr.getBytes();
 
         byte [] encodedData = RSACoder.encryptByPrivateKey(data, privateKey);
 
         byte [] decodedData = RSACoder
                 .decryptByPublicKey(encodedData, publicKey);
 
         String outputStr =  new  String(decodedData);
         System.err.println( "加密前: "  + inputStr +  "\n\r"  "解密後: "  + outputStr);
         assertEquals(inputStr, outputStr);
 
         System.err.println( "私鑰簽名——公鑰驗證簽名" );
         // 產生簽名
         String sign = RSACoder.sign(encodedData, privateKey);
         System.err.println( "簽名:\r"  + sign);
 
         // 驗證簽名
         boolean  status = RSACoder.verify(encodedData, publicKey, sign);
         System.err.println( "狀態:\r"  + status);
         assertTrue(status);
 
     }
 
}


控制檯輸出:

公鑰: 

MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCYU/+I0+z1aBl5X6DUUOHQ7FZpmBSDbKTtx89J
EcB64jFCkunELT8qiKly7fzEqD03g8ALlu5XvX+bBqHFy7YPJJP0ekE2X3wjUnh2NxlqpH3/B/xm
1ZdSlCwDIkbijhBVDjA/bu5BObhZqQmDwIxlQInL9oVz+o6FbAZCyHBd7wIDAQAB

私鑰: 

MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJhT/4jT7PVoGXlfoNRQ4dDsVmmY
FINspO3Hz0kRwHriMUKS6cQtPyqIqXLt/MSoPTeDwAuW7le9f5sGocXLtg8kk/R6QTZffCNSeHY3
GWqkff8H/GbVl1KULAMiRuKOEFUOMD9u7kE5uFmpCYPAjGVAicv2hXP6joVsBkLIcF3vAgMBAAEC
gYBvZHWoZHmS2EZQqKqeuGr58eobG9hcZzWQoJ4nq/CarBAjw/VovUHE490uK3S9ht4FW7Yzg3LV
/MB06Huifh6qf/X9NQA7SeZRRC8gnCQk6JuDIEVJOud5jU+9tyumJakDKodQ3Jf2zQtNr+5ZdEPl
uwWgv9c4kmpjhAdyMuQmYQJBANn6pcgvyYaia52dnu+yBUsGkaFfwXkzFSExIbi0MXTkhEb/ER/D
rLytukkUu5S5ecz/KBa8U4xIslZDYQbLz5ECQQCy5dutt7RsxN4+dxCWn0/1FrkWl2G329Ucewm3
QU9CKu4D+7Kqdj+Ha3lXP8F0Etaaapi7+EfkRUpukn2ItZV/AkEAlk+I0iphxT1rCB0Q5CjWDY5S
Df2B5JmdEG5Y2o0nLXwG2w44OLct/k2uD4cEcuITY5Dvi/4BftMCZwm/dnhEgQJACIktJSnJwxLV
o9dchENPtlsCM9C/Sd2EWpqISSUlmfugZbJBwR5pQ5XeMUqKeXZYpP+HEBj1nS+tMH9u2/IGEwJA
fL8mZiZXan/oBKrblAbplNcKWGRVD/3y65042PAEeghahlJMiYquV5DzZajuuT0wbJ5xQuZB01+X
nfpFpBJ2dw==

公鑰加密——私鑰解密
加密前: abc

解密後: abc
公鑰: 

MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDdOj40yEB48XqWxmPILmJAc7UecIN7F32etSHF
9rwbuEh3+iTPOGSxhoSQpOED0vOb0ZIMkBXZSgsxLaBSin2RZ09YKWRjtpCA0kDkiD11gj4tzTiM
l9qq1kwSK7ZkGAgodEn3yIILVmQDuEImHOXFtulvJ71ka07u3LuwUNdB/wIDAQAB

私鑰: 

MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAN06PjTIQHjxepbGY8guYkBztR5w
g3sXfZ61IcX2vBu4SHf6JM84ZLGGhJCk4QPS85vRkgyQFdlKCzEtoFKKfZFnT1gpZGO2kIDSQOSI
PXWCPi3NOIyX2qrWTBIrtmQYCCh0SffIggtWZAO4QiYc5cW26W8nvWRrTu7cu7BQ10H/AgMBAAEC
gYEAz2JWBizjI31bqhP4XiP9PuY5F3vqBW4T+L9cFbQiyumKJc58yzTWUAUGKIIn3enXLG7dNqGr
mbJro4JeFIJ3CiVDpXR9+FluIgI4SXm7ioGKF2NOMA9LR5Fu82W+pLfpTN2y2SaLYWEDZyp53BxY
j9gUxaxi1MQs+C1ZgDF2xmECQQDy70bQntbRfysP+ppCtd56YRnES1Tyekw0wryS2tr+ivQJl7JF
gp5rPAOXpgrq36xHDwUspQ0sJ0vj0O7ywxr1AkEA6SAaLhrJJrYucC0jxwAhUYyaPN+aOsWymaRh
9jA/Wc0wp29SbGTh5CcMuGpXm1g0M+FKW3dGiHgS3rVUKim4owJAbnxgapUzAgiiHxxMeDaavnHW
9C2GrtjsO7qtZOTgYI/1uT8itvZW8lJTF+9OW8/qXE76fXl7ai9dFnl5kzMk2QJBALfHz/vCsArt
mkRiwY6zApE4Z6tPl1V33ymSVovvUzHnOdD1SKQdD5t+UV/crb3QVi8ED0t2B0u0ZSPfDT/D7kMC
QDpwdj9k2F5aokLHBHUNJPFDAp7a5QMaT64gv/d48ITJ68Co+v5WzLMpzJBYXK6PAtqIhxbuPEc2
I2k1Afmrwyw=

私鑰加密——公鑰解密
加密前: sign

解密後: sign
私鑰簽名——公鑰驗證簽名
簽名:
ud1RsIwmSC1pN22I4IXteg1VD2FbiehKUfNxgVSHzvQNIK+d20FCkHCqh9djP3h94iWnIUY0ifU+
mbJkhAl/i5krExOE0hknOnPMcEP+lZV1RbJI2zG2YooSp2XDleqrQk5e/QF2Mx0Zxt8Xsg7ucv*n
i3wwbYWs9wSzIf0UjlM=

狀態:
true



    簡要總結一下,使用公鑰加密、私鑰解密,完成了乙方到甲方的一次數據傳遞,通過私鑰加密、公鑰解密,同時通過私鑰簽名、公鑰驗證簽名,完成了一次甲方到乙方的數據傳遞與驗證,兩次數據傳遞完成一整套的數據交互! 

類似數字簽名,數字信封是這樣描述的: 

數字信封 
        數字信封用加密技術來保證只有特定的收信人才能閱讀信的內容。 
流程: 
    信息發送方採用對稱**來加密信息,然後再用接收方的公鑰來加密此對稱**(這部分稱爲數字信封),再將它和信息一起發送給接收方;接收方先用相應的私鑰打開數字信封,得到對稱**,然後使用對稱**再解開信息。

    接下來我們分析DH加密算法,一種適基於**一致協議的加密算法。 
DH 
Diffie- Hellman算法(D-H算法),**一致協議。是由公開**密碼體制的奠基人Diffie和Hellman所提出的一種思想。簡單的說就是允許兩名用 戶在公開媒體上交換信息以生成"一致"的、可以共享的**。換句話說,就是由甲方產出一對**(公鑰、私鑰),乙方依照甲方公鑰產生乙方**對(公鑰、私 鑰)。以此爲基線,作爲數據傳輸保密基礎,同時雙方使用同一種對稱加密算法構建本地**(SecretKey)對數據加密。這樣,在互通了本地** (SecretKey)算法後,甲乙雙方公開自己的公鑰,使用對方的公鑰和剛纔產生的私鑰加密數據,同時可以使用對方的公鑰和自己的私鑰對數據解密。不單 單是甲乙雙方兩方,可以擴展爲多方共享數據通訊,這樣就完成了網絡交互數據的安全通訊!該算法源於中國的同餘定理——中國餘數定理。  

流程分析: 

1.甲方構建**對兒,將公鑰公佈給乙方,將私鑰保留;雙方約定數據加密算法;乙方通過甲方公鑰構建**對兒,將公鑰公佈給甲方,將私鑰保留。 
2.甲方使用私鑰、乙方公鑰、約定數據加密算法構建本地**,然後通過本地**加密數據,發送給乙方加密後的數據;乙方使用私鑰、甲方公鑰、約定數據加密算法構建本地**,然後通過本地**對數據解密。 
3.乙方使用私鑰、甲方公鑰、約定數據加密算法構建本地**,然後通過本地**加密數據,發送給甲方加密後的數據;甲方使用私鑰、乙方公鑰、約定數據加密算法構建本地**,然後通過本地**對數據解密。 

    1.  

各種Java加密算法

  1. 各種Java加密算法

  2. 各種Java加密算法


通過java代碼實現如下:Coder類見

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
import  java.security.Key;
import  java.security.KeyFactory;
import  java.security.KeyPair;
import  java.security.KeyPairGenerator;
import  java.security.PublicKey;
import  java.security.spec.PKCS8EncodedKeySpec;
import  java.security.spec.X509EncodedKeySpec;
import  java.util.HashMap;
import  java.util.Map;
 
import  javax.crypto.Cipher;
import  javax.crypto.KeyAgreement;
import  javax.crypto.SecretKey;
import  javax.crypto.interfaces.DHPrivateKey;
import  javax.crypto.interfaces.DHPublicKey;
import  javax.crypto.spec.DHParameterSpec;
 
/**
  * DH安全編碼組件
 
  * @author 樑棟
  * @version 1.0
  * @since 1.0
  */
public  abstract  class  DHCoder  extends  Coder {
     public  static  final  String ALGORITHM =  "DH" ;
 
     /**
      * 默認**字節數
     
      * <pre>
      * DH
      * Default Keysize 1024  
      * Keysize must be a multiple of 64, ranging from 512 to 1024 (inclusive).
      * </pre>
      */
     private  static  final  int  KEY_SIZE =  1024 ;
 
     /**
      * DH加密下需要一種對稱加密算法對數據加密,這裏我們使用DES,也可以使用其他對稱加密算法。
      */
     public  static  final  String SECRET_ALGORITHM =  "DES" ;
     private  static  final  String PUBLIC_KEY =  "DHPublicKey" ;
     private  static  final  String PRIVATE_KEY =  "DHPrivateKey" ;
 
     /**
      * 初始化甲方**
     
      * @return
      * @throws Exception
      */
     public  static  Map<String, Object> initKey()  throws  Exception {
         KeyPairGenerator keyPairGenerator = KeyPairGenerator
                 .getInstance(ALGORITHM);
         keyPairGenerator.initialize(KEY_SIZE);
 
         KeyPair keyPair = keyPairGenerator.generateKeyPair();
 
         // 甲方公鑰
         DHPublicKey publicKey = (DHPublicKey) keyPair.getPublic();
 
         // 甲方私鑰
         DHPrivateKey privateKey = (DHPrivateKey) keyPair.getPrivate();
 
         Map<String, Object> keyMap =  new  HashMap<String, Object>( 2 );
 
         keyMap.put(PUBLIC_KEY, publicKey);
         keyMap.put(PRIVATE_KEY, privateKey);
         return  keyMap;
     }
 
     /**
      * 初始化乙方**
     
      * @param key
      *            甲方公鑰
      * @return
      * @throws Exception
      */
     public  static  Map<String, Object> initKey(String key)  throws  Exception {
         // 解析甲方公鑰
         byte [] keyBytes = decryptBASE64(key);
         X509EncodedKeySpec x509KeySpec =  new  X509EncodedKeySpec(keyBytes);
         KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
         PublicKey pubKey = keyFactory.generatePublic(x509KeySpec);
 
         // 由甲方公鑰構建乙方**
         DHParameterSpec dhParamSpec = ((DHPublicKey) pubKey).getParams();
 
         KeyPairGenerator keyPairGenerator = KeyPairGenerator
                 .getInstance(keyFactory.getAlgorithm());
         keyPairGenerator.initialize(dhParamSpec);
 
         KeyPair keyPair = keyPairGenerator.generateKeyPair();
 
         // 乙方公鑰
         DHPublicKey publicKey = (DHPublicKey) keyPair.getPublic();
 
         // 乙方私鑰
         DHPrivateKey privateKey = (DHPrivateKey) keyPair.getPrivate();
 
         Map<String, Object> keyMap =  new  HashMap<String, Object>( 2 );
 
         keyMap.put(PUBLIC_KEY, publicKey);
         keyMap.put(PRIVATE_KEY, privateKey);
 
         return  keyMap;
     }
 
     /**
      * 加密<br>
     
      * @param data
      *            待加密數據
      * @param publicKey
      *            甲方公鑰
      * @param privateKey
      *            乙方私鑰
      * @return
      * @throws Exception
      */
     public  static  byte [] encrypt( byte [] data, String publicKey,
             String privateKey)  throws  Exception {
 
         // 生成本地**
         SecretKey secretKey = getSecretKey(publicKey, privateKey);
 
         // 數據加密
         Cipher cipher = Cipher.getInstance(secretKey.getAlgorithm());
         cipher.init(Cipher.ENCRYPT_MODE, secretKey);
 
         return  cipher.doFinal(data);
     }
 
     /**
      * 解密<br>
     
      * @param data
      *            待解密數據
      * @param publicKey
      *            乙方公鑰
      * @param privateKey
      *            乙方私鑰
      * @return
      * @throws Exception
      */
     public  static  byte [] decrypt( byte [] data, String publicKey,
             String privateKey)  throws  Exception {
 
         // 生成本地**
         SecretKey secretKey = getSecretKey(publicKey, privateKey);
         // 數據解密
         Cipher cipher = Cipher.getInstance(secretKey.getAlgorithm());
         cipher.init(Cipher.DECRYPT_MODE, secretKey);
 
         return  cipher.doFinal(data);
     }
 
     /**
      * 構建**
     
      * @param publicKey
      *            公鑰
      * @param privateKey
      *            私鑰
      * @return
      * @throws Exception
      */
     private  static  SecretKey getSecretKey(String publicKey, String privateKey)
             throws  Exception {
         // 初始化公鑰
         byte [] pubKeyBytes = decryptBASE64(publicKey);
 
         KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
         X509EncodedKeySpec x509KeySpec =  new  X509EncodedKeySpec(pubKeyBytes);
         PublicKey pubKey = keyFactory.generatePublic(x509KeySpec);
 
         // 初始化私鑰
         byte [] priKeyBytes = decryptBASE64(privateKey);
 
         PKCS8EncodedKeySpec pkcs8KeySpec =  new  PKCS8EncodedKeySpec(priKeyBytes);
         Key priKey = keyFactory.generatePrivate(pkcs8KeySpec);
 
         KeyAgreement keyAgree = KeyAgreement.getInstance(keyFactory
                 .getAlgorithm());
         keyAgree.init(priKey);
         keyAgree.doPhase(pubKey,  true );
 
         // 生成本地**
         SecretKey secretKey = keyAgree.generateSecret(SECRET_ALGORITHM);
 
         return  secretKey;
     }
 
     /**
      * 取得私鑰
     
      * @param keyMap
      * @return
      * @throws Exception
      */
     public  static  String getPrivateKey(Map<String, Object> keyMap)
             throws  Exception {
         Key key = (Key) keyMap.get(PRIVATE_KEY);
 
         return  encryptBASE64(key.getEncoded());
     }
 
     /**
      * 取得公鑰
      * </
相關文章
相關標籤/搜索