Java 關於密碼處理的工具類[MD5編碼][AES加密/解密]


 

項目中又遇到了加密問題,又去翻了半天,然后做測試,干脆就把常用的兩類小結一下.

 

1.第一種所謂的MD5加密

 其實也不算加密,只是基於Hash算法的不可逆編碼而已,等於說,一旦經過MD5處理,是不可能從編碼后的字符串反推回去的.

 MD5的方法是基於散列的。本身信息不全。理論上是不能還原成唯一字符串的。

 網上所謂的解密,也只是擁有一個足夠大的字典映射,將編碼前的源字符和編碼后的目標字符關聯起來而已,大多數常見的還行,復雜點的估計就會話費很長時間,有興趣的可以試試.

 

 至於MD5的用法,在初次錄入的時候,也就做一次編碼,而后存儲,沒什么可說的.主要是驗證一致性,如登錄中的密碼,普遍做法就是將新獲取的密碼編碼,在用編碼之后的和數據庫中的比較,判斷是否一致.

 理論上來講,對於這個密碼,除了使用的人,其他人是不知道的,包括管理員.

 一般的系統這種方案也就夠用了.或者利用MD5多次編碼(加密),次數自己控制即可,也能增加點安全性.

 

2.第二種就是AES加密/解密

 AES 是一種對稱加密算法,加密過程中要使用密鑰這個東西. 有興趣的可以去仔細了解一下: http://www.mamicode.com/info-detail-514466.html

 就是說,我有個密碼:mima001,要使用AES加密,此時我就需要提供一個 密鑰(key) :thisKey,然后使用AES算法加密,得到一個結果result,存入數據庫;

 然后,解密的時候,我們從數據庫中拿到這個result,然后同時也要獲得上面加密的時候用到的密鑰:thisKey,然后使用AES算法解密;

 在這個過程中,如果有密鑰,則整個過程是可逆的,並且密鑰只有一個,可逆相對來說也就是對稱的,加密前和解密后的東西,沒有什么差異.

 

另外,補充一點啊,就是加密解密基礎問題:字節數組和(16進制)字符串的相互轉換

在加密時,一般加密算法和hash算法,它們操作的都是字節數組,對字節數組按照加密算法進行各種變換,運算,得到的結果也是字節數組。而我們一般是要求對字符串進行加密,所以就涉及到字符串String到 byte[] 的轉換,這個很簡單。同時在解密時,也涉及到字節數組byte[] 到 String 的轉換。另外在對用戶的密碼進行hash加密之后,最終是要保存在數據庫中,所以加密得到 byte[] 也要轉換到 String.

想了解詳細一點的朋友可以去: http://www.cnblogs.com/digdeep/p/4627813.html 看看.

 

