zoukankan      html  css  js  c++  java
  • 【Java提高】---通过UUID、SHA-1、Base64组合加密

    通过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】

  • 相关阅读:
    武汉科技大学ACM :1004: 零起点学算法74——Palindromes _easy version
    武汉科技大学ACM :1003: 零起点学算法14——三位数反转
    武汉科技大学ACM :1002: 零起点学算法38——求阶乘和
    武汉科技大学ACM :1001: 零起点学算法34——继续求多项式
    cos实现文件上传--推荐
    文件夹分级保存文件
    apache_fileupload实现文件上传_上传多个文件
    UEFI模式下安装Win 7系统
    武汉科技大学ACM :1008: A+B for Input-Output Practice (VIII)
    武汉科技大学ACM :1007: A+B for Input-Output Practice (VII)
  • 原文地址:https://www.cnblogs.com/qdhxhz/p/8360360.html
Copyright © 2011-2022 走看看