基于Java实现的MD5算法

(1)MD5原理
MD5以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。
第一步、填充
如果输入信息的长度(bit)对512求余的结果不等于448,就需要填充使得对512求余的结果等于448。填充的方法是填充一个1和n个0。填充完后,信息的长度就为N*512+448(bit);

第二步、记录信息长度
用64位来存储填充前信息长度。这64位加在第一步结果的后面,这样信息长度就变为N*512+448+64=(N+1)*512位。

第三步、装入标准的幻数(四个整数)
标准的幻数(物理顺序)是(A=(01234567)16,B=(89ABCDEF)16,C=(FEDCBA98)16,D=(76543210)16)。如果在程序中定义应该是(A=0X67452301L,B=0XEFCDAB89L,C=0X98BADCFEL,D=0X10325476L)。有点晕哈,其实想一想就明白了。

首先清楚整型的位表示方法,其次标准文档上要求的是:四个幻数在内存地址上从低到高为:
A: 01 23 45 67
B: 89 ab cd ef
C: fe dc ba 98
D: 76 54 32 10
采用小端表示法表示为A=0X67452301L,则在地址中就是A=01 23 45 67

小端法和大端法区别如下图:
在这里插入图片描述

第四步、四轮循环运算

1.把消息分以12位一分组进行处理
2.每一个分组进行4轮变换,以上面所说4个标准的幻数为起始变量进行计算,重新输出4个变量
3.以这4个变量再进行下一分组的运算,如果已经是最后一个分组,则这4个变量为最后的结果,即MD5值
在这里插入图片描述

循环的次数是分组的个数(N+1)
(1)将每一512字节细分成16个小组,每个小组64位(8个字节)
(2)先认识四个线性函数(&是与,|是或,~是非,^是异或)
F(X,Y,Z)=(X&Y)|((~X)&Z)
G(X,Y,Z)=(X&Z)|(Y&(~Z))
H(X,Y,Z)=XYZ
I(X,Y,Z)=Y^(X|(~Z))
(3)设Mj表示消息的第j个子分组(从0到15),<<< s表示循环左移s位,则四种操作为:

FF(a,b,c,d,Mj,s,ti)表示a=b+((a+F(b,c,d)+Mj+ti)<<<s)
GG(a,b,c,d,Mj,s,ti)表示a=b+((a+G(b,c,d)+Mj+ti)<<<s)
HH(a,b,c,d,Mj,s,ti)表示a=b+((a+H(b,c,d)+Mj+ti)<<<s)
II(a,b,c,d,Mj,s,ti)表示a=b+((a+I(b,c,d)+Mj+ti)<<<s)
(4)四轮运算

第一轮
a=FF(a,b,c,d,M0,7,0xd76aa478)
b=FF(d,a,b,c,M1,12,0xe8c7b756)
c=FF(c,d,a,b,M2,17,0x242070db)
d=FF(b,c,d,a,M3,22,0xc1bdceee)
a=FF(a,b,c,d,M4,7,0xf57c0faf)
b=FF(d,a,b,c,M5,12,0x4787c62a)
c=FF(c,d,a,b,M6,17,0xa8304613)
d=FF(b,c,d,a,M7,22,0xfd469501)
a=FF(a,b,c,d,M8,7,0x698098d8)
b=FF(d,a,b,c,M9,12,0x8b44f7af)
c=FF(c,d,a,b,M10,17,0xffff5bb1)
d=FF(b,c,d,a,M11,22,0x895cd7be)
a=FF(a,b,c,d,M12,7,0x6b901122)
b=FF(d,a,b,c,M13,12,0xfd987193)
c=FF(c,d,a,b,M14,17,0xa679438e)
d=FF(b,c,d,a,M15,22,0x49b40821)

第二轮
a=GG(a,b,c,d,M1,5,0xf61e2562)
b=GG(d,a,b,c,M6,9,0xc040b340)
c=GG(c,d,a,b,M11,14,0x265e5a51)
d=GG(b,c,d,a,M0,20,0xe9b6c7aa)
a=GG(a,b,c,d,M5,5,0xd62f105d)
b=GG(d,a,b,c,M10,9,0x02441453)
c=GG(c,d,a,b,M15,14,0xd8a1e681)
d=GG(b,c,d,a,M4,20,0xe7d3fbc8)
a=GG(a,b,c,d,M9,5,0x21e1cde6)
b=GG(d,a,b,c,M14,9,0xc33707d6)
c=GG(c,d,a,b,M3,14,0xf4d50d87)
d=GG(b,c,d,a,M8,20,0x455a14ed)
a=GG(a,b,c,d,M13,5,0xa9e3e905)
b=GG(d,a,b,c,M2,9,0xfcefa3f8)
c=GG(c,d,a,b,M7,14,0x676f02d9)
d=GG(b,c,d,a,M12,20,0x8d2a4c8a)

第三轮
a=HH(a,b,c,d,M5,4,0xfffa3942)
b=HH(d,a,b,c,M8,11,0x8771f681)
c=HH(c,d,a,b,M11,16,0x6d9d6122)
d=HH(b,c,d,a,M14,23,0xfde5380c)
a=HH(a,b,c,d,M1,4,0xa4beea44)
b=HH(d,a,b,c,M4,11,0x4bdecfa9)
c=HH(c,d,a,b,M7,16,0xf6bb4b60)
d=HH(b,c,d,a,M10,23,0xbebfbc70)
a=HH(a,b,c,d,M13,4,0x289b7ec6)
b=HH(d,a,b,c,M0,11,0xeaa127fa)
c=HH(c,d,a,b,M3,16,0xd4ef3085)
d=HH(b,c,d,a,M6,23,0x04881d05)
a=HH(a,b,c,d,M9,4,0xd9d4d039)
b=HH(d,a,b,c,M12,11,0xe6db99e5)
c=HH(c,d,a,b,M15,16,0x1fa27cf8)
d=HH(b,c,d,a,M2,23,0xc4ac5665)

