一.基本概念
1.加密一般有两种:双向密码和单向加密。双向加密是最常用的,它既能加密又能解密;单向加密只能对数据进行加密,不能对其解密。
2.常用方法:单向加密:MD5(加密不可逆)、SHA1(加密不可逆,更安全,就是解析慢点)
双向加密:BASE64(可加密,解密)
二.实现
1.MD5的加密、加盐
(1).MD5:一种被广泛使用的密码散列函数,可以产生出一个128位(16字节)的散列值(hash value),用于确保信息传输完整一致,是一种不可逆的摘要算法,用于生成摘要,无法逆破解到原文
(2).引用commons-codec-1.10.jar包或者导入POM依赖
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.10</version>
</dependency>
(4).普通MD5加密(不建议使用,不安全):
String md5Str = DigestUtils.md5Hex(str);
System.out.println(“MD5–>” + md5Str);
(3).加盐:
原理是:先撒盐,使原密码+盐 生成一个新的字符串,然后对这个新的字符串进行MD5加密,或者base64加密,当然这只是简单的一种实现,实际开发中可以采用多次撒盐和多次MD5,或者base64加密的方式来进行编码。
==>
/**
* 获取十六进制字符串形式的MD5摘要
*/
private static String md5Hex(String src) {
try {
MessageDigest md5 = MessageDigest.getInstance("MD5");
byte[] bs = md5.digest(src.getBytes());
return new String(new Hex().encode(bs));
} catch (Exception e) {
return null;
}
}
==>注解:加盐方式不唯一,可自行研究高级算法
/**
* 加盐操作,生成含有随机盐的密码,每个用户随机不同盐值,生成48位密码
* @author TSYH
* @param password
* @return
*/
public static String generate(String password) {
Random r = new Random();
StringBuilder sb = new StringBuilder(16);
sb.append(r.nextInt(99999999)).append(r.nextInt(99999999));
int len = sb.length();
if (len < 16) {
for (int i = 0; i < 16 - len; i++) {
sb.append("0");
}
}
String salt = sb.toString();
password = md5Hex(password + salt);
char[] cs = new char[48];
for (int i = 0; i < 48; i += 3) {
cs[i] = password.charAt(i / 3 * 2);
char c = salt.charAt(i / 3);
cs[i + 1] = c;
cs[i + 2] = password.charAt(i / 3 * 2 + 1);
}
return new String(cs);
}
==>注解:password为原密码,md5为加盐后的密码
/**
* 校验加盐后是否和原密码一致,解密
* @author TSYH
* @param password
* @param md5
* @return
*/
public static boolean verify(String password, String md5) {
char[] cs1 = new char[32];
char[] cs2 = new char[16];
for (int i = 0; i < 48; i += 3) {
cs1[i / 3 * 2] = md5.charAt(i);
cs1[i / 3 * 2 + 1] = md5.charAt(i + 2);
cs2[i / 3] = md5.charAt(i + 1);
}
String salt = new String(cs2);
return md5Hex(password + salt).equals(new String(cs1));
}
==>测试
public static void main(String args[]) {
String password= "lalala";
System.out.println("原始:" + password);
System.out.println("普通MD5后:" + MD5Util.MD5(password));
// 获取加盐后的MD5值
String spassword= MD5Util.generate(password);
System.out.println("加盐后MD5:" + spassword);
System.out.println("是否是同一字符串:" + MD5Util.verify("aa", spassword)); //false
}
2.SHA1的加密
(1).安全哈希算法(Secure Hash Algorithm)主要适用于数字签名标准(Digital Signature Standard DSS)
引用commons-codec-1.10.jar包或者导入POM依赖
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.10</version>
</dependency>
(1).普通加密(不建议使用)
String str =”password”;
String sha1Str = DigestUtils.sha1Hex(str);
System.out.println(“SHA1–>” + sha1Str);
(2).加盐参照以上
(3).注:java的security提供了该加密的方法(加盐)
/**
* sha1加密
* @param data
* @return
* @throws NoSuchAlgorithmException
*/
public static String sha1(String data) throws NoSuchAlgorithmException {
//加盐 更安全一些
data += "lyz";
//信息摘要器 算法名称
MessageDigest md = MessageDigest.getInstance("SHA1");
//把字符串转为字节数组
byte[] b = data.getBytes();
//使用指定的字节来更新我们的摘要
md.update(b);
//获取密文 (完成摘要计算)
byte[] b2 = md.digest();
//获取计算的长度
int len = b2.length;
//16进制字符串
String str = "0123456789abcdef";
//把字符串转为字符串数组
char[] ch = str.toCharArray();
//创建一个40位长度的字节数组
char[] chs = new char[len*2];
//循环20次
for(int i=0,k=0;i<len;i++) {
byte b3 = b2[i];//获取摘要计算后的字节数组中的每个字节
// >>>:无符号右移
// &:按位与
//0xf:0-15的数字
chs[k++] = ch[b3 >>> 4 & 0xf];
chs[k++] = ch[b3 & 0xf];
}
//字符数组转为字符串
return new String(chs);
}
==>测试
public static void main(String[] args) throws NoSuchAlgorithmException {
String data = "password";
String result = sha1(data);
System.out.println("加密后:"+result);
}
3.Base64的加密、解密
(1). Base64,并非安全领域下的加密解密算法。虽然经常遇到所谓的base64的加密解密。但base64只能算是一个编码算法,对数据内容进行编码来适合传输。虽然base64编码过后原文也变成不能看到的字符格式,但是方式初级又简单。
(2).引用commons-codec-1.10.jar包或者导入POM依赖
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.10</version>
</dependency>
(2)加密
final Base64 base64 = new Base64();
final String text = "字串文字";
final byte[] textByte = text.getBytes("UTF-8");
final String encodedText = base64.encodeToString(textByte);
System.out.println(encodedText);
(3).解密
System.out.println(new String(base64.decode(encodedText), “UTF-8”));
(4).注:Java 8的java.util套件中,新增了Base64的类别,可以用来处理Base64的编码与解码,用法如下
final Base64.Decoder decoder = Base64.getDecoder();
final Base64.Encoder encoder = Base64.getEncoder();
final String text = "字串文字";
final byte[] textByte = text.getBytes("UTF-8");
//编码
final String encodedText = encoder.encodeToString(textByte);
System.out.println(encodedText);
//解码
System.out.println(new String(decoder.decode(encodedText), "UTF-8"));
不足之处请谅解或告知