>获取完整摘要算法工具类代码:

[JAVA]数字摘要算法工具类——(Hamc)MD5/SHA1/SHA256/SHA512/PBKDF2

>Java实现MD5

JAVA JDK中的security包自带了MD5的加密算法,经过加密后,会生成一个128位的二进制序列。

首先导入这个包:

import java.security.MessageDigest;

然后编写主要的业务逻辑:

        try {//1.获取算法MD5实例MessageDigest md = MessageDigest.getInstance("MD5");//2.MD5加密byte[] buff = md.digest("message digest".getBytes());// "message digest" 就是密文//3.将128位的二进制编码转为32位的16进制编码String md5str = toHex(buff);//4.打印System.out.println(md5str);//输出 f96b697d7cb7938d525a2f31aaf161d0} catch (NoSuchAlgorithmException e) {e.printStackTrace();}

其中,128bin -> 32hex的方法如下:

    //将128位的二进制序列转为32位的16进制编码public static String toHex(byte[] bytes) {String md5str = "";for (int i = 0; i < bytes.length; i++) {int temp = bytes[i];if (temp < 0) temp += 256; // 0x8* 在经过toHexString转化时,会被转为ffffff8*,需要+256保证其正值if (temp < 16) md5str += "0"; // 0x05 转化会变成 5,缺少一位0md5str+=Integer.toHexString(temp);}return md5str;}

>MD5的算法

MD5的主要算法思路有三步:

  1. 补位
  2. 分组(小端排序)
  3. 循环

>补位是什么呢?

MD5将密文按512分一个大组,然后每32位分一个小组,共16小组。(也就是64字节一个大组,4个字节一个小组)。

密文总长度为len,每条密文最后要留出64位(8个字节)的长度,用于保存原数据的长度len;因此,最后一个大分组必须有448位(56字节)的补位;

举个例子,假如一个密文长度为127位(字节),由于(127%64=63)!= 48,因此,必须补到其刚好余48字节为止,也就是(64-63)+48=49个字节。

补位时,第一个字节必为0x80,其后都是0x00。(也就是第一位为1,其他位都为0)。

补位完成后,再往后面写上八个字节的长度。比如对于上面那个例子,最后8个字节要写的是7fe 00 00 00 00 00 00 00。(127 = 0x7f)

     public static BYTES fill(BYTES s){int length=s.getLength();if(s.getLength()%64!=56){s.add((byte)0x80);if(length%64<56){for(int i=0;i<56-length%64-1;i++){s.add((byte)0x00);}}else {for(int i=0;i<56+64-length%64-1;i++){s.add((byte)0x00);}}}String hex = Integer.toHexString(length);int begin=-2,end=begin+2,remain=8;while(end<hex.length()){remain--;begin=end;end+=2;if (end>hex.length())end=hex.length();byte b = (byte)(int)Integer.valueOf(hex.substring(begin,end),16);s.add(b);}for (int i=0;i<remain;i++){s.add((byte)0x00);}//System.out.println(s.getLength());return s;}

>如何分组?

共分为16组,第j组记为M[j]。每4个字节(32位)一组,组内按小端排序。

比如M[1]对应的数据是12 13 14 15,那么M[1]=0x15141312。>

    public static int[] divide(BYTES s){int[] M = new int[16];for(int i=0;i<16;i++){int a = s.getI(i*4);if(a<0)a+=256;int b = s.getI(i*4+1);if(b<0)b+=256;int c = s.getI(i*4+2);if(c<0)c+=256;int d = s.getI(i*4+3);if(d<0)d+=256;String ta="";if(a<16)ta+="0";ta+=Integer.toHexString(a);String tb="";if(b<16)tb+="0";tb+=Integer.toHexString(b);String tc="";if(c<16)tc+="0";tc+=Integer.toHexString(c);String td="";if(d<16)td+="0";td+=Integer.toHexString(d);/*System.out.println("a="+a+" "+i+" "+Integer.toHexString(a));System.out.println("b="+b+" "+i+" "+Integer.toHexString(b));System.out.println("c="+c+" "+i+" "+Integer.toHexString(c));System.out.println("d="+d+" "+i+" "+Integer.toHexString(d));*/String temp=td+tc+tb+ta;M[i]=Integer.valueOf(temp,16);}return M;}

>循环

这是MD5的核心算法,涉及到数学,就不推导了。

总之,需要定义四个链接常量:

int A=0x67452301;
int B=0xefcdab89;
int C=0x98badcfe;
int D=0x10325476;

四个非线性函数:

    public static int F(int X,int Y,int Z){return (X&Y)|((~X)&Z);}public static int G(int X,int Y,int Z){return (X&Z)|(Y&(~Z));}public static int H(int X,int Y,int Z){return X^Y^Z;}public static int I(int X,int Y,int Z){return Y^(X|(~Z));}

四个循环函数:

    public static int FF(int a,int b,int c,int d,int Mj,int s,int ti){return b + ((a + F(b, c, d) + Mj + ti) << s);}public static int GG(int a,int b,int c,int d,int Mj,int s,int ti){return b + ((a + G(b, c, d) + Mj + ti) << s);}public static int HH(int a,int b,int c,int d,int Mj,int s,int ti){return b + ((a + H(b, c, d) + Mj + ti) << s);}public static int II(int a,int b,int c,int d,int Mj,int s,int ti){return b + ((a + I(b, c, d) + Mj + ti) << s);}

接着,进行N=sLength/64次大循环,其中sLength是补位后的数据长度(这里的单位是字节,所以除了64)。每次循环结束后,要做一个A+=a的操作。(这部分直接结合代码看吧)

整个循环的代码为:

    public static String getMD5(BYTES s){//链接常量int A=0x67452301;int B=0xefcdab89;int C=0x98badcfe;int D=0x10325476;int a=A,b=B,c=C,d=D;int N=s.getLength()/64;for(int i=0;i<N;i++){int[] M = divide(s);//对M[j]的第一轮循环a=FF(a,b,c,d,M[0],7,0xd76aa478);b=FF(d,a,b,c,M[1],12,0xe8c7b756);c=FF(c,d,a,b,M[2],17,0x242070db);d=FF(b,c,d,a,M[3],22,0xc1bdceee);a=FF(a,b,c,d,M[4],7,0xf57c0faf);b=FF(d,a,b,c,M[5],12,0x4787c62a);c=FF(c,d,a,b,M[6],17,0xa8304613);d=FF(b,c,d,a,M[7],22,0xfd469501) ;a=FF(a,b,c,d,M[8],7,0x698098d8) ;b=FF(d,a,b,c,M[9],12,0x8b44f7af) ;c=FF(c,d,a,b,M[10],17,0xffff5bb1) ;d=FF(b,c,d,a,M[11],22,0x895cd7be) ;a=FF(a,b,c,d,M[12],7,0x6b901122) ;b=FF(d,a,b,c,M[13],12,0xfd987193) ;c=FF(c,d,a,b,M[14],17,0xa679438e) ;d=FF(b,c,d,a,M[15],22,0x49b40821);//对M[j]的第二轮循环a=GG(a,b,c,d,M[1],5,0xf61e2562);b=GG(d,a,b,c,M[6],9,0xc040b340);c=GG(c,d,a,b,M[11],14,0x265e5a51);d=GG(b,c,d,a,M[0],20,0xe9b6c7aa) ;a=GG(a,b,c,d,M[5],5,0xd62f105d) ;b=GG(d,a,b,c,M[10],9,0x02441453) ;c=GG(c,d,a,b,M[15],14,0xd8a1e681);d=GG(b,c,d,a,M[4],20,0xe7d3fbc8) ;a=GG(a,b,c,d,M[9],5,0x21e1cde6) ;b=GG(d,a,b,c,M[14],9,0xc33707d6) ;c=GG(c,d,a,b,M[3],14,0xf4d50d87) ;d=GG(b,c,d,a,M[8],20,0x455a14ed);a=GG(a,b,c,d,M[13],5,0xa9e3e905);b=GG(d,a,b,c,M[2],9,0xfcefa3f8) ;c=GG(c,d,a,b,M[7],14,0x676f02d9) ;d=GG(b,c,d,a,M[12],20,0x8d2a4c8a);//对M[j]的第三轮循环a=HH(a,b,c,d,M[5],4,0xfffa3942);b=HH(d,a,b,c,M[8],11,0x8771f681);c=HH(c,d,a,b,M[11],16,0x6d9d6122);d=HH(b,c,d,a,M[14],23,0xfde5380c) ;a=HH(a,b,c,d,M[1],4,0xa4beea44) ;b=HH(d,a,b,c,M[4],11,0x4bdecfa9) ;c=HH(c,d,a,b,M[7],16,0xf6bb4b60) ;d=HH(b,c,d,a,M[10],23,0xbebfbc70);a=HH(a,b,c,d,M[13],4,0x289b7ec6);b=HH(d,a,b,c,M[0],11,0xeaa127fa);c=HH(c,d,a,b,M[3],16,0xd4ef3085);d=HH(b,c,d,a,M[6],23,0x04881d05);a=HH(a,b,c,d,M[9],4,0xd9d4d039);b=HH(d,a,b,c,M[12],11,0xe6db99e5);c=HH(c,d,a,b,M[15],16,0x1fa27cf8) ;d=HH(b,c,d,a,M[2],23,0xc4ac5665);//对M[j]的第四轮循环a=II(a,b,c,d,M[0],6,0xf4292244) ;b=II(d,a,b,c,M[7],10,0x432aff97) ;c=II(c,d,a,b,M[14],15,0xab9423a7);d=II(b,c,d,a,M[5],21,0xfc93a039) ;a=II(a,b,c,d,M[12],6,0x655b59c3) ;b=II(d,a,b,c,M[3],10,0x8f0ccc92) ;c=II(c,d,a,b,M[10],15,0xffeff47d);d=II(b,c,d,a,M[1],21,0x85845dd1) ;a=II(a,b,c,d,M[8],6,0x6fa87e4f) ;b=II(d,a,b,c,M[15],10,0xfe2ce6e0);c=II(c,d,a,b,M[6],15,0xa3014314) ;d=II(b,c,d,a,M[13],21,0x4e0811a1);a=II(a,b,c,d,M[4],6,0xf7537e82) ;b=II(d,a,b,c,M[11],10,0xbd3af235);c=II(c,d,a,b,M[2],15,0x2ad7d2bb);d=II(b,c,d,a,M[9],21,0xeb86d391);A += a;B += b;C += c;D += d;}if(A<0)A+=256;if(B<0)B+=256;if(C<0)C+=256;if(D<0)D+=256;return Integer.toHexString(A)+" "+Integer.toHexString(B)+" "+Integer.toHexString(C)+" "+Integer.toHexString(D);}

>MD5的盐运算

MD5理论上不可能求逆,但仍经不住黑客通过暴力解法去求解。例如黑客从数据库里得到一个序列为M的经过MD5加密的密码序列,那么他可以在他本机上经过大量摘要运算,当某个字符串S的MD5计算结果等于M时,就可以知道S就是原密码了。

盐运算可以较好得预防这个情况:

  1. 每次随机一个16位的Hex序列,如0x254f58d21a,把这个序列R作为字符串,直接加到密码序列S之后,也就是S+="254f58d21a";
  2. 对这个序列做MD5,并对结果M,把后16位或你指定的某16位用序列R替换;(当然更好的方法是按某种只有你知道的方式,插入到MD5序列中,可充分保证唯一性);
  3. 验证用户密码S时,从数据库存储的MD5码提取R(你已知其如何插入或替换也就知道如何提取),然后重复1、2两步,最后与数据库中的MD5校对即可。

[JAVA][MD5]关于MD5的实现和JAVA生成MD5相关推荐

  1. Windows下生成 MD5 文件校验和的方法

    在命令提示符下 Microsoft Windows 10 操作系统中内置了一个命令行工具,作为证书服务,即"CertUtil".该命令行提供了一个开关"Hashfile& ...

  2. 账单比较java代码_Java代码比较两个文件的MD5

    比较MD5就可以知道两个文件是否一样,那为什么要知道文件一不一样呢? 有时候开发的时候自己本地环境跑的功能一切正常,到了测试环境却不行了,那有可能是测试环境的文件没有部署到最新的. 怎么判断是否最新呢 ...

  3. java digestutils_java-Apache DigestUtils似乎部分错误地计算了MD5

    今晚,我正在研究一种简单的解决方案,以便在流通过时动态进行MD5计算.主要框架可以立即正常运行.数据流化并计算了MD5-hash.但是后来我开始在3个不同阶段监视MD5-Hash.流之前,流之后和流之 ...

  4. Java生成MD5的两种方式

    1 原生的 package com.pibigstar.common.utils;import java.security.MessageDigest;/*** MD5加密工具类* @author p ...

  5. Java生成MD5值

    MD5是什么 message-digest algorithm 5(信息-摘要算法).经常说的"MD5加密",就是它→信息-摘要算法. 在下载一下东西时,经常在一些压缩包属性里,看 ...

  6. Java对于数据加密与解密的实现EncryptUtil、MD5与sha-1

    前言 假设用户在创建账户的时候,会输入账户名和密码,此时,密码会存储到数据库中.如果我们的数据库被黑客黑了,数据泄露,那么黑客就得到了数据库中所有用户的账户密码,这不安全. 如果我们对于用户的密码进行 ...

  7. java 生成md5 8位_Java生成MD5算法

    MD5即Message-Digest Algorithm 5(信息-摘要算法5),是一种用于产生数字签名的单项散列算法. MD5算法的作用是让大容量信息在用数字签名软件签私人密匙前被"压缩& ...

  8. java 大文件 md5_使用Java为大文件生成MD5非常慢

    我用nio重写你的代码,代码有点像下面: private static String generateMD5(FileInputStream inputStream){ if(inputStream= ...

  9. Java生成MD5码

    第一种 //盐,用于混交md5private static final String slat = "&%5123***&&%%$$#@";public s ...

最新文章

  1. Alibaba Cloud Linux 2.1903 LTS 64位服务器yum源下载404,Alibaba Cloud Linux 2实例中使用docker-ce、epel等YUM源安装软件失败
  2. C++/C++11中std::stack的使用
  3. 经历就是财富——总结我的26岁
  4. hbuilderx 小程序分包_基于uniapp的微信小程序之分包
  5. 使用Java和Scala将Play Framework 2应用程序部署到Openshift
  6. java上传csv文件上传_java处理csv文件上传示例详解
  7. tensorflow 模型可视化_基于tensorflow-2.x的yolov3实现
  8. java:数字转string 报空指针_超干货详解:kotlin(4) java转kotlin潜规则
  9. 零基础机器学习(2)-你的第一个Python程序
  10. python 打印对象的全部属性_详解:Python 面向对象静态方法、类方法、属性方法知识点小结...
  11. NYOJ-背包问题(贪心)
  12. 清华硕士分享思维导图:机器学习所需的数学基础
  13. 笔记.cloudflare 的橙色云代理ssl坑
  14. 嵌套查询和连接查询的效率_LeetCode 查找:groupby+having/嵌套查询/连接
  15. 最小二乘的概率解释 广义线性模型解释
  16. 前端性能优化(慕课网笔记)-2-渲染优化(浏览器)
  17. 数字化公安预审系统应用业务流程解析
  18. a5松下驱动器参数设置表_松下A5,A6伺服电机参数设置
  19. mysql导入GP_GP数据库gpload数据导入详细操作
  20. 如何提取mp4中的音频?

热门文章

  1. knewton适应性学习白皮书(1)
  2. 认识、实践与否定之否定
  3. 信息管理系统总结报告
  4. 如何提升家中路由器的网速?
  5. 图标(ICON) 的 9 种设计原则
  6. java non-heap_Java堆内存Heap与非堆内存Non-Heap简介和设置
  7. AOSP的编译及刷机
  8. 自然语言处理(NLP)之二:文本表示(词向量)
  9. vue 日期判断_vue中根据时间戳判断对应的时间(今天 昨天 前天)
  10. STM32F103 SPI