在一篇blog名叫:项目中加密存储密码的工具类---PasswordUtil类
中说道了PBE——Password-based encryption(基于密码加密)。我也做测试了一下,现在把我做的效果给大家演示一下:
运行效果:
==============================================================
代码部分:
==============================================================
/pbe/src/com/b510/passwordutil/PasswordUtil.java
1 /**
2 *
3 */
4 package com.b510.passwordutil;
5
6 import java.security.Key;
7 import java.security.SecureRandom;
8
9 import javax.crypto.Cipher;
10 import javax.crypto.SecretKey;
11 import javax.crypto.SecretKeyFactory;
12 import javax.crypto.spec.PBEKeySpec;
13 import javax.crypto.spec.PBEParameterSpec;
14
15 /**
16 * PBE——Password-based encryption(基于密码加密)。<br>
17 * 其特点在于口令由用户自己掌管,不借助任何物理媒体;采用随机数(这里我们叫做盐)杂凑多重加密等方法保证数据的安全性。<br>
18 * 是一种简便的加密方式。<br>
19 *
20 * @author <a href="mailto:hongtenzone@foxmail.com">hongten</a><br>
21 * @date 2013-4-3<br>
22 *
23 * @see <a href="http://blog.csdn.net/hexingzhi/article/details/7424872">原文</a>
24 */
25 public class PasswordUtil {
26
27 /**
28 * JAVA6支持以下任意一种算法 PBEWITHMD5ANDDES PBEWITHMD5ANDTRIPLEDES<测试的时候报错>
29 * PBEWITHSHAANDDESEDE<测试的时候报错> PBEWITHSHA1ANDRC2_40 PBKDF2WITHHMACSHA1<测试的时候报错>
30 * */
31
32 /**
33 * 本地测试通过:<code>PBEWITHMD5ANDDES</code>,<code>PBEWITHSHA1ANDRC2_40</code>
34 */
35
36 /**
37 * 定义使用的算法为:PBEWITHMD5andDES算法
38 */
39 public static final String ALGORITHM = "PBEWITHMD5ANDDES";
40
41 /**
42 * 定义迭代次数为1000次
43 */
44 private static final int ITERATIONCOUNT = 1000;
45
46 /**
47 * 获取加密算法中使用的盐值,解密中使用的盐值必须与加密中使用的相同才能完成操作. 盐长度必须为8字节
48 *
49 * @return byte[] 盐值
50 * */
51 public static byte[] getSalt() throws Exception {
52 // 实例化安全随机数
53 SecureRandom random = new SecureRandom();
54 // 产出盐
55 return random.generateSeed(8);
56 }
57
58 /**
59 * 根据PBE密码生成一把密钥
60 *
61 * @param password
62 * 生成密钥时所使用的密码
63 * @return Key PBE算法密钥
64 * */
65 private static Key getPBEKey(String password) throws Exception {
66 // 实例化使用的算法
67 SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
68 // 设置PBE密钥参数
69 PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray());
70 // 生成密钥
71 SecretKey secretKey = keyFactory.generateSecret(keySpec);
72
73 return secretKey;
74 }
75
76 /**
77 * 加密明文字符串
78 *
79 * @param plaintext
80 * 待加密的明文字符串
81 * @param password
82 * 生成密钥时所使用的密码
83 * @param salt
84 * 盐值
85 * @return 加密后的密文字符串
86 * @throws Exception
87 */
88 public static String encrypt(String plaintext, String password, byte[] salt)
89 throws Exception {
90
91 Key key = getPBEKey(password);
92
93 PBEParameterSpec parameterSpec = new PBEParameterSpec(salt,
94 ITERATIONCOUNT);
95
96 Cipher cipher = Cipher.getInstance(ALGORITHM);
97
98 cipher.init(Cipher.ENCRYPT_MODE, key, parameterSpec);
99
100 byte encipheredData[] = cipher.doFinal(plaintext.getBytes());
101
102 return bytesToHexString(encipheredData);
103 }
104
105 /**
106 * 解密密文字符串
107 *
108 * @param ciphertext
109 * 待解密的密文字符串
110 * @param password
111 * 生成密钥时所使用的密码(如需解密,该参数需要与加密时使用的一致)
112 * @param salt
113 * 盐值(如需解密,该参数需要与加密时使用的一致)
114 * @return 解密后的明文字符串
115 * @throws Exception
116 */
117 public static String decrypt(String ciphertext, String password, byte[] salt)
118 throws Exception {
119
120 Key key = getPBEKey(password);
121
122 PBEParameterSpec parameterSpec = new PBEParameterSpec(salt,
123 ITERATIONCOUNT);
124
125 Cipher cipher = Cipher.getInstance(ALGORITHM);
126
127 cipher.init(Cipher.DECRYPT_MODE, key, parameterSpec);
128
129 byte[] passDec = cipher.doFinal(hexStringToBytes(ciphertext));
130
131 return new String(passDec);
132 }
133
134 /**
135 * 将字节数组转换为十六进制字符串
136 *
137 * @param src
138 * 字节数组
139 * @return
140 */
141 public static String bytesToHexString(byte[] src) {
142 StringBuilder stringBuilder = new StringBuilder("");
143 if (src == null || src.length <= 0) {
144 return null;
145 }
146 for (int i = 0; i < src.length; i++) {
147 int v = src[i] & 0xFF;
148 String hv = Integer.toHexString(v);
149 if (hv.length() < 2) {
150 stringBuilder.append(0);
151 }
152 stringBuilder.append(hv);
153 }
154 return stringBuilder.toString();
155 }
156
157 /**
158 * 将十六进制字符串转换为字节数组
159 *
160 * @param hexString
161 * 十六进制字符串
162 * @return
163 */
164 public static byte[] hexStringToBytes(String hexString) {
165 if (hexString == null || hexString.equals("")) {
166 return null;
167 }
168 hexString = hexString.toUpperCase();
169 int length = hexString.length() / 2;
170 char[] hexChars = hexString.toCharArray();
171 byte[] d = new byte[length];
172 for (int i = 0; i < length; i++) {
173 int pos = i * 2;
174 d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
175 }
176 return d;
177 }
178
179 private static byte charToByte(char c) {
180 return (byte) "0123456789ABCDEF".indexOf(c);
181 }
182
183
184 public static void main(String[] args) {
185 String str = "hongtenzone@foxmail.com";
186 String password = "hongten123";
187
188 System.out.println("明文:" + str);
189 System.out.println("密码:" + password);
190
191 try {
192 byte[] salt = PasswordUtil.getSalt();
193 System.out.println("盐值:"+salt.toString());
194 String ciphertext = PasswordUtil.encrypt(str, password, salt);
195 System.out.println("密文:" + ciphertext);
196 String plaintext = PasswordUtil.decrypt(ciphertext, password, salt);
197 System.out.println("明文:" + plaintext);
198 } catch (Exception e) {
199 e.printStackTrace();
200 }
201 }
202 }
盐值一直在变,当然密文就跟着变啦...不错的东东,分享给大家啦...