在網上找到一些朋友的資料,用Java實現了一個MD5加密碼,類比了一個使用者註冊產生密文儲存,使用者登入密文比較的效果。
類比實現功能細節:
1、使用者註冊,產生一個隨機位元組數組,並加密成16進位的字串,再把使用者的密碼也加密成16進位字串,將二者組合成一個密文,儲存入庫。
2、使用者登入,取出庫中的密文,轉成位元組數組,再從位元組數組中取出隨機位元組數組,與使用者登入密碼一起加密成存放雜湊值的位元組數組,再與庫中轉成的位元組數組比較,完成登入。
下面貼上代碼,供大家傳閱。
/** * 本類實現的功能要求:產生一個固定位元的隨機字串,並加密,和使用者密碼加密後的密文組合。 */package com.zyujie.util;import java.io.UnsupportedEncodingException;import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;import java.security.SecureRandom;import java.util.Arrays;public class MD5Util {//16進位需要的字串資料private static final String HEX_NUMS_STR = "0123456789ABCDEF";//隨機字串位元組數長度private static final Integer BYTE_LENGTH = 18;/** * 將16進位字串轉換成位元組數組 * * @param hex * @return */public static byte[] hexStringToByte(String hex) {int len = (hex.length() / 2);byte[] result = new byte[len];char[] hexChars = hex.toCharArray();for (int i = 0; i < len; i++) {int pos = i * 2;result[i] = (byte) (HEX_NUMS_STR.indexOf(hexChars[pos]) << 4 | HEX_NUMS_STR.indexOf(hexChars[pos + 1]));}return result;}/** * 將指定byte數群組轉換成16進位字串 * * @param b * @return */public static String byteToHexString(byte[] b) {StringBuffer hexString = new StringBuffer();for (int i = 0; i < b.length; i++) {String hex = Integer.toHexString(b[i] & 0xFF);if (hex.length() == 1) {hex = '0' + hex;}hexString.append(hex.toUpperCase());}return hexString.toString();}/** * 驗證口令是否合法 * * @param password * @param passwordInDb * @return * @throws NoSuchAlgorithmException * @throws UnsupportedEncodingException */public static boolean validPassword(String password, String passwordInDb)throws NoSuchAlgorithmException, UnsupportedEncodingException {// 將16進位字串格式口令轉換成位元組數組byte[] pwdInDb = hexStringToByte(passwordInDb);// 聲明一個隨機陣列變數byte[] randomByte = new byte[BYTE_LENGTH];// 將隨機數組從資料庫中儲存的口令位元組數組中提取出來,按其長度System.arraycopy(pwdInDb, 0, randomByte, 0, BYTE_LENGTH);// 建立訊息摘要對象MessageDigest md = MessageDigest.getInstance("MD5");// 將隨機數組據傳入訊息摘要對象md.update(randomByte);// 將口令的資料傳給訊息摘要對象md.update(password.getBytes("UTF-8"));// 產生輸入口令的訊息摘要byte[] digest = md.digest();// 聲明一個儲存資料庫中口令訊息摘要的變數byte[] digestInDb = new byte[pwdInDb.length - BYTE_LENGTH];// 取得資料庫中口令的訊息摘要System.arraycopy(pwdInDb, BYTE_LENGTH, digestInDb, 0,digestInDb.length);// 比較根據輸入口令產生的訊息摘要和資料庫中訊息摘要是否相同if (Arrays.equals(digest, digestInDb)) {// 口令正確返回口令匹配訊息return true;} else {// 口令不正確返回口令不匹配訊息return false;}}/** * 獲得加密後的16進位形式口令 * * @param password * @return * @throws NoSuchAlgorithmException * @throws UnsupportedEncodingException */public static String getEncryptedPwd(String password)throws NoSuchAlgorithmException, UnsupportedEncodingException {// 聲明加密後的口令陣列變數byte[] pwd = null;// 隨機數產生器SecureRandom random = new SecureRandom();// 聲明隨機陣列變數byte[] randomByte = new byte[BYTE_LENGTH];// 將隨機數放入隨機陣列變數中random.nextBytes(randomByte);// 聲明訊息摘要對象MessageDigest md = null;// 建立訊息摘要md = MessageDigest.getInstance("MD5");// 將鹽資料傳入訊息摘要對象md.update(randomByte);// 將口令的資料傳給訊息摘要對象md.update(password.getBytes("UTF-8"));// 獲得訊息摘要的位元組數組byte[] digest = md.digest();// 因為要在口令的位元組數組中存放隨機數組密文,所以加上隨機數組的位元組長度pwd = new byte[digest.length + BYTE_LENGTH];// 將鹽的位元組拷貝到產生的加密口令位元組數組的前相應該長度BYTE_LENGTH個位元組,以便在驗證口令時取出隨機數組System.arraycopy(randomByte, 0, pwd, 0, BYTE_LENGTH);// 將訊息摘要拷貝到加密口令位元組數組從第BYTE_LENGTH個位元組開始的位元組System.arraycopy(digest, 0, pwd, BYTE_LENGTH, digest.length);// 將位元組數組格式加密後的口令轉化為16進位字串格式的口令return byteToHexString(pwd);}}
package com.zyujie.util;import java.io.UnsupportedEncodingException;import java.security.NoSuchAlgorithmException;import java.util.HashMap;import java.util.Map;public class MD5Client {private static Map users = new HashMap();/* * main方法測試 */public static void main(String[] args) {String userName = "admin";String password = "123456";registerUser(userName, password);userName = "mduse";password = "abc";registerUser(userName, password);String loginUserId = "admin";String pwd = "123456";try {if (loginValid(loginUserId, pwd)) {System.out.println("登陸成功!!!");} else {System.out.println("口令錯誤,請重新輸入!!!");}} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (UnsupportedEncodingException e) {e.printStackTrace();}}/** * 註冊使用者 * * @param userName * @param password */public static void registerUser(String userName, String password) {String encryptedPwd = null;try {encryptedPwd = MD5Util.getEncryptedPwd(password);users.put(userName, encryptedPwd);} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (UnsupportedEncodingException e) {e.printStackTrace();}}/** * 驗證登陸 * * @param userName * @param password * @return * @throws UnsupportedEncodingException * @throws NoSuchAlgorithmException */public static boolean loginValid(String userName, String password)throws NoSuchAlgorithmException, UnsupportedEncodingException {String pwdInDb = (String) users.get(userName);if (null != pwdInDb) { // 該使用者存在return MD5Util.validPassword(password, pwdInDb);} else {System.out.println("不存在該使用者!!!");return false;}}}