通过UUID、SHA-1、Base64组合加密

该篇文章实现的最终效果是:

1)加密是不可逆的。

2)相同字符串加密产生后的字符串都不一样

3)所以要想比较两个字符串是否相等,需要用已经加过密的字符串进行处理后,在与另一个字符串比较。

下面直接代码演示:

加密工具类

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.UUID; import org.apache.commons.codec.binary.Base64; import cn.edu.zju.grs.alufer.exception.InvalidParameterException; /**
* 加密工具类
*/
public class EncryptionUtil { /**
* 先生成一个10位的随机字符串(这个随意)
*/
public static String dealPassword(String password) throws UnsupportedEncodingException {
String salt = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 10);
System.out.println(salt+"---111111");
try { // salt.getBytes("UTF-8"):字符串转成UTF-8的字节数组
return dealPasswordWithSalt(password, salt.getBytes("UTF-8"));
} catch (InvalidParameterException e) {
e.printStackTrace();
}
return null;
} /**
* 通过SHA-1和Base64处理之后,给字符串数据加密在返回字符串
*/
public static String dealPasswordWithSalt(String password, byte[] salt)
throws InvalidParameterException, UnsupportedEncodingException {
if (password == null)
throw new InvalidParameterException("Parameter is null"); // 将两个数组合2为1
byte[] msg = byteCat(password.getBytes("UTF-8"), salt);
String dealedPassword = null; /*
* MessageDigest 类为应用程序提供信息摘要算法的功能,如 MD5 或 SHA 算法。
* 信息摘要是安全的单向哈希函数,它接收任意大小的数据,并输出固定长度的哈希值。
*/
MessageDigest md;
try { // 返回实现指定摘要算法的 MessageDigest
// 对象。MessageDigest是java自带加密工具类,通过SHA-1加密,也可以采用MD5
md = MessageDigest.getInstance("SHA-1"); // 使用指定的 byte 数组更新摘要。
md.update(msg); // 通过执行诸如填充之类的最终操作完成哈希计算。digest 方法只能被调用一次。在调用 digest
// 之后,MessageDigest 对象被重新设置成其初始状态。
byte[] dig = md.digest(); // 在合2为1
byte[] passb = byteCat(dig, salt); // 最后通过BASE64算法转换二进 制数据为ASCII字符串格式。
dealedPassword = new String(Base64.encodeBase64(passb));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return dealedPassword;
} /**
* 这个方法的目的是将两个数组合成一个数组
*/
private static byte[] byteCat(byte[] l, byte[] r) {
byte[] b = new byte[l.length + r.length];
System.arraycopy(l, 0, b, 0, l.length);
System.arraycopy(r, 0, b, l.length, r.length);
return b;
} /**
* 通过上面生成的字符串来进行解密,其最终目的就是获得上面随机生成的UUID
* 这样只要你password一致,UUID一致,那dealPasswordWithSalt方法产生的加密字符串就会一致
*/
public static byte[] getSalt(String dealedPassword) throws InvalidParameterException { /*
* 解码:这里获得的是上面passb数组,因为SHA-1是固定20个字节,所以从20位置开始截取,MD516个字节。
*/
byte[] decoded = Base64.decodeBase64(dealedPassword);
byte[][] bs = null;
bs = byteSplit(decoded, 20);
byte[] salt = bs[1];
System.out.println(new String(salt)+"---222222");
return salt;
} /**
* 将数组1分为2,其实就是获得上面uuid所产生的数组
* 第一个数组是上面dig数组,第二个是salt数组
*/
private static byte[][] byteSplit(byte[] src, int n) {
byte[] l, r;
if (src == null || src.length <= n) {
l = src;
r = new byte[0];
} else {
l = new byte[n];
r = new byte[src.length - n];
System.arraycopy(src, 0, l, 0, n);
System.arraycopy(src, n, r, 0, r.length);
}
byte[][] lr = { l, r };
return lr;
} }

 

测试类

import java.io.UnsupportedEncodingException;

import cn.edu.zju.grs.alufer.exception.InvalidParameterException;

