如何将带有盐的 C# 密码散列转换为 python for windows

How to convert C# password hashing with salt to python for windows

如何转换 Python 中的以下代码,以便它在 Windows 上给出相同的值,即使在多次执行时也是如此。
基本上,它使用 sha512 和 salt 对密码进行 1000 次迭代散列。

代码如下:

using System;
using System.Security.Cryptography;
using System.Text;

namespace CheckHashing
{
    class Program
    {
        protected static string CreateSHA512Hash(string Password, string Salt)
        {
            try
            {
                byte[] bytes_password = Encoding.UTF8.GetBytes(Password);
                byte[] bytes_salt = Encoding.UTF8.GetBytes(Salt);
                HashAlgorithm sha512hash = (HashAlgorithm)new SHA512CryptoServiceProvider();
                for (int index = 0; index < 1000; ++index)
                {
                    byte[] bytes_iteration = Encoding.UTF8.GetBytes(Convert.ToBase64String(bytes_password) + Convert.ToBase64String(bytes_salt));
                    bytes_password = sha512hash.ComputeHash(bytes_iteration);
                }
                return Convert.ToBase64String(bytes_password);
            }
            catch (Exception ex)
            {
                return "Exception"+ex.Message;
            }
        }
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");

            string hash_pwd = CreateSHA512Hash("Pass@21", "SALT(}");
            Console.WriteLine(hash_pwd);
            // Answer => HoCg9kKAl5WY0lWzvH7hdW+cTQGUfknALKDw49rvzUVUTt9X9fuggGpDIRfCdotR/kVU8m7gj2xzRzwIfDc5Xw==
        }


    }
}

已经尝试了下面给出不同值的代码。下面的输出给出了无效密码作为函数中的错误。

import hashlib
from base64 import b64encode

password = "Pass@21"
salt = "SALT(}"

h = hashlib.pbkdf2_hmac('sha512', password.encode('utf-8'), salt.encode('utf-8'), 1000)


print(b64encode(h).decode())

# and below as well

hex_hash = hashlib.sha512(password.encode('utf-8') + salt.encode('utf-8')).digest()
for i in range(1000):
    hex_hash = hashlib.sha512(hex_hash + salt.encode('utf-8')).digest()

print(b64encode(hex_hash).decode())


from passlib.hash import sha512_crypt as sha512

sha512_passwd = sha512.hash(password, rounds=1000)
print(sha512_passwd)

他们的开始并不相同。

如果你在 C# 中添加一些打印

    protected static string CreateSHA512Hash(string Password, string Salt)
    {
        try
        {
            byte[] bytes_password = Encoding.UTF8.GetBytes(Password);
            byte[] bytes_salt = Encoding.UTF8.GetBytes(Salt);
            HashAlgorithm sha512hash = (HashAlgorithm)new SHA512CryptoServiceProvider();
            for (int index = 0; index < 1000; ++index)
            {
                if (index < 10)
                    Console.WriteLine(Convert.ToBase64String(bytes_password));

                byte[] bytes_iteration = Encoding.UTF8.GetBytes(Convert.ToBase64String(bytes_password) + Convert.ToBase64String(bytes_salt));
                bytes_password = sha512hash.ComputeHash(bytes_iteration);
            }
            Console.WriteLine("...");
            return Convert.ToBase64String(bytes_password);
        }
        catch (Exception ex)
        {
            return "Exception" + ex.Message;
        }
    }

这是我的 python 相同代码的端口,具有相同的调试打印,因此您可以比较前 10 个值。

import hashlib
from base64 import b64encode

password = "Pass@21"
salt = "SALT(}"

bytes_password = password.encode('utf-8') 
bytes_salt = salt.encode('utf-8')
for i in range(1000):
    if i < 10:
        print(b64encode(bytes_password).decode())
        
    b64pw = b64encode(bytes_password).decode()
    b64sa = b64encode(bytes_salt).decode()
    bytes_iteration = (b64pw + b64sa).encode('utf-8')
    
    bytes_password = hashlib.sha512(bytes_iteration).digest()

print('...')
print(b64encode(bytes_password).decode())

您的原始代码在十六进制编码时和计算哈希值时不一致,并且在进入循环之前计算了哈希值。