07-密码加盐(DES加解密/MD5)

1. 常用加密算法可以分为单向加密和双向加密。

(1)单向加密:

只提供单向加密不能解密,不可逆的过程。通常用来存储用户名和密码,直接从前端传输来存储到数据库中

(2)双向加密:又分为对称性加密算法和非对称性加密算法。
对称性加密算法,发送和接收端双方都知道秘钥和加密算法且秘钥都是相同的,之后便是对数据的加密和解密过程。
非对称加密算法 :发送之前A B事先 生成一对秘钥,A将秘钥发送给B,B将秘钥发送给 A,A先用B的秘钥加密密文在发送B,B解密,同理。

对于各种加密算法的选用:由于对称加密算法的密钥管理是一个复杂的过程,密钥的管理直接决定着他的安全性;

(1)数据量很小时 ----> 采用非对称加密算法。
(2)在实际的操作采用的方式是:
采用非对称加密算法管理对称算法的密钥,然后用对称加密算法加密数据; 这样我们就集成了两类加密算法的优点,既实现了加密速度快的优点,又实现了安全方便管理密钥的优点。

即对称加密算法加密速度快,可用于加密大量数据文件,但是一旦秘钥丢失,就可以获取数据。
非对称算法加密速度慢,可是丢失秘钥,无法推算出另一方的秘钥。

DES加密算法 -----【对称性加密算法】

DES(Data Encryption Standard)数据加密标准算法,是一种双向加密算法,也是对称性加密算法。入口参数包括:key,data,mode。key为加密秘钥,data为加密的 数据,mode为加密或解密模式。key共8个字节64位,其中有56位用于加密公钥。

工作原理:当需要加密的时候就用key对 data加密,生成密码形式的data作为输出结果,解密就需要再利用key对data进行解密获得原文密码作为输出。

特点:
对称加密算法,发送方接受方必须持有相同的秘钥才能加解密
秘钥较短,加密速度快,加密处理简单,适用于加密大量数据的场合。
加密算法是公布的,但是秘钥是未知的。
虽有极高的安全性,加密公钥只有56位,随便技术发展,秘钥长度较短存在被破解的可能性。

MD5加密算法---【单向加密】

Message-Digest-Algorithm 信息摘要算法第五代。属于Hash算法一代,是一种单向加密算法,可以将输入的信息加密转换为128位固定长度的散列值,用于检验数据传输过程中的完整性。

功能:

输入任意长度的信息,经过处理,输出都是128位的信息值
不同的输入对应的输出一定不同,保证唯一性
争议:

MD5属不属于加密算法,因为只可以加密,无法获得密码原文,只能属于算法。
另一种观点,正因为看不到原文,使得原文得到加密处理。
个人观点:对于公司的用户,采用MD5是可以放心的,第一,对于黑色截获MD5后很难破解。第二,对于商家内部,只能获得用户加密后的密文,无法看到用户的真实密码,这也是对用户信息的一定保护。
MD5的优势:
防止被篡改,在传输过程中一旦被串改,那么计算出的MD5值一定不同。
计算速度快。加密速度快,不需要秘钥。
检查文件的完整性,一旦文件被更改,MD5值也是不同的。
防止看到明文,公司存放密码存放的是MD5值。
防止抵赖,用于数字签名,一旦用户的文件被第三方MD5加密,若以后A说这个文件不是他写的,那么当用文件MD5后获得的签名一致,可以确认。

MD5的实现原理:
填充:将输入信息进行512求余分组,若不等于448,那么进行填充 1 和0,一个1 N个0。最后的数据就为N*512+448
记录信息长度:将得到的信息用64位存储填充之前的信息长度,这样448+64=512,总信息为N+1个512
以四个常数ABCD与每组512位进行函数运算,最后输出的结果就是4组32位的常数。拼接得到MD5码
MD5的缺点:
作为一种散列算法,虽然很难发生散列碰撞,但是经过证实,仍然存在两种不同数据会发生碰撞。
MD5的安全性:将用户的密码直接MD5后存储在数据库是不安全的。第一,用户普遍习惯用容易记忆的密码,生日,手机号等,黑客容易破译此类密码。这也是加盐值的一个原因。第二,直接MD5存入数据库,若数据库被破解,通过MD5反查会查到密码,需要随机盐值的配合。
考虑到多数人所使用的密码为常见的组合,攻击者可以将所有密码的常见组合进行单向哈希,得到一个摘要组合,然后与数据库中的摘要进行比对即可获得对应的密码。这个摘要组合也被称为rainbow table。

SHA1加密算法----【单向加密】

SHA-1是一种数据加密算法,该算法的思想是接收一段明文,然后以一种不可逆的方式将它转换成一段(通常更小)密文,也可以简单的理解为取一串输入码(称为预映射或信息),并把它们转化为长度较短、位数固定的输出序列即散列值(也称为信息摘要或信息认证代码)的过程。

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

RSA加密算法--【非对称加密算法】

RSA是一种非对称加密算法。目前最有影响力的公钥加密算法,该算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但那时想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥,即公钥,而两个大素数组合成私钥。公钥是可发布的供任何人使用,私钥则为自己所有,供解密之用。

解密者拥有私钥,并且将由私钥计算生成的公钥发布给加密者。加密都使用公钥进行加密,并将密文发送到解密者,解密者用私钥解密将密文解码为明文。

相对于DES优缺点:非对称算法,加密程度更高。但是对应的加密速度慢几个数量级。

————————————————

1 . 第一种 DES加解密( DES是一种对称加密算法)

import java.security.Key;
import java.security.SecureRandom;
 
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
 
/**
 * DES是一种对称加密算法,所谓对称加密算法:加密和解密使用相同的秘钥的算法
 * @author llp
 *
 */
public class DESUtil {
    private static final Logger logger = LoggerFactory.getLogger(DESUtil.class);
 
    private static Key key;
    //设置秘钥key
    private static String KEY_STR="myKey";
    private static String CHARSETNAME="UTF-8";
    private static String ALGORITHM="DES";
    
    static{
        try{
            //生成DES算法对象
            KeyGenerator generator=KeyGenerator.getInstance(ALGORITHM);
            //运用SHA1安全策略
            SecureRandom secureRandom=SecureRandom.getInstance("SHA1PRNG");
            //设置上密钥种子
            secureRandom.setSeed(KEY_STR.getBytes());
            //初始化基于SHA1的算法对象
            generator.init(secureRandom);
            //生成密钥对象
            key=generator.generateKey();
            generator=null;
        }catch(Exception e){
            throw new RuntimeException(e);
        }
    }
    
    /**
     * 获取加密的信息
     * @param str
     * @return
     */
    public static String getEncryptString(String str){
        //基于BASE64编码,接收byte[]并转换成String
        BASE64Encoder base64Encoder=new BASE64Encoder();
        try {
            // 按UTF8编码
            byte[] bytes = str.getBytes(CHARSETNAME);
            // 获取加密对象
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            // 初始化密码信息
            cipher.init(Cipher.ENCRYPT_MODE, key);
            // 加密
            byte[] doFinal = cipher.doFinal(bytes);
            // byte[]to encode好的String并返回
            return base64Encoder.encode(doFinal);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    
    /**
     * 获取解密之后的信息
     * 
     * @param str
     * @return
     */
    public static String getDecryptString(String str) {
        // 基于BASE64编码,接收byte[]并转换成String
        BASE64Decoder base64decoder = new BASE64Decoder();
        try {
            // 将字符串decode成byte[]
            byte[] bytes = base64decoder.decodeBuffer(str);
            // 获取解密对象
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            // 初始化解密信息
            cipher.init(Cipher.DECRYPT_MODE, key);
            // 解密
            byte[] doFinal = cipher.doFinal(bytes);
            // 返回解密之后的信息
            return new String(doFinal, CHARSETNAME);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    
    public static void main(String[] args) {
        //加密
        logger.info(getEncryptString("root"));//WnplV/ietfQ=
        logger.info(getEncryptString("123456"));//QAHlVoUc49w=
        //解密
        logger.info(getDecryptString(getEncryptString("root")));//root
        logger.info(getDecryptString(getEncryptString("123456")));//123456
    }
}

2. 第二种 MD5(单向加密算法)

import java.security.MessageDigest;
/**
 * MD5加密
 * @author llp
 *
 */
public class MD5 {
 
    /**
     * 对传入的String进行MD5加密
     * 
     * @param s
     * @return
     */
    public static final String getMd5(String s) {
        // 16进制数组
        char hexDigits[] = { '5', '0', '5', '6', '2', '9', '6', '2', '5', 'q', 'b', 'l', 'e', 's', 's', 'y' };
        try {
            char str[];
            // 将传入的字符串转换成byte数组
            byte strTemp[] = s.getBytes();
            // 获取MD5加密对象
            MessageDigest mdTemp = MessageDigest.getInstance("MD5");
            // 传入需要加密的目标数组
            mdTemp.update(strTemp);
            // 获取加密后的数组
            byte md[] = mdTemp.digest();
            int j = md.length;
            str = new char[j * 2];
            int k = 0;
            // 将数组做位移
            for (int i = 0; i < j; i++) {
                byte byte0 = md[i];
                str[k++] = hexDigits[byte0 >>> 4 & 0xf];
                str[k++] = hexDigits[byte0 & 0xf];
            }
            // 转换成String并返回
            return new String(str);
        } catch (Exception e) {
            return null;
        }
    }
 
    public static void main(String[] args) {
        System.out.println(MD5.getMd5("123456"));//s05bse6q2qlb9qblls96s592y55y556s
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容