方案1 (加密后存储“算法设置”、“盐(随机值)”、“Hash值”,以“$”分隔):
//Nuget引入SCrypt.NET库
using Org.BouncyCastle.Crypto.Generators;
using Scrypt;
using System;
using System.Security.Cryptography;namespace XXX.Common.Helpers;
public static class SCryptHelper
{//该库的SCrypt加密会得到包含“算法设置、盐(是个随机数)、Hash”一起的值,并以“$”分隔
//由于每次盐是随机产生的,所以每次对同一明文加密得到的值并不相同,
//但由于加密后的信息存储了算法设置及盐信息,所以Compare方法中可以利用这些信息再次对明文进行运算而得到相同的Hash值进行匹配
public static string Encrypt(string password)
{
ScryptEncoder encoder = new ScryptEncoder();
return encoder.Encode(password); //得到包含“算法设置、盐(是个随机数)、Hash”一起的值,并以“$”分隔
}public static bool Verify(string password, string hashedPassword)
{
ScryptEncoder encoder = new ScryptEncoder();
bool areEquals = encoder.Compare(password, hashedPassword);
return areEquals;
}}
//该方案采用的即是以下存储方案(由于Salt是随机的,因此需要保存起来):
//以下来自:https://cryptobook.nakov.com/mac-and-key-derivation/scrypt
方案2 (加密后只存储“Hash值”):
//Nuget引入SCrypt库
using CryptSharp.Utility;
using System;
using System.Text;namespace XXX.Common.Helpers;
public static class SCryptHelper
{//该方案使用Scrypt库自己设置加密参数,
//由于使用固定的“算法设置”、并可以传入相同的参数值作为“盐”,
//因此无需存储算法设置和盐信息,加密后只得到加密参数中指定长度的Hash值,
public static string Encrypt(string password, string salt)
{
byte[] saltArray = Encoding.UTF8.GetBytes(salt);
byte[] result = SCrypt.ComputeDerivedKey(Encoding.UTF8.GetBytes(password), saltArray, 256, 8, 1, 2, 32);//参数: key,salt,cpuCost,memoryBlockSize,parallel,maxThreads,derivedKeyLength),
//详见以下SCrypt.ComputeDerivedKey方法说明截图
string hashResult = BitConverter.ToString(result).Replace("-", "").ToLower();
return hashResult; //返回hashResult长度为64(32*2,即以上参数指定的32字节并以每字节2位的16进制表示)
}public static bool Verify(string password, string salt, string hashedPassword)
{
var hash = Encrypt(password, salt);
return hash.Equals(hashedPassword, StringComparison.OrdinalIgnoreCase);
}
}//该方案加密后只返加Hash值,只需存储该Hash值,每次用相同的Salt计算后匹对
//以下来自:https://8gwifi.org/scrypt.jsp
SCrypt.ComputeDerivedKey方法说明:
参考:
- https://www.oomake.com/question/1177086
- https://blog.csdn.net/LongtengGensSupreme/article/details/107001127
- https://blog.csdn.net/LongtengGensSupreme/article/details/107002537
相关知识(过往相关博文):
- 浅述.Net中的Hash算法(顺带对称、非对称算法)_nthash 算法-CSDN博客
- 密钥派生算法介绍 及 PBKDF2(过时)<Bcrypt(开始淘汰)<Scrypt< Argon2(含Argon2d、Argon2i、Argon2id)简介_bcrypt scrypt-CSDN博客