public class Test {

public static void main(String[] args) {
try {
try { //模拟获得用户注册的密码
String password="zhang123456"; //通过加密获得的密码,存放到数据库
String plusPassword = EncryptionUtil.dealPassword(password);
System.out.println("加密后:"+plusPassword); //模拟用户登录
String loginpassword="zhang123456";
String LessPassword= EncryptionUtil.dealPasswordWithSalt(loginpassword,EncryptionUtil.getSalt(plusPassword));
System.out.println("在加密:"+LessPassword); System.out.println(plusPassword.equals(LessPassword));
} catch (InvalidParameterException e) {
e.printStackTrace();
} } catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
/**
* 总结:
* 1:通过UUID有个最大的好处就是它会产生随机数,所以你同样的两个字符串它的加密后结果是不一样的,
* 你要解密,那你首先要做的是要先得到那个UUID字符串,在进行加密,才会之前的加密字符串一致
*
*/
}

看后台打印:

看上面的例子,如果你对System.arraycopy()不是很了解,可以看这篇博客:

使用System.arraycopy()实现数组之间的复制

它对里面的参数做了详细讲解。

总结下

加密过程

1)将用户前段传入的password传入加密方法中。

2)加密方法先通过UUID随机生成字符串,可以理解为salt。

3)将password和salt都转为byte[],在通过system.arrayCopy方法变成一个byte[]

4)将上面的byte[]进行SHA-1加密,之后在于salt组成的byte[],组成一个新的byte[](也就是说这个salt在加密过程中使用了两次,第二次是为解密用的)

5)在通过Base64进行加密。

 解密过程

解密过程的关键就是要获得加密过程的salt。

1)通过Base64.decodeBase64将数据的密码转为byte数组。

2)截取byte数组20个字节后的字节(因为SHA-1是固定20个字节,那么剩下的就是盐了)

3) 只要获得盐,那就把用户登录的密码和盐再加密一次,和数据库的密码一样就代码验证通过。

MD5  和 SHA-1的区别

最后说下:MD5  和 SHA-1  的一些区别:

由于MD5与SHA-1均是从MD4发展而来,它们的结构和强度等特性有很多相似之处

因为二者均由MD4导出,SHA-1和MD5彼此很相似。相应的,他们的强度和其他特性也是相似,但还有以下几点不同:
1. 对强行攻击的安全性:最显著和最重要的区别是SHA-1摘要比MD5摘要长32 位。使用强行技术,产生任何一个报文使其摘要等于给定报摘要的难度对MD5是2^128数量级的操作,而对SHA-1则是2^160数量级的操作。这样,SHA-1对强行攻击有更大的强度。
2. 对密码分析的安全性:由于MD5的设计,易受密码分析的攻击,SHA-1显得不易受这样的攻击。
3. 速度:在相同的硬件上,SHA-1的运行速度比MD5慢。

4. MD5最后生成的摘要信息是16个字节,SHA1是20个字节。

想的太多,做的太少,中间的落差就是烦恼,要么去做,要么别想 少尉【19】

