View Javadoc
1   /**
2    * Copyright By Grandsoft Company Limited.  
3    * 2014年3月26日 下午4:11:51
4    */
5   package gboat2.base.bridge.util.security;
6   
7   import java.io.File;
8   import java.io.FileInputStream;
9   import java.io.FileNotFoundException;
10  import java.io.IOException;
11  import java.io.InputStream;
12  import java.security.Key;
13  import java.security.KeyPair;
14  import java.security.KeyPairGenerator;
15  import java.security.MessageDigest;
16  import java.security.NoSuchAlgorithmException;
17  
18  import javax.crypto.Cipher;
19  import javax.crypto.KeyGenerator;
20  
21  import org.apache.commons.io.IOUtils;
22  import org.apache.commons.lang3.StringUtils;
23  
24  /**
25   * 对数据进行加密、解密操作的基础工具类
26   * @author <a href="mailto:[email protected]">何明旺</a>
27   * @since 3.0
28   * @date 2014年3月26日
29   */
30  /**
31   * 
32   * @author <a href="mailto:[email protected]">何明旺</a>
33   * @since 3.0
34   * @date 2014年3月27日
35   */
36  public class Encryptor {
37  
38      /** The MD2 message digest algorithm defined in RFC 1319. */
39      public static final String MD2 = "MD2";
40  
41      /** The MD5 message digest algorithm defined in RFC 1321. */
42      public static final String MD5 = "MD5";
43      
44      /** Secure Hash Algorithm,安全散列算法 */
45      public static final String SHA = "SHA";
46  
47      /** The SHA-1 hash algorithm defined in the FIPS PUB 180-2. */
48      public static final String SHA_1 = "SHA-1";
49  
50      /** The SHA-256 hash algorithm defined in the FIPS PUB 180-2. */
51      public static final String SHA_256 = "SHA-256";
52  
53      /** The SHA-384 hash algorithm defined in the FIPS PUB 180-2. */
54      public static final String SHA_384 = "SHA-384";
55  
56      /** The SHA-512 hash algorithm defined in the FIPS PUB 180-2. */
57      public static final String SHA_512 = "SHA-512";
58  
59      /**
60       * 获取 MessageDigest 实例
61       * @param algorithm 加密算法,请参见本类中的名称为 {@code MD*} 和 {@code SHA*} 的常量
62       * @return
63       */
64      public static MessageDigest getMessageDigest(String algorithm){
65          try {
66              return MessageDigest.getInstance(algorithm);
67          } catch (NoSuchAlgorithmException e) {
68              throw new GboatSecurityException("算法 [" + algorithm + "] 不存在,或当前  JDK 不支持该算法。", e);
69          }
70      }
71  
72      /**
73       * 
74       * @param data 要加密的数据
75       * @param algorithm 加密算法,请参见本类中的名称为 {@code MD*} 和 {@code SHA*} 的常量
76       * @return 密文
77       */
78      public static byte[] digest(byte[] data, String algorithm){
79          if(data == null)
80              return null;
81          
82          MessageDigest messageDigest = getMessageDigest(algorithm);
83          messageDigest.update(data);
84          return messageDigest.digest(); 
85      }
86      
87      /**
88       * @param data 要加密的字符串
89       * @param algorithm 加密算法,请参见本类中的名称为 {@code MD*} 和 {@code SHA*} 的常量
90       * @return 密文
91       */
92      public static byte[] digest(String data, String algorithm){
93          return (data == null) ? null : digest(data.getBytes(), algorithm);
94      }
95      
96      /**
97       * @param file  要加密的文件
98       * @param algorithm 加密算法,请参见本类中的名称为 {@code MD*} 和 {@code SHA*} 的常量
99       * @return 密文
100      */
101     public static byte[] digest(File file, String algorithm){
102         if(file == null)
103             return null;
104         
105         MessageDigest messageDigest = getMessageDigest(algorithm);
106         InputStream input = null;
107         try {
108             input = new FileInputStream(file);
109             byte[] buffer = new byte[4096];
110             int length = 0;
111             while ((length = input.read(buffer)) > 0) {
112                 messageDigest.update(buffer, 0, length);
113             }
114         } catch (FileNotFoundException e) {
115             throw new GboatSecurityException("文件 [" + file.getAbsolutePath() + "] 不存在。", e);
116         } catch (IOException e) {
117             throw new GboatSecurityException("读取文件 [" + file.getAbsolutePath() + "] 发生错误。", e);
118         } finally {
119             IOUtils.closeQuietly(input);
120         }
121         return messageDigest.digest();
122     }
123     
124     /**
125      * 获取密钥生成器实例
126      * 
127      * @param algorithm 加密算法的名称,支持的算法有:
128      *            AES、ARCFOUR、Blowfish、DES、DESede、HmacMD5、HmacSHA1、HmacSHA256、HmacSHA384、HmacSHA512、RC2
129      * @return 密钥生成器
130      */
131     public static KeyGenerator getKeyGenerator(String algorithm) {
132         try {
133             return KeyGenerator.getInstance(algorithm);
134         } catch (NoSuchAlgorithmException e) {
135             throw new GboatSecurityException("获取密钥生成器实例失败:算法 [" + algorithm + "] 不存在,或当前  JDK 不支持该算法。", e);
136         }
137     }
138     
139     /**
140      * 根据算法名称和密钥长度生成私钥公钥对
141      * @param algorithm 算法名称,如:RSA、DSA
142      * @param size 密钥长度,如:512、1024
143      * @return
144      */
145     public static KeyPair getKeyPair(String algorithm, int size) {
146         try {
147             KeyPairGenerator keyGen = KeyPairGenerator.getInstance(algorithm);
148             keyGen.initialize(size);
149             return keyGen.genKeyPair();
150         } catch (NoSuchAlgorithmException e) {
151             throw new GboatSecurityException("生成私钥公钥对失败:算法 [" + algorithm + "] 不存在,或当前  JDK 不支持该算法。", e);
152         }
153     }
154     
155     /**
156      * 取得算法名称
157      * @param transformation
158      * @return
159      */
160     protected static String getAlgorithmFromTransformation(String transformation) {
161         return StringUtils.substringBefore(transformation, "/");
162     }
163     
164 
165     /**
166      * 对数据进行加密
167      * 
168      * @param data 要加密的明文数据
169      * @param key 密钥
170      * @param transformation the name of the transformation, format is "Algorithm/Modes/Paddings", e.g.,
171      *            DES/CBC/PKCS5Padding. See Appendix A in the <a target="_blank"
172      *            href="http://docs.oracle.com/javase/6/docs/technotes/guides/security/crypto/CryptoSpec.html#AppA">
173      *            Java Cryptography Architecture Reference Guide</a> for information about standard transformation names.<br>
174      *            <table>
175      *            <caption><h3>The following table lists cipher algorithms available in the SunJCE provider</h3></caption>
176      *            <thead>
177      *            <tr>
178      *            <th>Algorithm Name</th>
179      *            <th>Modes</th>
180      *            <th>Paddings</th>
181      *            </tr>
182      *            </thead>
183      *            <tbody>
184      *            <tr>
185      *            <td>AES</td>
186      *            <td>ECB, CBC, PCBC, CTR, CTS, CFB, CFB8..CFB128, OFB,
187      *            OFB8..OFB128</td>
188      *            <td>NOPADDING, PKCS5PADDING, ISO10126PADDING</td>
189      *            </tr>
190      *            <tr>
191      *            <td>AESWrap</td>
192      *            <td>ECB</td>
193      *            <td>NOPADDING</td>
194      *            </tr>
195      *            <tr>
196      *            <td>ARCFOUR</td>
197      *            <td>ECB</td>
198      *            <td>NOPADDING</td>
199      *            </tr>
200      *            <tr>
201      *            <td>Blowfish, DES, DESede, RC2</td>
202      *            <td>ECB, CBC, PCBC, CTR, CTS, CFB, CFB8..CFB64, OFB,
203      *            OFB8..OFB64</td>
204      *            <td>NOPADDING, PKCS5PADDING, ISO10126PADDING</td>
205      *            </tr>
206      *            <tr>
207      *            <td>DESedeWrap</td>
208      *            <td>CBC</td>
209      *            <td>NOPADDING</td>
210      *            </tr>
211      *            <tr>
212      *            <td>PBEWithMD5AndDES, PBEWithMD5AndTripleDES,
213      *            PBEWithSHA1AndDESede, PBEWithSHA1AndRC2_40</td>
214      *            <td>CBC</td>
215      *            <td>PKCS5Padding</td>
216      *            </tr>
217      *            <tr>
218      *            <td>RSA</td>
219      *            <td>ECB</td>
220      *            <td>NOPADDING, PKCS1PADDING, OAEPWITHMD5ANDMGF1PADDING,
221      *            OAEPWITHSHA1ANDMGF1PADDING, OAEPWITHSHA-1ANDMGF1PADDING,
222      *            OAEPWITHSHA-256ANDMGF1PADDING, OAEPWITHSHA-384ANDMGF1PADDING,
223      *            OAEPWITHSHA-512ANDMGF1PADDING <!-- OAEPPadding later --></td>
224      *            </tr>
225      *            </tbody>
226      *            </table>
227      * @return 密文
228      */
229     public static byte[] encrypt(byte[] data, Key key, String transformation) {  
230         try {
231             Cipher cipher = Cipher.getInstance(transformation);  
232             cipher.init(Cipher.ENCRYPT_MODE, key);  
233             return cipher.doFinal(data);
234         } catch (Exception e) {
235             throw new IllegalArgumentException("对数据进行 [" + transformation + "] 加密失败。", e);
236         }  
237     }
238 
239     /**
240      * 对数据进行解密
241      * 
242      * @param data 要解密的明文数据
243      * @param key 密钥
244      * @param transformation the name of the transformation, format is "Algorithm/Modes/Paddings", e.g.,
245      *            DES/CBC/PKCS5Padding. See Appendix A in the <a target="_blank"
246      *            href="http://docs.oracle.com/javase/6/docs/technotes/guides/security/crypto/CryptoSpec.html#AppA">
247      *            Java Cryptography Architecture Reference Guide</a> for information about standard transformation names.<br>
248      *            <table>
249      *            <caption><h3>The following table lists cipher algorithms available in the SunJCE provider</h3></caption>
250      *            <thead>
251      *            <tr>
252      *            <th>Algorithm Name</th>
253      *            <th>Modes</th>
254      *            <th>Paddings</th>
255      *            </tr>
256      *            </thead>
257      *            <tbody>
258      *            <tr>
259      *            <td>AES</td>
260      *            <td>ECB, CBC, PCBC, CTR, CTS, CFB, CFB8..CFB128, OFB,
261      *            OFB8..OFB128</td>
262      *            <td>NOPADDING, PKCS5PADDING, ISO10126PADDING</td>
263      *            </tr>
264      *            <tr>
265      *            <td>AESWrap</td>
266      *            <td>ECB</td>
267      *            <td>NOPADDING</td>
268      *            </tr>
269      *            <tr>
270      *            <td>ARCFOUR</td>
271      *            <td>ECB</td>
272      *            <td>NOPADDING</td>
273      *            </tr>
274      *            <tr>
275      *            <td>Blowfish, DES, DESede, RC2</td>
276      *            <td>ECB, CBC, PCBC, CTR, CTS, CFB, CFB8..CFB64, OFB,
277      *            OFB8..OFB64</td>
278      *            <td>NOPADDING, PKCS5PADDING, ISO10126PADDING</td>
279      *            </tr>
280      *            <tr>
281      *            <td>DESedeWrap</td>
282      *            <td>CBC</td>
283      *            <td>NOPADDING</td>
284      *            </tr>
285      *            <tr>
286      *            <td>PBEWithMD5AndDES, PBEWithMD5AndTripleDES,
287      *            PBEWithSHA1AndDESede, PBEWithSHA1AndRC2_40</td>
288      *            <td>CBC</td>
289      *            <td>PKCS5Padding</td>
290      *            </tr>
291      *            <tr>
292      *            <td>RSA</td>
293      *            <td>ECB</td>
294      *            <td>NOPADDING, PKCS1PADDING, OAEPWITHMD5ANDMGF1PADDING,
295      *            OAEPWITHSHA1ANDMGF1PADDING, OAEPWITHSHA-1ANDMGF1PADDING,
296      *            OAEPWITHSHA-256ANDMGF1PADDING, OAEPWITHSHA-384ANDMGF1PADDING,
297      *            OAEPWITHSHA-512ANDMGF1PADDING <!-- OAEPPadding later --></td>
298      *            </tr>
299      *            </tbody>
300      *            </table>
301      * 
302      * @return 密文
303      */
304     public static byte[] decrypt(byte[] data, Key key, String transformation) {  
305         try {
306             Cipher cipher = Cipher.getInstance(transformation);  
307             cipher.init(Cipher.DECRYPT_MODE, key);  
308             return cipher.doFinal(data);
309         } catch (Exception e) {
310             throw new IllegalArgumentException("对数据进行 [" + transformation + "] 解密失败。", e);
311         }  
312     }
313     
314 }