在一篇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 }
盐值一直在变,当然密文就跟着变啦...不错的东东,分享给大家啦...