【Java提高】---通过UUID、SHA-1、Base64组合加密的更多相关文章

  1. java提高篇(九)-----实现多重继承

    多重继承指的是一个类可以同时从多于一个的父类那里继承行为和特征,然而我们知道Java为了保证数据安全,它只允许单继承.有些时候我们会认为如果系统中需要使用多重继承往往都是糟糕的设计,这个时候我们往往需 ...

  2. java提高篇(四)-----理解java的三大特性之多态

    面向对象编程有三大特性:封装.继承.多态. 封装隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据.对外界而已它的内部细节是隐藏的,暴露给外界的只是它的访问方法. 继承 ...

  3. Java提高篇——Java实现多重继承

    多重继承指的是一个类可以同时从多于一个的父类那里继承行为和特征,然而我们知道Java为了保证数据安全,它只允许单继承.有些时候我们会认为如果系统中需要使用多重继承往往都是糟糕的设计,这个时候我们往往需 ...

  4. 生成Base58格式的UUID(Hibernate Base64格式的UUID续)

    Base58简介 Base58采用的字符集合为“123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ”,从这不难看出,Base58是纯数 ...

  5. java提高篇(三)-----理解java的三大特性之多态

    面向对象编程有三大特性:封装.继承.多态. 封装隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据.对外界而已它的内部细节是隐藏的,暴露给外界的只是它的访问方法. 继承 ...

  6. java提高篇(八)-----实现多重继承

    多重继承指的是一个类可以同时从多于一个的父类那里继承行为和特征,然而我们知道Java为了保证数据安全,它只允许单继承.有些时候我们会认为如果系统中需要使用多重继承往往都是糟糕的设计,这个时候我们往往需 ...

  7. 1.Java 加解密技术系列之 BASE64

    Java 加解密技术系列之 BASE64 序号 背景 正文 总结 序 这段时间,工作中 用到了 Java 的加解密技术,本着学习的态度,打算从这篇文章开始,详细的研究一番 Java 在加解密技术上有什 ...

  8. Java提高篇——对象克隆(复制)

    假如说你想复制一个简单变量.很简单: int apples = 5; int pears = apples; 不仅仅是int类型,其它七种原始数据类型(boolean,char,byte,short, ...

  9. Java提高篇(三三)-----Map总结

    在前面LZ详细介绍了HashMap.HashTable.TreeMap的实现方法,从数据结构.实现原理.源码分析三个方面进行阐述,对这个三个类应该有了比较清晰的了解,下面LZ就Map做一个简单的总结. ...

随机推荐

  1. 联想功能 Jquery autocomplete.js输入框联想补全功能

    转载地址:https://www.cnblogs.com/jinzhiming/p/6768402.html

  2. hive 优化方法

    https://blog.csdn.net/jiangsanfeng1111/article/details/52847044 -- 高级优化 使用各种函数hive>show functions ...

  3. 使用kbmmw 生成客户端delphi函数原型

    前面我们讲了使用swagger 生成java,php 的客户端调用函数原型. 对于delphi,其实很遗憾,不能直接生成客户端函数原型代码. 不要紧,解铃还须系铃人,既然是kbmmw 自己生成的,我们 ...

  4. 小白的CTF学习之路3——二进制数据基础与运算(下)

    处理了二进制的整数运算,下面我们来进行令人绝望的浮点数运算 我们先来看一下float事列程序: #include<"stdio.sh"> int main() { fl ...

  5. vue学习_01

    一.什么是VUE 渐进式的前端框架,MVVM(Model,view,viewmodel)模式,饿了么用的就是vue框架 二.VUE基本语法 1.引入vue: <script src=" ...

  6. shiro简单配置 (写的不错 收藏一下)

    抄袭的连接:https://blog.csdn.net/clj198606061111/article/details/24185023 注:这里只介绍spring配置模式. 因为官方例子虽然中有更加 ...

  7. 15. Life Cycle of the Products 产品的生命周期

    15. Life Cycle of the Products 产品的生命周期 (1) We can see how the product life cycle works by looking at ...

  8. 编写shell脚本kill掉占用cpu超过90%以上的程序

    由于集群用户经常会不懂如何提交作业,将作业直接运行到登录节点上,这样导致登录节点的cpu及内存占用很大,导致其他用户甚至无法登录.所以就想到了一种解决方法,写一个shell脚本,常驻登录节点,监控cp ...

  9. AlphaGo原理浅析

    一.PolicyNetwork(走棋网络) 首先来讲一下走棋网络.我们都知道,围棋的棋盘上有19条纵横交错的线总共构成361个交叉点,状态空间非常大,是不可能用暴力穷举的方式来模拟下棋的.但是我们可以 ...

  10. c语言构建哈希表

    /*哈希查找 *哈希函数的构造方法常用的有5种.分别是: *数字分析法 *平方取中法 *分段叠加 *伪随机数 *除留取余法 *这里面除留取余法比较常用 *避免哈希冲突常用的方法有4种: *开放定址法( ...