hash函数原理实现

哈希函数(Hash)
又称为 散列函数、散列算法、杂凑函数等
是一种单向密码体制:从明文到密文的不可逆映射
可将任意长度的输入变换为固定长度的输出
生成消息的“数据指纹”(也称消息摘要或散列值),
在数据完整性认证和数字签名等领域有广泛的应用

分类:
改动检测码MDC(Manipulation Detection Code)
不带密钥哈希函数,检测消息有无篡改
消息认证码MAC(Message Authentication Code)
带密钥哈希函数,认证消息源真实性与消息完整性

主要说,hash函数作用是检测消息的完整性,所以在以减少碰撞性为原则,然后有不可逆性
其次不管多长都需要生成固定长度的散列值

记住上面两点,然后参考hash函数的实现原理如下:

MD5算法是hash函数算法的一个实例。

对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)。有点晕哈,其实想一想就明白了。

第四步、四轮循环运算:循环的次数是分组的个数(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))

然后经过四轮遍历运算,详情见博客:
https://blog.csdn.net/u012611878/article/details/54000607

JAVA实现MD5

在java中实现MD5是很简单的,在包java.security有个类MessageDigest。官方文档如下
MessageDigest 类为应用程序提供信息摘要算法的功能,如 MD5 或 SHA 算法。信息摘要是安全的单向哈希函数,它接收任意大小的数据,输出固定长度的哈希值。

MessageDigest 对象开始被初始化。该对象通过使用 update 方法处理数据。任何时候都可以调用 reset 方法重置摘要。一旦所有需要更新的数据都已经被更新了,应该调用 digest 方法之一完成哈希计算。

对于给定数量的更新数据,digest 方法只能被调用一次。digest 被调用后,MessageDigest 对象被重新设置成其初始状态。

JAVA代码如下:

import java.security.MessageDigest;

public class MyMD5 {

    static char[] hex = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; 
    public static void main(String[] args) {
        try{
            MessageDigest md5 = MessageDigest.getInstance("MD5");//申明使用MD5算法
            md5.update("a".getBytes());//
            System.out.println("md5(a)="+byte2str(md5.digest()));
            md5.update("a".getBytes());
            md5.update("bc".getBytes());
            System.out.println("md5(abc)="+byte2str(md5.digest()));
        }catch(Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 将字节数组转换成十六进制字符串
     * @param bytes
     * @return
     */
    private static String byte2str(byte []bytes){
        int len = bytes.length;   
        StringBuffer result = new StringBuffer();    
        for (int i = 0; i < len; i++) {   
            byte byte0 = bytes[i];   
            result.append(hex[byte0 >>> 4 & 0xf]);   
            result.append(hex[byte0 & 0xf]);   
        }
        return result.toString();
    }
} 

你可能感兴趣的:(算法)