安全的签名摘要

作者: 生命科学  发布:2019-10-05

本文旨在科普安全相关的知识,并附一个C#实现的文件管理工具。

MD5、SHA1、HMAC、HMAC_SHA1区别

atitit.安全的签名 算法attilax总结

Hash

安全散列算法(英语:Secure Hash Algorithm,缩写为SHA)是一个密码散列函数家族,是FIPS所认证的五种安全散列算法。能计算出一个数字消息所对应到的,长度固定的字符串(又称消息摘要)的算法。且若输入的消息不同,它们对应到不同字符串的概率很高。这些算法之所以称作“安全”是基于以下两点(根据官方标准的描述):

HASH是根据文件的内容的数据通过逻辑运算得到的数值, 不同的文件(即使是相同的文件名)得到的HASH值是不同的, 所以HASH值就成了每一个文件的身份证。

不同HASH值的文件内容也是不相同的,相同的HASH值的文件的内容肯定是完全相同(即使文件名不同).

HASH值还有文件校验的功能,相当于文件的校验码. 所以还可以用来检查文件下载是否正确(比如我们在下载系统镜像或其它开源软件时,官网都会提供文件的HASH值,让我们通过对比HASH值来判断文件是否被修改过)。

文件的Hash值在下载文件的校验方面有很大的用途,Hash值是文件内容的通过二进制码进行一系列的变换生成出来的,即使文件名发生变化,Hash的值也不会发生改变。因此在开发的过程中一般比较两个文件是否相同都是去比较两个文件的Hash值。

 

