MD5加密的基本常识和封装类

MD5加密的基本常识和封装类

MD5(Message Digest Algorithm 5)是一种常见的哈希算法,用于将任意长度的数据转换为固定长度的(通常是128位或16字节)哈希值。它是MD家族中的第五个算法,广泛用于数据校验、数字签名、密码存储等领域。MD5是单向函数,即无法从生成的哈希值反推出原始数据,这也是其常用于对敏感信息进行加密或签名的原因之一。

1. MD5的原理

MD5算法的核心原理是基于位操作、逻辑运算和模运算,对输入的数据进行多轮循环处理,生成最终的128位哈希值。具体步骤如下:

  1. 填充数据: 将原始数据填充至512位的倍数(64字节)。

  2. 初始值: 初始化4个32位的寄存器(A、B、C、D),用作哈希的中间结果。

  3. 分组处理: 将填充后的数据分成512位(64字节)的分组,每个分组进行下面的处理。

  4. 循环压缩: 将每个分组进行四轮循环压缩,每轮循环使用不同的非线性函数(F、G、H、I)和常量。

  5. 合并结果: 将每个分组经过四轮循环压缩后的中间结果与初始值相加,得到新的中间结果。

  6. 输出: 最后,将四个寄存器的内容按照从低位到高位的顺序连接起来,得到128位的MD5哈希值。

2. MD5的应用

MD5在计算机领域有广泛的应用,包括但不限于以下几个方面:

  1. 数据完整性校验: 在数据传输过程中,使用MD5计算数据的哈希值,接收方根据接收到的数据和哈希值重新计算哈希值,并与接收到的哈希值进行对比,以验证数据的完整性和是否被篡改。

  2. 数字签名: 在数字签名中,对原始数据使用MD5进行哈希计算,然后使用私钥对哈希值进行加密生成数字签名。接收方使用公钥解密数字签名,再对原始数据进行MD5哈希计算,并与解密后的签名对比,以验证数据的来源和完整性。

  3. 密码存储: 在密码存储中,不应该将明文密码直接存储在数据库中,而是将密码进行MD5哈希后再存储。用户登录时,输入的密码也进行MD5哈希后与数据库中存储的哈希值进行比较,从而验证密码是否正确。

  4. 防篡改校验: 在软件发布过程中,可以对软件文件进行MD5哈希计算,并将哈希值与官方发布的哈希值进行比较,从而验证软件是否被篡改。

需要注意的是,由于MD5算法的特性,它已经不再被认为是一种安全的哈希算法。因为MD5容易受到碰撞攻击(collision attack),即找到两个不同的输入数据,经过MD5计算后得到相同的哈希值。因此,在安全性要求较高的场景下,应该使用更强大、不易受到碰撞攻击的哈希算法,如SHA-256或SHA-3。

3. MD5加密封装类

/// <summary>
/// 不可逆加密
/// 1 防止被篡改
/// 2 防止明文存储
/// 3 防止抵赖,数字签名
/// </summary>
public class MD5Encrypt
{
    #region MD5
    /// <summary>
    /// MD5加密,和动网上的16/32位MD5加密结果相同,
    /// 使用的UTF8编码
    /// </summary>
    /// <param name="source">待加密字串</param>
    /// <param name="length">16或32值之一,其它则采用.net默认MD5加密算法</param>
    /// <returns>加密后的字串</returns>
    public static string Encrypt(string source, int length = 32)//默认参数
    {
        if (string.IsNullOrEmpty(source)) return string.Empty;
        HashAlgorithm provider = CryptoConfig.CreateFromName("MD5") as HashAlgorithm;
        byte[] bytes = Encoding.UTF8.GetBytes(source);//这里需要区别编码的
        byte[] hashValue = provider.ComputeHash(bytes);
        StringBuilder sb = new StringBuilder();
        switch (length)
        {
            case 16://16位密文是32位密文的9到24位字符
                for (int i = 4; i < 12; i++)
                {
                    sb.Append(hashValue[i].ToString("x2"));
                }
                break;
            case 32:
                for (int i = 0; i < 16; i++)
                {
                    sb.Append(hashValue[i].ToString("x2"));
                }
                break;
            default:
                for (int i = 0; i < hashValue.Length; i++)
                {
                    sb.Append(hashValue[i].ToString("x2"));
                }
                break;
        }
        return sb.ToString();
    }
    #endregion MD5

    #region MD5摘要
    /// <summary>
    /// 获取文件的MD5摘要
    /// </summary>
    /// <param name="fileName"></param>
    /// <returns></returns>
    public static string AbstractFile(string fileName)
    {
        using (FileStream file = new FileStream(fileName, FileMode.Open))
        {
            return AbstractFile(file);
        }
    }
    /// <summary>
    /// 根据stream获取文件摘要
    /// </summary>
    /// <param name="stream"></param>
    /// <returns></returns>
    public static string AbstractFile(Stream stream)
    {
        MD5 md5 = new MD5CryptoServiceProvider();
        byte[] retVal = md5.ComputeHash(stream);

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < retVal.Length; i++)
        {
            sb.Append(retVal[i].ToString("x2"));
        }
        return sb.ToString();
    }
    #endregion
}
posted @ 2023-07-26 21:34  陈憨憨啊  阅读(39)  评论(0编辑  收藏  举报