基于MD5的HMAC消息认证

 

 

实验三

  • 实验题目

HMAC消息认证(基于MD5)

  • 实验要求

(1)在了解HMAC、MD5的基础上编写HMAC-MD5源码

(2)构造长度任意的字符串以及任意长度的密钥字符串,以HMAC算法对文件计算Hash值

 

三、算法描述

使用 MD5 哈希函数计算基于哈希值的消息验证代码 (HMAC)。MD5(消息摘要算法)是 RSA Laboratories 开发的加密哈希算法。HMACMD5 接受任何大小的密钥,并生成长度为 128 位的哈希序列。

基于MD5的HMAC消息认证_第1张图片

图1:HMAC-MD5流程图

 

(1) 在密钥key后面添加0来创建一个长为B(64字节)的字符串(str)。
(2) 将上一步生成的字符串(str)与ipad(0x36)做异或运算,形成结果字符串(istr)。 
(3) 将数据流data附加到第二步的结果字符串(istr)的末尾。
(4) 做md5运算于第三步生成的数据流(istr)。 
(5) 将第一步生成的字符串(str)与opad(0x5c)做异或运算,形成结果字符串(ostr)。
(6) 再将第四步的结果(istr)附加到第五步的结果字符串(ostr)的末尾。 
(7) 做md5运算于第六步生成的数据流(data),输出最终结果(out)。

注:如果第一步中,key的长度klen大于64字节,则先进行md5运算,使其长度klen=16字节。

 

四、算法设计

整体采用byte[]数组存储数据

首先对密钥进行操作:

如果密钥长度,大于64字节,就使用哈希算法,计算其摘要,作为真正的密钥赋值给actualKey, 此时actualKey存放的就是所需密钥

  if (key.length > length)   actualKey = md5(key);

如果密钥长度不足64字节,就使用0x00左补齐到64字节。     

        if (actualKey.length < length) {

            for (int i = actualKey.length; i < keyArr.length; i++)

                keyArr[i] = 0x00;

        }

 

之后就是对密钥之类的进行的图示中各种操作:

使用密钥和ipad[]进行异或运算;

将待加密数据追加到K XOR ipad[]计算结果后面;

使用哈希算法计算H(K XOR ipad, text);

使用密钥和opad进行异或运算;

S0 + H(Si||M) = secondAppendResult

H(secondAppendResult)计算SecondAppendResult的哈希值;

 

界面部分:  采用FlowLayout布局,用标签label1接受输入的需要加密的字符串message,用标签label2接受输入的密钥secret字符串,用button设置相应的ActionListener,关联HMAC操作函数getHmacMd5Bytes(),按下按钮则执行。HMAC完成后的字符串out送到标签outtext显示

 

 

五、运行结果

基于MD5的HMAC消息认证_第2张图片

与网站在线HMAC结果对比得知结果正确

附录:关键代码(可选)

