项目中又遇到了加密问题,又去翻了半天,然后做测试,干脆就把常用的两类小结一下.
1.第一种所谓的MD5加密
不可逆编码而已,等于说,一旦经过MD5处理,是不可能从编码后的字符串反推回去的.
不能还原成唯一字符串的。
网上所谓的解密,也只是拥有一个足够大的字典映射,将编码前的源字符和编码后的目标字符关联起来而已,大多数常见的还行,复杂点的估计就会话费很长时间,有兴趣的可以试试.
至于MD5的用法,在初次录入的时候,也就做一次编码,而后存储,没什么可说的.主要是验证一致性,如登录中的密码,普遍做法就是将新获取的密码编码,在用编码之后的和数据库中的比较,判断是否一致.
理论上来讲,对于这个密码,除了使用的人,其他人是不知道的,包括管理员.
一般的系统这种方案也就够用了.或者利用MD5多次编码(加密),次数自己控制即可,也能增加点安全性.
2.第二种就是AES加密/解密
AES 是一种对称加密算法,加密过程中要使用密钥这个东西. 有兴趣的可以去仔细了解一下: http://www.mamicode.com/info-detail-514466.html
密钥(key) :thisKey,然后使用AES算法加密,得到一个结果result,存入数据库;
密钥:thisKey,然后使用AES算法解密;
可逆的,并且密钥只有一个,可逆相对来说也就是对称的,加密前和解密后的东西,没有什么差异.
另外,补充一点啊,就是加密解密基础问题:字节数组和(16进制)字符串的相互转换
在加密时,一般加密算法和hash算法,它们操作的都是字节数组,对字节数组按照加密算法进行各种变换,运算,得到的结果也是字节数组。而我们一般是要求对字符串进行加密,所以就涉及到字符串String到 byte[] 的转换,这个很简单。同时在解密时,也涉及到字节数组byte[] 到 String 的转换。另外在对用户的密码进行hash加密之后,最终是要保存在数据库中,所以加密得到 byte[] 也要转换到 String.
想了解详细一点的朋友可以去: 看看.
下面是工具类:提供了加密方法,解密方法,还有讲加密结果转换为常见的字符串转换方法.
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 }
使用工具类的时候,要传入什么参数,主要方法上面的注释即可;