随机数生成
package com.frank.common.utils;
import java.util.Random;
/**
* Description: 随机生成字符串
* Auth: Frank
* Date: 2017-10-26
* Time: 上午 10:25
*/
public class StringRandomUtil {
private static final String CHAR = "char";//字母
private static final String NUM = "num";//数字
/**
* 获得指定长度的随机字符串
* 参照ASCII码表 65到90为大写字母,97到122为小写字母
* @param length 要生成的字符串长度
* @return 返回生成的随机字符串
*/
public static String getStringRandom(int length) {
StringBuffer valSb = new StringBuffer();
Random random = new Random();
//参数length,表示生成几位随机数
for(int i = 0; i < length; i++) {
//输出是数字还是字母
String charOrNum = random.nextInt(2) % 2 == 0 ? CHAR : NUM;
switch (charOrNum){
case CHAR:
//输出是大写字母还是小写字母
int temp = random.nextInt(2) % 2 == 0 ? 65 : 97;
valSb.append((char)(random.nextInt(26) + temp));
break;
case NUM:
valSb.append(random.nextInt(10));
break;
default:
break;
}
}
return valSb.toString();
}
}
MD5
package com.frank.common.utils;
import java.util.Random;
/**
* Description: 随机生成字符串
* Auth: Frank
* Date: 2017-10-26
* Time: 上午 10:25
*/
public class StringRandomUtil {
private static final String CHAR = "char";//字母
private static final String NUM = "num";//数字
/**
* 获得指定长度的随机字符串
* 参照ASCII码表 65到90为大写字母,97到122为小写字母
* @param length 要生成的字符串长度
* @return 返回生成的随机字符串
*/
public static String getStringRandom(int length) {
StringBuffer valSb = new StringBuffer();
Random random = new Random();
//参数length,表示生成几位随机数
for(int i = 0; i < length; i++) {
//输出是数字还是字母
String charOrNum = random.nextInt(2) % 2 == 0 ? CHAR : NUM;
switch (charOrNum){
case CHAR:
//输出是大写字母还是小写字母
int temp = random.nextInt(2) % 2 == 0 ? 65 : 97;
valSb.append((char)(random.nextInt(26) + temp));
break;
case NUM:
valSb.append(random.nextInt(10));
break;
default:
break;
}
}
return valSb.toString();
}
}
BASE64
package com.frank.common.utils;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
/**
* Description:BASE64 加密工具类
* Auth: Frank
* Date: 2017-10-26
* Time: 下午 3:29
*/
public class BASE64Util {
/**
* BASE64解密
*
* @param key
* @return
* @throws Exception
*/
public static byte[] decryptBASE64(String key) throws Exception {
return (new BASE64Decoder()).decodeBuffer(key);
}
/**
* BASE64加密
*
* @param key
* @return
* @throws Exception
*/
public static String encryptBASE64(byte[] key) throws Exception {
return (new BASE64Encoder()).encodeBuffer(key);
}
}
package com.frank.common.utils;
import org.apache.commons.codec.binary.Hex;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;
/**
* Description: 加盐工具
* Auth: Frank
* Date: 2017-10-26
* Time: 上午 9:58
*/
public class SaltUtil {
/**
* 密码进行加盐
* <p>
* 加盐规则:
* 1.随机生成十六位的字符
* 2.字符串加盐:密码和随机生成的十六位字符串组成密码加盐字符串
* 2.密码加盐字符串生成的十六进制的MD5
* 3.MD5加盐:new一个48位的char数组,然后往这个48位数组中插入32位的密码加盐字符串生成的十六进制的MD5和随机生成的16位字符串;
* 插入规则为把48位数组分成16块,每块的第一和第三个位置按顺序放入密码加盐字符串生成的十六进制的MD5的值,第二个位置按顺序放入随机字符
* 4.返回加盐后的密码
* </p>
* @param pwd 要进行加盐的字符串
* @return 经过加盐之后的一串字符
*/
public static String addSalt(String pwd) throws NoSuchAlgorithmException {
//随机生成十六位的字符
String salt = StringRandomUtil.getStringRandom(16);
//生成加盐密码字符串
StringBuffer passSalt = new StringBuffer();
passSalt.append(pwd).append(salt);
//生成加盐密码字符串的十六进制MD5摘要
String md5Hex = Md5Util.md5Hex(passSalt.toString());
//加盐密码的MD5进行加盐
char[] cs = new char[48];
for (int i = 0; i < 48; i += 3) {
cs[i] = md5Hex.charAt(i / 3 * 2);
cs[i + 1] = salt.charAt(i / 3);
cs[i + 2] = md5Hex.charAt(i / 3 * 2 + 1);
}
return new String(cs);
}
/**
* 校验密码和加盐的密码是否匹配
* @param pwd 密码
* @param md5Salt 加盐之后的密码
* @return 是否匹配
* @throws NoSuchAlgorithmException
*/
public static boolean verifyPwd(String pwd, String md5Salt) throws NoSuchAlgorithmException {
//加盐密码的md5
char[] pwdSaltMd5 = new char[32];
//加盐的char数组
char[] saltChar = new char[16];
for (int i = 0; i < 48; i += 3) {
pwdSaltMd5[i / 3 * 2] = md5Salt.charAt(i);
pwdSaltMd5[i / 3 * 2 + 1] = md5Salt.charAt(i + 2);
saltChar[i / 3] = md5Salt.charAt(i + 1);
}
String salt = new String(saltChar);
StringBuffer sb = new StringBuffer();
sb.append(pwd).append(salt);
return Md5Util.md5Hex(sb.toString()).equals(new String(pwdSaltMd5));
}
}
密码生成
package com.frank.common.utils;
/**
* Description: 用户密码工具
* Auth: Frank
* Date: 2017-10-26
* Time: 下午 3:44
*/
public class PwdUtil {
/**
* 返回用户加密后的密码
* <p>
* 加密后的密码生成规则:
* 1.先对密码进行加盐操作
* 2.对加盐后的密码进行Base64加密
* </p>
* @param pwd 用户密码
* @return 加密后的密码
* @throws Exception
*/
public static String getEncryptePwd(String pwd) throws Exception {
String pwdSalt = SaltUtil.addSalt(pwd);
return BASE64Util.encryptBASE64(pwdSalt.getBytes());
}
/**
* 校验用户密码是否与加密后的密码匹配
* @param pwd 用户密码
* @param pwdSaltBase64 加密后的密码
* @return 是否匹配
* @throws Exception
*/
public static boolean verifyPwd(String pwd,String pwdSaltBase64) throws Exception {
byte[] pwdSaltByte = BASE64Util.decryptBASE64(pwdSaltBase64);
//Base64解密之后加盐密码
String pwdSalt = new String(pwdSaltByte);
return SaltUtil.verifyPwd(pwd,pwdSalt);
}
public static void main(String[] args) throws Exception {
String pass = "#@%¥#¥……%~!@#¥%……&**……1q2w3e4r";
String salt = getEncryptePwd(pass);
System.out.println("原文:"+pass);
System.out.println("加盐:"+salt);
System.out.println("校验:"+verifyPwd(pass,salt));
}
}