第四轮
a=II(a,b,c,d,M0,6,0xf4292244)
b=II(d,a,b,c,M7,10,0x432aff97)
c=II(c,d,a,b,M14,15,0xab9423a7)
d=II(b,c,d,a,M5,21,0xfc93a039)
a=II(a,b,c,d,M12,6,0x655b59c3)
b=II(d,a,b,c,M3,10,0x8f0ccc92)
c=II(c,d,a,b,M10,15,0xffeff47d)
d=II(b,c,d,a,M1,21,0x85845dd1)
a=II(a,b,c,d,M8,6,0x6fa87e4f)
b=II(d,a,b,c,M15,10,0xfe2ce6e0)
c=II(c,d,a,b,M6,15,0xa3014314)
d=II(b,c,d,a,M13,21,0x4e0811a1)
a=II(a,b,c,d,M4,6,0xf7537e82)
b=II(d,a,b,c,M11,10,0xbd3af235)
c=II(c,d,a,b,M2,15,0x2ad7d2bb)
d=II(b,c,d,a,M9,21,0xeb86d391)
5)每轮循环后,将A,B,C,D分别加上a,b,c,d,然后进入下一循环。

MD5算法实现代码:

package internetsafe;
import java.io.File;  

import java.io.FileInputStream;  
  
import java.io.IOException;  
  
import java.security.MessageDigest;  
  
   
  
public class MD5 {  
  
    static char hexdigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };  
  
    public static String getMD5(File file) {  
  
        FileInputStream fis = null;  
  
        try {  
  
            MessageDigest md = MessageDigest.getInstance("MD5");  
  
            fis = new FileInputStream(file);  
  
            byte[] buffer = new byte[2048];  
  
            int length = -1;  
  
            while ((length = fis.read(buffer)) != -1) {  
  
                md.update(buffer, 0, length);  
  
            }  
  
            byte[] b = md.digest();  
  
            return byteToHexString(b);  
  
        } catch (Exception e) {  
  
            e.printStackTrace();  
  
            return null;  
  
        } finally {  
  
            try {  
  
                fis.close();  
  
            } catch (IOException e) {  
  
                e.printStackTrace();  
  
            }  
  
        }  
  
    }   
  
  
    private static String byteToHexString(byte[] tmp) {  
  
        String s;  
  
        // 用字节表示就是 16 个字节  
  
        // 每个字节用 16 进制表示的话,使用两个字符,所以表示成 16 进制需要 32 个字符  
  
        // 比如一个字节为01011011,用十六进制字符来表示就是“5b”  
  
        char str[] = new char[16 * 2];  
  
        int k = 0; // 表示转换结果中对应的字符位置  
  
        for (int i = 0; i < 16; i++) { // 从第一个字节开始,对 MD5 的每一个字节转换成 16 进制字符的转换  
  
            byte byte0 = tmp[i]; // 取第 i 个字节  
  
            str[k++] = hexdigits[byte0 >>> 4 & 0xf]; // 取字节中高 4 位的数字转换, >>> 为逻辑右移,将符号位一起右移  
  
            str[k++] = hexdigits[byte0 & 0xf]; // 取字节中低 4 位的数字转换  
  
        }  
        s = new String(str); // 换后的结果转换为字符串  
        return s;  
    }  
    public static void main(String arg[]) {  
        String a = getMD5(new File("d:/a.txt"));   
        System.out.println("a.txt的摘要值为:" + a);  

    }  
  
}  
  • 25
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是基于 Java 的 Mac 类实现 HMAC-MD5 算法的示例代码: ```java import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.util.Base64; public class HmacMd5 { public static void main(String[] args) { String message = "Hello, world!"; String key = "secret"; String hmac = hmacMd5(message, key); System.out.println(hmac); } public static String hmacMd5(String message, String key) { try { // 创建 Mac 对象 Mac mac = Mac.getInstance("HmacMD5"); // 创建 SecretKeySpec 对象 SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "HmacMD5"); // 初始化 Mac 对象 mac.init(keySpec); // 计算 HMAC 值 byte[] hmacBytes = mac.doFinal(message.getBytes()); // 对 HMAC 值进行 Base64 编码 return Base64.getEncoder().encodeToString(hmacBytes); } catch (NoSuchAlgorithmException | InvalidKeyException e) { e.printStackTrace(); return null; } } } ``` 在示例代码中,我们通过调用 `hmacMd5` 方法来计算 HMAC-MD5 值。该方法接受两个参数:`message` 表示要计算 HMAC 值的消息,`key` 表示 HMAC 密钥。在方法内部,我们首先创建 Mac 对象,然后创建 SecretKeySpec 对象,并使用 HMAC 密钥初始化 Mac 对象。接着,我们调用 Mac 对象的 `doFinal` 方法来计算 HMAC 值,并将其转换为 Base64 编码的字符串返回。最后,在 `main` 方法中,我们演示了如何使用该方法来计算 HMAC-MD5 值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值