c# - 如何使用 C# 验证加盐和散列密码
问题描述
到目前为止,我已经处理了几个小时的以下问题,并且正在发疯。
语境
我有一个使用以下算法存储密码的旧数据库。遗留代码使用了Python 库。
- 带有 SHA256 的 PBKDF2
- 1000 次迭代
- 盐的长度为 8
- 密码是这样存储的$salt$hashedPassword
我正在为新系统切换登录流程,我需要将旧算法迁移到新算法。新系统使用 .netcore
问题
我正在尝试做的甚至是可能的?我怎样才能实现它?
我的逻辑要求我可以使用盐并使用 .netcore Crypto 库重新创建散列算法,但它不起作用并且函数始终返回 false。
旧代码
from werkzeug.security import generate_password_hash, check_password_hash
def setPassword(self, password):
self.password = generate_password_hash(password, method='pbkdf2:sha256')
其中generate_password_hash来自库,这是代码
SALT_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
def generate_password_hash(password, method="pbkdf2:sha256", salt_length=8):
"""Hash a password with the given method and salt with a string of
the given length. The format of the string returned includes the method
that was used so that :func:`check_password_hash` can check the hash.
The format for the hashed string looks like this::
method$salt$hash
This method can **not** generate unsalted passwords but it is possible
to set param method='plain' in order to enforce plaintext passwords.
If a salt is used, hmac is used internally to salt the password.
If PBKDF2 is wanted it can be enabled by setting the method to
``pbkdf2:method:iterations`` where iterations is optional::
pbkdf2:sha256:80000$salt$hash
pbkdf2:sha256$salt$hash
:param password: the password to hash.
:param method: the hash method to use (one that hashlib supports). Can
optionally be in the format ``pbkdf2:<method>[:iterations]``
to enable PBKDF2.
:param salt_length: the length of the salt in letters.
"""
salt = gen_salt(salt_length) if method != "plain" else ""
h, actual_method = _hash_internal(method, salt, password)
return "%s$%s$%s" % (actual_method, salt, h)
def gen_salt(length):
"""Generate a random string of SALT_CHARS with specified ``length``."""
if length <= 0:
raise ValueError("Salt length must be positive")
return "".join(_sys_rng.choice(SALT_CHARS) for _ in range_type(length))
代码
using System;
using System.Security.Cryptography;
using System.Text;
namespace test_pwd
{
class Program
{
static void Main(string[] args)
{
var res = SameHash("Qwerty12", "84e8c8a5dbdafaf23523ffa5dfecf29d53522a35ca4c76fa877c5fcf9eb4b654", "laSgSC6R");
Console.WriteLine(res);
}
public static bool SameHash(string userpwd, string storedHash, string storedSalt)
{
var saltByte = Encoding.UTF8.GetBytes(storedSalt);
var rfc = new Rfc2898DeriveBytes(userpwd, saltByte, 1000);
var baseString = Convert.ToBase64String(rfc.GetBytes(64));
return baseString == storedHash;
}
}
}
基本字符串转换为
k6vhCweBNz8ymMeEdhi+1czrea+oTTYLrW1OuwdinA78AFyEXKitpKUGLCt1ZdyS1Vka8Cptzd5u5Uzdbi4MbA==
这与我发送的存储密码哈希不同。我做错了什么或者这个想法甚至是可行的?
解决方案
推荐阅读
- javascript - Angular js图像上传更改浏览按钮文本
- javascript - 从按钮重新启动 Intro.Js 之旅?
- r - 如何使用 stringr 库删除列中的部分字符串值?
- swift - 如何重构 Swift API 调用以使用 Swift 5.5 async/await?
- android - Bottomsheet 不会从屏幕的最顶部拖动
- android - android java中的排序列表
- android - 如何从 android studio 中的 Cowin Public API 解决错误代码 403?
- python - 遍历日期以计算差异
- javascript - nodejs PythonShell,如何在运行函数中导出变量
- gradle - Gradle 带来错误版本的传递依赖[Gradle 中的 java.lang.NoClassDefFoundError]