引言

    什么是MD5,什么是SHA1,如何校验这些Hash。还有拿单个apk文件的MD5,SHA1讯问是不是原版的问题,在这里,让我们先来了解一些基本知识,了解Hash。

    Hash,一般翻译做“散列”,也有直接音译为”哈希”的,就是把任意长度的输入(又叫做预映射,pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一地确定输入值。

    简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。

    Hash主要用于信息安全领域中加密算法,他把一些不同长度的信息转化成杂乱的128位的编码里,叫做Hash值.也可以说,Hash就是找到一种数据内容和数据存放地址之间的映射关系。

    了解了Hash基本定义,就不能不提到一些著名的Hash算法,MD5和SHA1可以说是目前应用最广泛的Hash算法,而它们都是以MD4为基础设计的。

 

MD5

英文全称Message-Digest Algorithm(消息摘要算法)

在下载一下东西时,经常在一些压缩包属性里,看到md5值。而且这个下载页面,很可能会在某一个地方,写了一句,此文件的MD5值为XXXXXXXXX。这有什么作用呢?

白话白话:md5,其实就是一中算法。可以将一个字符串,或文件,或压缩包,执行md5后,就可以生成一个固定长度为128bit的串。这个串,基本上是唯一的。

所以,有人修过压缩包后,就会生成新的串,这时就可以拿网站提供的串和新生成的串对比,如果不同,那就是被人修过过了。

更多请查看: /

 

MD4

    MD4(RFC1320)是MIT的RonaldL.Rivest在1990年设计的,MD是MessageDigest的缩写。它适用在32位字长的处理器上用高速软件实现--它是基于32位操作数的位操作来实现的。

1. MD5 (不推荐)结果是128位二进制,只有转为16进制字符串是32位 1

CRC

循环冗余校验(英语:Cyclic redundancy check,通称“CRC”)是一种根据网络数据包或电脑文件等数据产生简短固定位数校验码的一种散列函數,主要用来检测或校验数据传输或者保存后可能出现的错误。生成的数字在传输或者存储之前计算出来并且附加到数据后面,然后接收方进行检验确定数据是否发生变化。一般来说,循环冗余校验的值都是32位的整数。由于本函数易于用二进制的电脑硬件使用、容易进行数学分析并且尤其善于检测传输通道干扰引起的错误,因此获得广泛应用。此方是由W. Wesley Peterson于1961年发表

 

MD5

    MD5(RFC1321)是Rivest于1991年对MD4的改进版本。它对输入仍以512位分组,其输出是4个32位字的级联,与MD4相同。MD5比MD4来得复杂,并且速度较之要慢一点,但更安全,在抗分析和抗差分方面表现更好。

    MD5是一种不可逆的加密算法,目前是最牢靠的加密算法之一,尚没有能够逆运算的程序被开发出来,它对应任何字符串都可以加密成一段唯一的固定长度的代码。

    那么它有什么用呢?很简单,通过它可以判断原始值是否正确(是否被更改过)。一般用于密码的加密。而我们所提供的MD5校验码就是针对安装程序的唯一对应的一段代码。你可以使用任何MD5运算器对下载的文件进行运算,运算出来的结果如果完全符合我们提供的MD5校验码,那么说明你下载的这个程序没有被中途修改过。

    这个特征码有如下特性,首先它不可逆,例如我有一段秘密的文字如:”MySecretWords”,经算法变换后得到MD5码(b9944e9367d2e40dd1f0c4040d4daaf7),把这个码告诉其他人,他们根据这个MD5码是没有系统的方法可以知道你原来的文字是什么的。

    其次,这个码具有高度的离散性,也就是说,原信息的一点点变化就会导致MD5的巨大变化,例如,”ABC”MD5(902fbdd2b1df0c4f70b4a5d23525e932)和”ABC”(多了一空格)MD5(12c774468f981a9487c30773d8093561)差别非常大,而且之间没有任何关系,也就是说产生的MD5码是不可预测的。

    最后由于这个码有128位那么长,所以任意信息之间具有相同MD5码的可能性非常之低,通常被认为是不可能的。

    所以一般认为MD5码可以唯一地代表原信息的特征,通常用于密码的加密存储,数字签名,文件完整性验证等。

    查看某文件的md5值,dos命令行如下

certutil -hashfile D:your.txt MD5

2. 使用sha1算法加密后的密串长度有40位,相对更安全一些。Sha2安全更高 1

HashHelper

下面一个C#版本的工具类,主要功能是计算文件Hash,文件MD5,文件的CRC32

using System;
using System.IO;
using System.Text;

/// <summary>
/// 提供用于计算指定文件哈希值的方法
/// <example>例如计算文件的MD5值:
/// <code>
///   String hashMd5=HashHelper.GetMD5("MyFile.txt");
/// </code>
/// </example>
/// <example>例如计算文件的CRC32值:
/// <code>
///   String hashCrc32 = HashHelper.GetCRC32("MyFile.txt");
/// </code>
/// </example>
/// <example>例如计算文件的SHA1值:
/// <code>
///   String hashSha1 =HashHelper.GetSHA1("MyFile.txt");
/// </code>
/// </example>
/// </summary>
public class HashHelper
{
    /// <summary>
    ///  计算指定文件的MD5值
    /// </summary>
    /// <param name="fileName">指定文件的完全限定名称</param>
    /// <returns>返回值的字符串形式</returns>
    public static String GetMD5(String fileName)
    {
        String hashMD5 = String.Empty;
        //检查文件是否存在,如果文件存在则进行计算,否则返回空值
        if (File.Exists(fileName))
        {
            using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read))
            {
                //计算文件的MD5值
                System.Security.Cryptography.MD5 calculator = System.Security.Cryptography.MD5.Create();
                Byte[] buffer = calculator.ComputeHash(fs);
                calculator.Clear();
                //将字节数组转换成十六进制的字符串形式
                StringBuilder stringBuilder = new StringBuilder();
                for (int i = 0; i < buffer.Length; i++)
                {
                    stringBuilder.Append(buffer[i].ToString("x2"));
                }
                hashMD5 = stringBuilder.ToString();
            }//关闭文件流
        }//结束计算
        return hashMD5;
    }//ComputeMD5

    /// <summary>
    ///  计算指定文件的CRC32值
    /// </summary>
    /// <param name="fileName">指定文件的完全限定名称</param>
    /// <returns>返回值的字符串形式</returns>
    public static String GetCRC32(String fileName)
    {
        String hashCRC32 = String.Empty;
        //检查文件是否存在,如果文件存在则进行计算,否则返回空值
        if (File.Exists(fileName))
        {
            using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read))
            {
                //计算文件的CSC32值
                Crc32 calculator = new Crc32();
                Byte[] buffer = calculator.ComputeHash(fs);
                calculator.Clear();
                //将字节数组转换成十六进制的字符串形式
                StringBuilder stringBuilder = new StringBuilder();
                for (int i = 0; i < buffer.Length; i++)
                {
                    stringBuilder.Append(buffer[i].ToString("x2"));
                }
                hashCRC32 = stringBuilder.ToString();
            }//关闭文件流
        }
        return hashCRC32;
    }//ComputeCRC32


    /// <summary>
    /// 获取文件的SHA1
    /// </summary>
    /// <param name="fileName"></param>
    /// <returns></returns>
    public static String GetSHA1(String fileName)
    {
        String hashSHA1 = String.Empty;
        //检查文件是否存在,如果文件存在则进行计算,否则返回空值
        if (File.Exists(fileName))
        {
            using (FileStream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
            {
                //计算文件的SHA1值
                System.Security.Cryptography.SHA1 calculator = System.Security.Cryptography.SHA1.Create();
                Byte[] buffer = calculator.ComputeHash(fileStream);
                calculator.Clear();
                //将字节数组转换成十六进制的字符串形式
                StringBuilder stringBuilder = new StringBuilder();
                for (int bufferIdx = 0; bufferIdx < buffer.Length; bufferIdx++)
                {
                    stringBuilder.Append(buffer[bufferIdx].ToString("x2"));
                }
                hashSHA1 = stringBuilder.ToString();

            }//关闭文件流
        }
        else
        {
            Console.Error.WriteLine("{0}文件找不到!", fileName);
        }
        return hashSHA1;
    }//end GetSHA1
}

