MD5、AES、Jasypt加密方式的简要介绍与对比

您所在的位置:网站首页 md5加密结果一样 MD5、AES、Jasypt加密方式的简要介绍与对比

MD5、AES、Jasypt加密方式的简要介绍与对比

2023-11-10 21:31| 来源: 网络整理| 查看: 265

MD5、AES、Jasypt加密方式的简要介绍与对比 1 前言

目前做的项目中用的加密工具有:MD5、AES加密工具(旧的)及Jasypt加密工具(新增),对这三种加密工具的简要原理和应用做了整理。内容参考的文章见第6部分。如下是各工具在系统中的应用:

MD5: 主要用在系统用户名密码的加密上AES:除数据库密码解密外、系统用于密码等所有的均使用该加密工具:redis、邮件、账户等Jasypt:目前只计划实现数据库密码的加解密,配合实现数据库自动化运维 2 MD5加密算法 2.1简介 MD5信息摘要算法,一种被广泛使用的密码散列函数,可以产生出一个128位的散列值,用于确保信息传输完整一致。MD5常用于防止数据被篡改、防止直接存储明文、防止抵赖(数字签名) 2.2 原理 加密要素 明文信息(即不需要秘钥之类的加密要素) 唯一性 通过密码散列函数产生输入信息对应的128位的散列值,同一份信息原文计算后的散列值一定是一样的;所以通过对比两个散列值是否一样可以判断原文信息是否被篡改;但理论上来说一个MD5是可能对应无数多个原文,但是在实际现实应用中,原文长度有限,在某个范围内让两个原文对应上同一个MD5是非常困难。 不可逆性 密码散列函数:散列(哈希)函数的一种,即可以解释为一种单向函数,很难从函数的输出结果推出它的输入是什么;算法计算过程中原文的部分信息是丢失的,所以无法将一个MD5密文进行解密(所以从解密角度看,MD5不算一个加密算法)。 2.3 应用范围 防止数据被篡改

比如在发送文件前,先传输文件使用MD5生成的MD5值,再传输文件,通过对收到的文件生成的MD5值与之前的MD5值对比来判断是否文件在传输过程中被篡改

避免直接存储明文

保存用户密码,这样即使数据库中的密码数据信息被泄露出去,也无法通过解密获得密码原文; 但是对于用户,系统根据用户输入的密码用MD5再次产生MD5值,和数据库的数据进行比较是否一致来确定用户输入的密码的合法性

数字签名

利用唯一性,例如A写了一个文件,认证机构用MD5产生摘要信息保存,只要再次对这个文件用MD5生成摘要信息,和原先保存的那份摘要信息一对比,只要一致,就证明是A写的那个文件,A无法抵赖

2.4 安全性上的问题 暴力破解风险

MD5虽然无法逆向解密,但是却可以“正向暴力破解”。 尽管暴力破解很费时间,但对于诸如密码的加密存储,往往若密码过短过简单则容易被暴力破解。很多在线工具提供通过密文匹配对应输入的原文。如后面示例,其中的一个简单密码就存在这个库中,很轻松就被找出来:

简单密码:用MD5生成password123456的MD5值, 用这个MD5值去查询,可以查询到原文 在这里插入图片描述 在这里插入图片描述

复杂密码:用MD5生成哈哈哈XSWL2333的MD5值, 用这个MD5值去查询,则目前这个在线工具还无法匹配到这个结果的原文

在这里插入图片描述 在这里插入图片描述

破解原理

实际上上述的“暴力破解”不是简单的一个一个去生成MD5值再去比较,也不是“字典法”预先构建一个庞大的明文->密文的库,而是在字典法上改进的构建彩虹表的方式。 但都本质都是通过输入MD5值得方式查找对应的原文。

安全规避方式

因此MD5应用在例如密码加密中,对于密码的要求应该不能过于简单,所以密码的设置不应过于简单; 常见的要求就是大小写字母+数字+字符,四选三来组成密码(公司手册对员工门户、个人电脑的密码要求就是如此)

