在一篇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 }
鹽值一直在變,當然密文就跟着變啦...不錯的東東,分享給大家啦...