下面是工具類:提供了加密方法,解密方法,還有講加密結果轉換為常見的字符串轉換方法.

 

  1 import javax.crypto.*;
  2 import javax.crypto.spec.SecretKeySpec;
  3 import java.io.UnsupportedEncodingException;
  4 import java.security.InvalidKeyException;
  5 import java.security.MessageDigest;
  6 import java.security.NoSuchAlgorithmException;
  7 import java.security.SecureRandom;
  8 
  9 /**
 10  * @see: PasswordUtil
 11  * @author: lnexin@aliyun.com
 12  * @date: 2017-04-29  10:12
 13  */
 14 public class PasswordUtil {
 15     /**
 16      * 使用:
 17      *      直接使用即可,至於具體參數,看下面方法的說明即可;
 18      *      1. PasswordUtil.MD5Encode();  MD5不可逆簡單加密:散列函數-基於HASH算法的編碼
 19      *      2. PasswordUtil.AESEncrypt(); AES加密
 20      *      3. PasswordUtil.AESDecrypt(); AES解密
 21      *      4. PasswordUtil.parseByte2HexStr(); 二進制到16進制
 22      *      5. PasswordUtil.parseHexStr2Byte(); 16進制到2進制
 23      */
 24     
 25     // 16進制的字符數組
 26     private final static String[] hexDigits = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};
 27     
 28     /**
 29      * @param source    原字符串
 30      * @param encoding  指定編碼類型
 31      * @param uppercase 是否轉為大寫字符串
 32      */
 33     public static String MD5Encode(String source, String encoding, boolean uppercase) {
 34         String result = null;
 35         try {
 36             result = source;
 37             // 獲得MD5摘要對象
 38             MessageDigest messageDigest = MessageDigest.getInstance("MD5");
 39             // 使用指定的字節數組更新摘要信息
 40             messageDigest.update(result.getBytes(encoding));
 41             // messageDigest.digest()獲得16位長度
 42             // result = parseByte2HexStr(messageDigest.digest());
 43             result = byteArrayToHexString(messageDigest.digest());
 44             
 45         } catch (Exception e) {
 46             e.printStackTrace();
 47         }
 48         return uppercase ? result.toUpperCase() : result;
 49     }
 50     
 51     /**
 52      * AES 加密
 53      *
 54      * @param content 需要加密的內容
 55      * @param aesKey  加密密鑰
 56      * @return
 57      */
 58     public static byte[] AESEncrypt(String content, String aesKey) {
 59         try {
 60             KeyGenerator kgen = KeyGenerator.getInstance("AES");
 61             kgen.init(128, new SecureRandom(aesKey.getBytes()));
 62             SecretKey secretKey = kgen.generateKey();
 63             byte[] enCodeFormat = secretKey.getEncoded();
 64             SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
 65             Cipher cipher = Cipher.getInstance("AES");// 創建密碼器
 66             byte[] byteContent = content.getBytes("utf-8");
 67             cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化
 68             byte[] result = cipher.doFinal(byteContent);
 69             return result; // 加密
 70         } catch (NoSuchAlgorithmException e) {
 71             e.printStackTrace();
 72         } catch (NoSuchPaddingException e) {
 73             e.printStackTrace();
 74         } catch (InvalidKeyException e) {
 75             e.printStackTrace();
 76         } catch (UnsupportedEncodingException e) {
 77             e.printStackTrace();
 78         } catch (IllegalBlockSizeException e) {
 79             e.printStackTrace();
 80         } catch (BadPaddingException e) {
 81             e.printStackTrace();
 82         }
 83         return null;
 84     }
 85     
 86     /**
 87      * 解密
 88      *
 89      * @param content 待解密內容
 90      * @param aesKey  解密密鑰 秘miyao
 91      * @return
 92      */
 93     public static byte[] AESDecrypt(byte[] content, String aesKey) {
 94         try {
 95             KeyGenerator kgen = KeyGenerator.getInstance("AES");
 96             kgen.init(128, new SecureRandom(aesKey.getBytes()));
 97             SecretKey secretKey = kgen.generateKey();
 98             byte[] enCodeFormat = secretKey.getEncoded();
 99             SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
100             Cipher cipher = Cipher.getInstance("AES");// 創建密碼器
101             cipher.init(Cipher.DECRYPT_MODE, key);// 初始化
102             byte[] result = cipher.doFinal(content);
103             return result; // 加密
104         } catch (NoSuchAlgorithmException e) {
105             e.printStackTrace();
106         } catch (NoSuchPaddingException e) {
107             e.printStackTrace();
108         } catch (InvalidKeyException e) {
109             e.printStackTrace();
110         } catch (IllegalBlockSizeException e) {
111             e.printStackTrace();
112         } catch (BadPaddingException e) {
113             e.printStackTrace();
114         }
115         return null;
116     }
117     
118     /**
119      * 將二進制轉換成16進制
120      */
121     public static String parseByte2HexStr(byte buf[]) {
122         StringBuffer sb = new StringBuffer();
123         for (int i = 0; i < buf.length; i++) {
124             String hex = Integer.toHexString(buf[i] & 0xFF);
125             if (hex.length() == 1) {
126                 hex = '0' + hex;
127             }
128             sb.append(hex.toUpperCase());
129         }
130         return sb.toString();
131     }
132     
133     /**
134      * 將16進制轉換為二進制
135      */
136     public static byte[] parseHexStr2Byte(String hexStr) {
137         if (hexStr.length() < 1)
138             return null;
139         byte[] result = new byte[hexStr.length() / 2];
140         for (int i = 0; i < hexStr.length() / 2; i++) {
141             int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
142             int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
143             result[i] = (byte) (high * 16 + low);
144         }
145         return result;
146     }
147     
     //byte轉16進制 148 private static String byteArrayToHexString(byte[] bytes) { 149 StringBuilder stringBuilder = new StringBuilder(); 150 for (byte tem : bytes) { 151 stringBuilder.append(byteToHexString(tem)); 152 } 153 return stringBuilder.toString(); 154 } 155 //16進制轉byte[] 156 private static String byteToHexString(byte b) { 157 int n = b; 158 if (n < 0) { 159 n = 256 + n; 160 } 161 int d1 = n / 16; 162 int d2 = n % 16; 163 return hexDigits[d1] + hexDigits[d2]; 164 } 165 166 }

 

使用說明:

隨便寫個測試類:截圖直觀一點,控制台輸出在圖右下角,測試具體代碼在文末.

 

 

 1 public class PasswordTest {
 2     
 3     
 4     @Test
 5     public void MD5Test() throws Exception {
 6         String encode = PasswordUtil.MD5Encode("admin", "UTF8", true);
 7         System.out.println();
 8         System.out.println("MD5算法:"+encode);
 9     }
10     
11     @Test
12     public void aesTest() throws Exception {
13         String content = "admin";
14         String aesKey = "thisiskey";
15         
16         byte[] encrypt = PasswordUtil.AESEncrypt(content, aesKey);//加密
17         System.out.println("AES加密后-byte[]:"+encrypt);
18         
19         String strHex = PasswordUtil.parseByte2HexStr(encrypt);
20         System.out.println("轉換后的十六進制:"+strHex);
21         
22         
23         byte[] decrypt = PasswordUtil.AESDecrypt(PasswordUtil.parseHexStr2Byte(strHex), aesKey);//解密
24         System.out.println("AES解密后-byte[]"+decrypt);
25         System.out.println("AES解密轉換后:"+new String(decrypt));
26     }
27     
28 }

 

使用工具類的時候,要傳入什么參數,主要方法上面的注釋即可;

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM