C# pbkdf2 算法

内容纲要

直接使用 .NET 的 CLR 库生成,不依赖第三方框架。

using System;
using System.Linq;
using System.Security.Cryptography;

    /// <summary>
    /// 哈希加解密帮助类
    /// </summary>
    public static class HashHelper
    {
        private const int SALT_SIZE = 128; // size in bytes,salt 的大小
        private const int HASH_SIZE = 128; // size in bytes,生成的哈希串的大小
        private const int ITERATIONS = 100000; // number of pbkdf2 iterations,表示循环次数

        #region 生成 Salt

        /// <summary>
        /// 随机生成 Salt,相当于生成密钥
        /// </summary>
        /// <returns></returns>
        public static byte[] CreateSalt()
        {
            // 生成盐
            RNGCryptoServiceProvider provider = new RNGCryptoServiceProvider();
            byte[] salt = new byte[SALT_SIZE];
            provider.GetBytes(salt);
            return salt;
        }

        /// <summary>
        /// 随机生成 Salt,相当于生成密钥,同时返回此密钥的字符串
        /// </summary>
        /// <param name="text">Salt 的字符串 表示</param>
        /// <returns></returns>
        public static byte[] CreateSalt(out string text)
        {
            // 生成盐
            RNGCryptoServiceProvider provider = new RNGCryptoServiceProvider();
            byte[] salt = new byte[SALT_SIZE];
            provider.GetBytes(salt);
            text = BitConverter.ToString(salt);
            return salt;
        }

        #endregion

        #region 加密

        /// <summary>
        /// 将一个字符串加密
        /// </summary>
        /// <param name="text">待加密的字符串</param>
        /// <param name="salt">盐</param>
        /// <returns></returns>
        public static string CreateHashString(string text, out byte[] salt)
        {
            salt = CreateSalt();
            Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(text, salt, ITERATIONS);
            var bytes = pbkdf2.GetBytes(HASH_SIZE);

            return BitConverter.ToString(bytes);
        }

        /// <summary>
        /// 将一个字符串加密
        /// </summary>
        /// <param name="text">待加密的字符串</param>
        /// <param name="salt">盐</param>
        public static string CreateHashString(string text, out string salt)
        {
            var _salt = CreateSalt();
            Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(text, _salt, ITERATIONS);
            var bytes = pbkdf2.GetBytes(HASH_SIZE);
            salt = BitConverter.ToString(_salt);
            return BitConverter.ToString(bytes);
        }

        /// <summary>
        /// 将一个字符串加密
        /// </summary>
        /// <param name="text">待加密的字符串</param>
        /// <param name="salt">盐</param>
        /// <returns></returns>
        public static string CreateHashString(string text, byte[] salt)
        {
            Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(text, salt, ITERATIONS);
            var bytes = pbkdf2.GetBytes(HASH_SIZE);

            return BitConverter.ToString(bytes);
        }

        #endregion

        #region 验证

        /// <summary>
        /// 检查一个字符串是否与密文相同
        /// </summary>
        /// <param name="password">未加密的字符串</param>
        /// <param name="hashPassword">密文</param>
        /// <param name="salt">盐</param>
        /// <returns></returns>
        public static bool HashCheck(string password, string hashPassword, string salt)
        {
            // 还原 salt
            var chars = salt.Split('-').ToArray();
            var saltBytes = chars.Select(x => (byte)int.Parse(x, System.Globalization.NumberStyles.AllowHexSpecifier)).ToArray();
            return EqualHash(password, hashPassword, saltBytes);
        }

        /// <summary>
        /// 检查一个字符串是否与密文相同
        /// </summary>
        /// <param name="text">未加密的字符串</param>
        /// <param name="hash">密文</param>
        /// <param name="salt">盐</param>
        /// <returns></returns>
        public static bool EqualHash(string text, string hash, byte[] salt)
        {
            // 原文生成密文
            Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(text, salt, ITERATIONS);
            var bytes = pbkdf2.GetBytes(HASH_SIZE);

            // 密文还原 byte
            var chars = hash.Split('-').ToArray();
            var hashBytes = chars.Select(x => (byte)int.Parse(x, System.Globalization.NumberStyles.AllowHexSpecifier)).ToArray();

            return EqualsBytes(bytes, hashBytes);
        }

        #endregion

                /// <summary>
        /// 判断两个字节数组是否相等
        /// </summary>
        /// <param name="b1"></param>
        /// <param name="b2"></param>
        /// <returns></returns>
        public static bool EqualsBytes(byte[] b1, byte[] b2)
        {
            return b1.AsSpan().SequenceEqual(b2.AsSpan());
        }
}
点赞

发表评论

邮箱地址不会被公开。 必填项已用*标注

You must enable javascript to see captcha here!