2.5 项目中的应用 用于用户密码的加密,包括对用户密码加密后存储以及登录效验用户密码是否正确封装了MD5Util工具类,提供三个加密方法直接调用: 字节数据的加密:getMD5(byte[] bytes) 字符串数据的加密:getMD5(String str) 文件的加密:getFileMD5(File file) /** * MD5信息-摘要算法5,是一种单向加密算法(不可逆) */ public final class MD5Util { //用来将字节转换成16进制表示的字符 private static char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; /** * 私有构造函数,防止实例化使用 */ private MD5Util() {} /** * 对参数进行MD5加密 * @param bytes 要加密的参数 * @return MD5值 */ public static String getMD5(byte[] bytes) { String result = null; MessageDigest md = null; try { md = MessageDigest.getInstance("MD5"); md.update(bytes); byte[] temp = md.digest(); //MD5的计算结果是一个128位长整数,用字节表示就是16字节 char[] chars = new char[32]; //每个字节用16进制表示的话,需要2个字符,所以共32个字符 //对MD5的每个字节转换成16进制的字符 int k = 0; for (int i = 0; i e.printStackTrace(); } return result; } /** * 对参数进行MD5加密 * @param str 要加密的参数 * @return MD5值 */ public static String getMD5(String str) { try { return getMD5(str.getBytes("GBK")); } catch (UnsupportedEncodingException e) { throw new AppException("MD5加密异常", e); } } /** * 计算文件的MD5加密值,注意如果文件较大、计算MD5时可能性能较差 * @param file 文件 * @return MD5值 */ public static String getFileMD5(File file) { FileInputStream in = null; String result = null; try { MessageDigest md = MessageDigest.getInstance("MD5"); in = new FileInputStream(file); byte[] buffer = new byte[1024]; while (in.read(buffer) != -1) { md.update(buffer); } BigInteger bigInt = new BigInteger(1, md.digest()); result = bigInt.toString(16); } catch (Exception e) { throw new AppException("MD5加密异常", e); } finally { try { if (in != null) { in.close(); } } catch (Exception e) { throw new AppException("MD5加密时,流关闭异常", e); } } return result; } /** * 计算文件的MD5加密值 * @param fileName 文件名 * @return MD5值 */ public static String getFileMD5(String fileName) { File file = new File(fileName); return getFileMD5(file); } } 3 AES加密算法 3.1 简介 高级加密标准(AES,Advanced Encryption Standard)采用同一个秘钥进行加解密,是一种对称秘钥加密算法,加解密需要秘钥和密文/明文 3.2 原理 加密要素 明文/密文秘钥 加解密过程

在这里插入图片描述

是一种对称加密算法:即加解密使用的是同一个秘钥,对于同一个明文,用这个秘钥加密出来的密文是一样的;反过来,相同的密文用这个秘钥解密出的结果一定是最开始的明文

什么是非对称加密算法?加解密的秘钥是不同的,例如公钥加密,只有私钥能解密。但算法复杂,加解密速度慢。

3.3 应用 因为是对称加密,所以加密速度快,适合大量数据的加密,且加密的数据可复原所以应用场景广泛,例如用户信息,实时通信的敏感信息等 3.4 安全性上的问题 安全性 速度快,安全级别高:目前是最安全的加密算法之一但不是绝对安全,要保证你的秘钥不被泄露,因为AES是对称加密算法,只需要知道秘钥就能解密处所有的加密算法; 安全规避方式 对于系统,秘钥往往写在代码里,所以如果说源代码和数据库数据泄露,那么数据就完全暴露给不法分子,若不法分子只有密文,没有秘钥,那么至少被加密的敏感数据不会被利用。 所以数据加密了并不代表就万无一失。因此公司有诸如不应该把源代码传到外网等规定,目的之一就是为了防止源代码泄露导致重要或敏感数据泄露 3.5 系统中的应用 redis、邮件、Eterm账户等密码或其他信息的加密,应用最多封装工具类:AESUtil 私有构造函数:制定加密算法,生成Key加解密只需要密文/明文,返回结果加密:getEncString(String str)解密:getDesString(String str) /** * AES加密算法,采用同一个密钥进行加解密,是一种对称密钥加密算法。 */ public final class AESUtil { //自己定义的秘钥,128bit即16位的随机串。也支持192,25bit,长度越长安全性越高,对应的加解密时间越长 private final static String KEY_STR = "gOZ+l59TRoBajn3G"; private final Key key; private static AESUtil instance = new AESUtil(); private static final String ALGORITHM = "AES"; private static final String RANDOM_ALGORITHM = "SHA1PRNG"; /** * 私有构造函数,防止通过实例化使用 */ private AESUtil() { try { KeyGenerator generator = KeyGenerator.getInstance(ALGORITHM);//Java的秘钥生产器,使用的是AES SecureRandom random = SecureRandom.getInstance(RANDOM_ALGORITHM);//随机数的算法,NativePRNG和SHA1PRNG random.setSeed(KEY_STR.getBytes("GBK"));//用我们设定的秘钥串作为随机数的种子,因为种子是我们固定的,产生的随机数也是固定的 generator.init(random); key = generator.generateKey();//生成的秘钥,我们在加密解密需要用到相同秘钥 } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) { throw new AppException("AES构造函数异常", e); } } public static AESUtil getInstance() { return instance; } /** * 对byte[]参数进行加密 * @param bytes 要加密的参数 * @return 加密后的参数 */ private byte[] getEncCode(byte[] bytes) { byte[] result = null; Cipher cipher = null; try { cipher = Cipher.getInstance("AES");//获取算法实例 cipher.init(Cipher.ENCRYPT_MODE, key);//初始化,入参为加密模式和秘钥 result = cipher.doFinal(bytes);//进行加密 } catch (Exception e) { throw new AppException("AES加密异常", e); } finally { cipher = null; } return result; } /** * 对byte[]参数进行解密 * @param bytes 要解密的参数 * @return 解密后的参数 */ private byte[] getDesCode(byte[] bytes) { byte[] result = null; Cipher cipher = null; try { cipher = Cipher.getInstance("AES");//获取算法实例 cipher.init(Cipher.DECRYPT_MODE, key);//初始化,入参为解密模式和秘钥 result = cipher.doFinal(bytes);//进行解密 } catch (Exception e) { throw new AppException("AES解密异常", e); } finally { cipher = null; } return result; } /** * 对string参数进行加密 * @param str 要加密的参数 * @return 加密后的参数 */ public String getEncString(String str) { BASE64Encoder base64en = new BASE64Encoder(); byte[] input = null; //明文 byte[] output = null; //密文 String result = null; try { input = str.getBytes(CommonConstant.CHARSET_NAME); output = getEncCode(input); result = base64en.encode(output); } catch (Exception e) { throw new AppException("AES解密异常,参数:" + str, e); } finally { input = null; output = null; } return result; } /** * 对String参数进行解密 * @param str 要解密的参数 * @return 解密后的参数 */ public String getDesString(String str) { BASE64Decoder base64De = new BASE64Decoder(); byte[] input = null; //密文 byte[] output = null; //明文 String result = null; try { input = base64De.decodeBuffer(str); output = getDesCode(input); result = new String(output, CommonConstant.CHARSET_NAME); } catch (Exception e) { throw new AppException("AES解密异常,参数:" + str, e); } finally { input = null; output = null; } return result; } } 4 Jasypt加密工具 4.1 简介

Jasypt是一个开源的java库,只需要引入组件就可以使用,开发中无需关注其太多细节即可实现java项目的加密功能; 也因此很难找到相关的资料,因此原理也基本是自己使用和测试结果的总结,不一定严谨。

4.2 原理 加密要素

密文/明文:password 系统钥: sysKey 秘钥:secretKey

加密机制 一套sysKey和secretKey生产的密文是“动态”的(即同一个明文每次加密后的结果不一样); 但这些密文用这一套sysKey和secretKey解密处的结果都一样;同一套sysKey、secretKey加密后的密文是“固定”的; (准确说不是由这一套加密出来的密文解密不出东西,会报错)同一系统拥同一套sysKey和secretKey(目前仅是公司DBA那边的规定)加解密需要三个加密要素,直接调用,无需其他步骤 4.3 应用范围 密码、敏感数据、甚至文件、应用程序因为无需关注其细节,容易使用,很适合在java项目中实现基本的加密要求 4.4 安全性上的问题 安全规避方式 和AES都是对称加密算法的一种,一样要保证secretKey和sysKey的安全和AES有点不一样的是,Jasypt加解密需要sysKey和secretKey,所以在系统中使用时,要避免将这两者放在一起,例如都写在一个配置文件 4.5 系统中的应用 目前主要用于数据库连接,对数据库密码的加密,配合公司对数据库安全的要求。password和sysKey由DBA管理提供,自助下载secretKey 由DBA提供(配合Apollo配置中心可以实现开发人员无法接触到secretKey,在一些安全管理实践上很方便)封装工具类JasyptForDbUtil 使用到原生工具:JasyptUtil(直接调用,无需其他步骤) public String encryptString(String sysKey, String secretKey, String str) public String decryptString(String sysKey, String secretKey, String encString)秘钥写在代码里,与sysKey和密文分开,避免都在一个地方 private final static String SECRET_KEY = “aSecretKey”;加密:public String getEncStr(String sysKey, String plainText)解密:public String getDesStr(String sysKey, String cipherText) /** * Jasypt 加密算法,用于数据库密码加解密 * 加解密需要 sysKey、secretKey、密文或明文 * 加密生成的密码是动态的,但与同一组sysKey、secretKey是对应的 */ public final class JasyptUtil { /** * 秘钥,不同系统的秘钥不同 * 秘钥与配置文件密文分开,避免都在一个地方 */ private final static String SECRET_KEY = "mySrcretKey"; private static com.mytest.jasypt.util.JasyptUtil jasyptUtil = new com.mytest.jasypt.util.JasyptUtil(); private static JasyptUtil instance = new JasyptUtil(); public static JasyptUtil getInstance() { return instance; } /** * 私有构造函数,防止通过实例化使用 */ private JasyptUtil() { } /** * Jasypt 加密 * @param sysKey sysKey * @param plainText 要加密的明文 * @return 加密后的字符串 */ public String getEncStr(String sysKey, String plainText) { try { return jasyptUtil.encryptString(sysKey, SECRET_KEY, plainText); } catch (Exception e) { throw new AppException("Jasypt加密异常" + e); } } /** * Jasypt 解密 * @param sysKey sysKey * @param cipherText 要解密的密文 * @return 解密密后的字符串 */ public String getDesStr(String sysKey, String cipherText) { try { return jasyptUtil.decryptString(sysKey, SECRET_KEY, cipherText); } catch (Exception e) { throw new AppException("Jasypt解密异常" + e); } } } 4.6延伸:实现对配置文件属性的解密(使用Jasypt)

系统中加密工具一个重要的应用是对一些配置文件的信息进行解密,例如数据库连接的密码使用密文保存在配置文件中,需要解密后使用

1 读取配置文件,对配置文件属性进行解密并重置操作

重写PropertyResourceConfigurer类的convertProperties方法,启动时执行该方法,读取配置文件所有属性,并解密重设需解密的属性值; 该方法由PropertyResourceConfigurer自身提供缺省实现,用于对属性值做必要的转换处理,缺省不做任何处理; 是否解密通过是否存在同名属性名+.encode,属性值为对应加密算法,根据配置的加密算法值使用对应加密工具进行解密 伪代码

@Override protected void convertProperties(Properties props) { //获取所有配置文件属性信息 Enumeration propertyNames = props.propertyNames(); while (propertyNames.hasMoreElements()) { //循环这些属性 if (name.endsWith(".encode")) { value = props.getProperty(name); //获取加密算法,看采用哪种加密工具进行解密 name = name.substring(0, name.indexOf(".encode")); //找待解密参数名 value = decode(name, value, props); //进行解密,获取解密后的参数值 props.setProperty(name, value);//用解密结果重设属性值 } } } 2 修改相关配置文件 classpath:public.properties classpath:jdbc.properties classpath:redis.properties # public.properties配置文件 # jasypt加密使用到的sysKey,同一系统sysKey相同 jasypt.sysKey=sysKey串 # jdbc.properties配置文件 oracle.name=dbname oracle.username=username oracle.password=密文 oracle.password.encode=JASYPT 6 参考资料 MD5算法原理及实现密码散列函数MD5在线解密工具彩虹表AES加密算法的详细介绍与实现java实现AES


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3