/// <summary>
/// 提供 CRC32 算法的实现
/// </summary>
public class Crc32 : System.Security.Cryptography.HashAlgorithm
{
    public const UInt32 DefaultPolynomial = 0xedb88320;
    public const UInt32 DefaultSeed = 0xffffffff;
    private UInt32 hash;
    private UInt32 seed;
    private UInt32[] table;
    private static UInt32[] defaultTable;
    public Crc32()
    {
        table = InitializeTable(DefaultPolynomial);
        seed = DefaultSeed;
        Initialize();
    }
    public Crc32(UInt32 polynomial, UInt32 seed)
    {
        table = InitializeTable(polynomial);
        this.seed = seed;
        Initialize();
    }
    public override void Initialize()
    {
        hash = seed;
    }
    protected override void HashCore(byte[] buffer, int start, int length)
    {
        hash = CalculateHash(table, hash, buffer, start, length);
    }
    protected override byte[] HashFinal()
    {
        byte[] hashBuffer = UInt32ToBigEndianBytes(~hash);
        this.HashValue = hashBuffer;
        return hashBuffer;
    }
    public static UInt32 Compute(byte[] buffer)
    {
        return ~CalculateHash(InitializeTable(DefaultPolynomial), DefaultSeed, buffer, 0, buffer.Length);
    }
    public static UInt32 Compute(UInt32 seed, byte[] buffer)
    {
        return ~CalculateHash(InitializeTable(DefaultPolynomial), seed, buffer, 0, buffer.Length);
    }
    public static UInt32 Compute(UInt32 polynomial, UInt32 seed, byte[] buffer)
    {
        return ~CalculateHash(InitializeTable(polynomial), seed, buffer, 0, buffer.Length);
    }
    private static UInt32[] InitializeTable(UInt32 polynomial)
    {
        if (polynomial == DefaultPolynomial && defaultTable != null)
        {
            return defaultTable;
        }
        UInt32[] createTable = new UInt32[256];
        for (int i = 0; i < 256; i++)
        {
            UInt32 entry = (UInt32)i;
            for (int j = 0; j < 8; j++)
            {
                if ((entry & 1) == 1)
                    entry = (entry >> 1) ^ polynomial;
                else
                    entry = entry >> 1;
            }
            createTable[i] = entry;
        }
        if (polynomial == DefaultPolynomial)
        {
            defaultTable = createTable;
        }
        return createTable;
    }
    private static UInt32 CalculateHash(UInt32[] table, UInt32 seed, byte[] buffer, int start, int size)
    {
        UInt32 crc = seed;
        for (int i = start; i < size; i++)
        {
            unchecked
            {
                crc = (crc >> 8) ^ table[buffer[i] ^ crc & 0xff];
            }
        }
        return crc;
    }
    private byte[] UInt32ToBigEndianBytes(UInt32 x)
    {
        return new byte[] { (byte)((x >> 24) & 0xff), (byte)((x >> 16) & 0xff), (byte)((x >> 8) & 0xff), (byte)(x & 0xff) };
    }
}//end class: Crc32

SHA1及其他

    SHA1是由NISTNSA设计为同DSA一起使用的,它对长度小于264的输入,产生长度为160bit的散列值,因此抗穷举(brute-force)性更好。SHA-1设计时基于和MD4相同原理,并且模仿了该算法。SHA-1是由美国标准技术局(NIST)颁布的国家标准,是一种应用最为广泛的Hash函数算法,也是目前最先进的加密技术,被政府部门和私营业主用来处理敏感的信息。而SHA-1基于MD5,MD5又基于MD4。

    论坛里提供的系统镜像文件的Hash也就是微软官方提供的SHA-1值,下载后和此值对应,就说明你下载过程中文件没有被更改,属于原版。

    查看某文件的SHA1值,dos命令如下:

certutil -hashfile D:your.txt SHA1

3. CRC32 (一般8位数据) 2

本文由金沙澳门官网发布于生命科学,转载请注明出处:安全的签名摘要

关键词:

上一篇:没有了
下一篇:没有了