【算法笔记】HASH_算法简单实践

Page content

这篇文章简单的整理了hash算法的简单实践

1.hash算法概念

我们先看看维基百科的解释。

是一种从任何一种数据中创建小的数字`指纹fingerprint`的方法。  
散列函数把消息或数据压缩成摘要,使得数据量变小,将数据的格式固定下来。  
该函数将数据打乱混合,重新创建一个叫做散列值(hash values,hash codes,hash sums,或hashes)的指纹。  
散列值通常用一个短的随机字母和数字组成的字符串来代表。  
好的散列函数在输入域中很少出现散列冲突。在散列表和数据处理中,不抑制冲突来区别数据,会使得数据库记录更难找到。

2.hash算法的特点

  • 正向快速:给定的明文和hash算法,在有限的资源和有限的时间内能快速的算出hash值。
  • 逆向困难:在有限的时间内很难(几乎不可能)逆推明文。
  • 输入敏感:原始输入信息修改一点,产生的hash值看起来变化很大。
  • 抗冲突:又称为抗碰撞性,就是不同的明文算出相同的hash值的概率要很低(几乎不可能)。就是用一段hash值找出相同的明文的可能性极低。

3.目前流行的方法

MD5, SHA-1, SHA-2系列(SHA-224, SHA-256, SHA-384, SHA-512)。
其中MD5和SHA-1算法已经认为不太安全。

4.简单实例

下面用java实现的简单用例:

import org.junit.Test;
import java.security.MessageDigest;

/**
 * @author : 李明燮
 * @since : 2022/10/31
 * create at : 2022/10/31 下午10:50
 */
public class HashUtil {
    
    //byte转换成16进制
    public static String bytes2HexStr(byte[] bytes) {
        StringBuffer result = new StringBuffer();
        for (byte byt : bytes) {
            result.append(Integer.toString((byt & 0xff) + 0x100, 16).substring(1));
        }
        return result.toString();
    }

    //16进制转byte
    public static byte[] hexStr2HexBytes(String strHex) {
        if (strHex == null || strHex.length() == 0) {
            return null;
        }
        strHex = (strHex.length() == 1) ? "0" + strHex : strHex;
        byte[] arr = new byte[strHex.length() / 2];
        byte[] tmp = strHex.getBytes();
        for (int i = 0; i < (tmp.length / 2); i++) {
            arr[i] = unitBytes(tmp[i * 2], tmp[i * 2 + 1]);
        }
        return arr;
    }

    /**
     * 将两个ASCII字符合成一个字节;
     * 如:"EF"--> 0xEF
     *
     * @param src0 byte
     * @param src1 byte
     * @return byte
     */
    public static byte unitBytes(byte src0, byte src1) {
        byte _b0 = Byte.decode("0x" + new String(new byte[]{src0})).byteValue();
        _b0 = (byte) (_b0 << 4);
        byte _b1 = Byte.decode("0x" + new String(new byte[]{src1})).byteValue();
        byte ret = (byte) (_b0 ^ _b1);
        return ret;
    }


    public static String md5(byte[] data) throws Exception {
        //初始化MessageDigest
        MessageDigest md = MessageDigest.getInstance("MD5");
        //执行摘要方法
        byte[] digest = md.digest(data);
        return bytes2HexStr(digest);
    }

    public static String sha(byte[] data) throws Exception {
        //初始化MessageDigest
        MessageDigest md = MessageDigest.getInstance("SHA");
        //执行摘要方法
        byte[] digest = md.digest(data);
        return bytes2HexStr(digest);
    }

    public static String sha256(byte[] data) throws Exception {
        //初始化MessageDigest
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        //执行摘要方法
        byte[] digest = md.digest(data);
        return bytes2HexStr(digest);
    }

    public static String sha512(byte[] data) throws Exception {
        //初始化MessageDigest
        MessageDigest md = MessageDigest.getInstance("SHA-512");
        //执行摘要方法
        byte[] digest = md.digest(data);
        return bytes2HexStr(digest);
    }

    @Test
    public void testHash() throws Exception {
        String src = "123456";

        try {
            String md5 = md5(src.getBytes());
            System.out.println(md5);

            String sha = sha(src.getBytes());
            System.out.println(sha);

            String sha256 = sha256(src.getBytes());
            System.out.println(sha256);

            String sha512 = sha512(src.getBytes());
            System.out.println(sha512);

        } catch (Exception e) {
            e.printStackTrace();
        }

        System.out.println("-------------------------");

        try {
            byte[] arrByte = hexStr2HexBytes(src);
            String md5 = md5(arrByte);
            System.out.println(md5);

            String sha = sha(arrByte);
            System.out.println(sha);

            String sha256 = sha256(arrByte);
            System.out.println(sha256);

            String sha512 = sha512(arrByte);
            System.out.println(sha512);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

执行结果

e10adc3949ba59abbe56e057f20f883e
7c4a8d09ca3762af61e59520943dc26494f8941b
8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92
ba3253876aed6bc22d4a6ff53d8406c6ad864195ed144ab5c87621b6c233b548baeae6956df346ec8c17f5ea10f35ee3cbc514797ed7ddd3145464e2a0bab413
-------------------------
ae1fa6209a246b8b2f2cd2d21be8f2e1
d54093641b8ab5efe6d9c8dca9fb39112cb1722a
bf7cbe09d71a1bcc373ab9a764917f730a6ed951ffa1a7399b7abd8f8fd73cb4
45341a09a5df1bec7ceac3716e32692a8029903178b1ce8bc57c2ac2c11c82100553ae1fcb99118fa7f5a62f524e162e80e0e1533a4e6177b3fa9d830f48bd37

go实现

func HASH(text string, hashType string, isHex bool) (string, error) {
 var hashInstance hash.Hash
 switch hashType {
 case "md4":
  hashInstance = md4.New()
 case "md5":
  hashInstance = md5.New()
 case "sha1":
  hashInstance = sha1.New()
 case "ripemd160":
  hashInstance = ripemd160.New()
 case "sha256":
  hashInstance = sha256.New()
 case "sha512":
  hashInstance = sha512.New()
 }
 if isHex {
  arr, err := hex.DecodeString(text)
  if err != nil {
   return "", err
  }
  hashInstance.Write(arr)
 } else {
  hashInstance.Write([]byte(text))
 }

 bytes := hashInstance.Sum(nil)
 return fmt.Sprintf("%x", bytes), nil
}

func Hash256Double(text string, isHex bool) ([]byte, error) {
 hashInstance := sha256.New()
 if isHex {
  arr, err := hex.DecodeString(text)
  if err != nil {
   return nil, err
  }
  hashInstance.Write(arr)
 } else {
  hashInstance.Write([]byte(text))
 }

 bytes := hashInstance.Sum(nil)
 hashInstance.Reset()
 bytes = hashInstance.Sum(nil)
 return bytes, nil
}

func Hash256DoubleString(text string, isHex bool) (string, error) {
 bytes, err := Hash256Double(text, isHex)
 if err != nil {
  return "", err
 }
 return fmt.Sprintf("%x", bytes), nil
}

欢迎大家的意见和交流

email: li_mingxie@163.com