import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class Hmacmd5 {
    //md5 
    private static byte[] md5(byte[] str) throws NoSuchAlgorithmException {
        MessageDigest md = MessageDigest.getInstance("MD5");
        md.update(str);
        return md.digest();
    }

    //数据data    密钥key
    public static byte[] getHmacMd5Bytes(byte[] key, byte[] data) throws NoSuchAlgorithmException {
        
        int length = 64;
        byte[] ipad = new byte[length];
        byte[] opad = new byte[length];
        for (int i = 0; i < 64; i++) {
            ipad[i] = 0x36;
            opad[i] = 0x5C;
        }
        
        byte[] actualKey = key; 
        byte[] keyArr = new byte[length]; // 64 bytes
        //如果密钥长度,大于64字节,就使用哈希算法,计算其摘要,作为真正的密钥赋值给actualKey
        if (key.length > length) {
            actualKey = md5(key);
        }//此时actualKey存放的就是所需密钥
        for (int i = 0; i < actualKey.length; i++) {
            keyArr[i] = actualKey[i];
        }

        // 如果密钥长度不足64字节,就使用0x00左补齐到64字节。      
        if (actualKey.length < length) {
            for (int i = actualKey.length; i < keyArr.length; i++)
                keyArr[i] = 0x00;
        }
        
         // 使用密钥和ipad[]进行异或运算。
        byte[] kIpadXorResult = new byte[length];
        for (int i = 0; i < length; i++) {
            kIpadXorResult[i] = (byte) (keyArr[i] ^ ipad[i]);
        }

        //将待加密数据追加到K XOR ipad[]计算结果后面。
        byte[] firstAppendResult = new byte[kIpadXorResult.length + data.length];
        for (int i = 0; i < kIpadXorResult.length; i++) {
            firstAppendResult[i] = kIpadXorResult[i];
        }
        for (int i = 0; i < data.length; i++) {
            firstAppendResult[i + keyArr.length] = data[i];
        }

        //使用哈希算法计算H(K XOR ipad, text) 
        byte[] firstHashResult = md5(firstAppendResult);

        //使用密钥和opad进行异或运算。
        byte[] kOpadXorResult = new byte[length];
        for (int i = 0; i < length; i++) {
            kOpadXorResult[i] = (byte) (keyArr[i] ^ opad[i]);
        }

        //S0 + H(Si||M) = secondAppendResult
        byte[] secondAppendResult = new byte[kOpadXorResult.length + firstHashResult.length];
        for (int i = 0; i < kOpadXorResult.length; i++) {
            secondAppendResult[i] = kOpadXorResult[i];
        }
        for (int i = 0; i < firstHashResult.length; i++) {
            secondAppendResult[i + keyArr.length] = firstHashResult[i];
        }

        //H(secondAppendResult)
        byte[] hmacMd5Bytes = md5(secondAppendResult);

        return hmacMd5Bytes;

    }

    //byte[] -> String
    public static String bytesToHexString(byte[] src){
        StringBuilder stringBuilder = new StringBuilder("");
        if (src == null || src.length <= 0) {
            return null;
        }
        for (int i = 0; i < src.length; i++) {
            int v = src[i] & 0xFF;
            String hv = Integer.toHexString(v);
            if (hv.length() < 2) {
                stringBuilder.append(0);
            }
            stringBuilder.append(hv);
        }
        return stringBuilder.toString();
    }

    //主函数
    public static void main(String[] args) throws Exception {
    	
    	JFrame f = new JFrame("HMAC-Md5");
        f.setSize(400, 180);
        f.setLocation(200, 200);

        f.setLayout(new FlowLayout());

        JLabel label1 = new JLabel("message:");
        // 输入框
        JTextField text1 = new JTextField("");
        text1.setText("");
        text1.setPreferredSize(new Dimension(100, 30));

        JLabel label2 = new JLabel("secret:");
        // 输入框
        JTextField text2 = new JTextField("");
        text2.setText("");
        text2.setPreferredSize(new Dimension(100, 30));

        JLabel outlabel = new JLabel("after:");
        // 输入框
        JTextField outtext = new JTextField("");
        outtext.setText("");
        outtext.setPreferredSize(new Dimension(250, 30));
        
        JButton button = new JButton("加密");
        //相应的函数
        button.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                //点击按钮后执行的代码
            	String src = text1.getText();
            	String key = text2.getText();
            	try {
					byte[] macmd5 = Hmacmd5.getHmacMd5Bytes(key.getBytes(), src.getBytes());
					String out =  Hmacmd5.bytesToHexString(macmd5);
					outtext.setText(out);
				} catch (NoSuchAlgorithmException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
                
            }
        });
        
        f.add(label1);	 f.add(text1);	
        f.add(label2);	f.add(text2);	
        f.add(button);
        f.add(outlabel);	f.add(outtext);
        		

        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        f.setVisible(true);
        text1.grabFocus();
    }
}

 

你可能感兴趣的:(基于MD5的HMAC消息认证)