Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/328.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在Python中重现System.Security.Cryptography.SHA1管理结果_C#_.net_Python_Cryptography - Fatal编程技术网

C# 如何在Python中重现System.Security.Cryptography.SHA1管理结果

C# 如何在Python中重现System.Security.Cryptography.SHA1管理结果,c#,.net,python,cryptography,C#,.net,Python,Cryptography,交易是这样的:我正在将一个.NET网站迁移到Python。我有一个数据库,使用System.Security.Cryptography.SHA1Managed实用程序对密码进行哈希处理 我使用以下代码在.NET中创建哈希: string hashedPassword = Cryptographer.CreateHash("MYHasher", userInfo.Password); MYHasher块如下所示: <add algorithmType="System.Security.Cr

交易是这样的:我正在将一个.NET网站迁移到Python。我有一个数据库,使用System.Security.Cryptography.SHA1Managed实用程序对密码进行哈希处理

我使用以下代码在.NET中创建哈希:

string hashedPassword = Cryptographer.CreateHash("MYHasher", userInfo.Password);
MYHasher块如下所示:

<add algorithmType="System.Security.Cryptography.SHA1Managed, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=blahblahblah"
    saltEnabled="true" type="Microsoft.Practices.EnterpriseLibrary.Security.Cryptography.HashAlgorithmProvider, Microsoft.Practices.EnterpriseLibrary.Security.Cryptography, Version=3.0.0.0, Culture=neutral, PublicKeyToken=daahblahdahdah"
    name="MYHasher" />

因此,对于给定的密码,我返回并在数据库中存储一个48字节的salt sha1。我假设最后8个字节是salt。我曾尝试在python中通过执行sha1(salt+密码)和sha1(password+salt)来重现哈希过程,但我没有运气

我的问题是:

  • 如何使用公钥
  • 如何使用salt重新设置密码
  • 盐是如何产生的?(例如,当我说saltEnabled=“true”时,会发生什么额外的魔法?)
  • 我需要的具体细节不仅仅是参考其他.NET库,我还需要在黑盒中寻找实际的操作逻辑


    谢谢

    根据,这应该类似于sha1(密码+盐)+盐。SHA-1输出为20字节,因此对于48字节,这应该是28字节的salt,而不是8字节的salt,除非使用某种编码。

    当使用
    字符串CreateHash(字符串,字符串)
    重载时,会发生以下情况:

  • 使用UTF16(使用Encoding.Unicode.GetBytes())将字符串转换为字节
  • 生成一个随机的16字节salt
  • salt被附加到转换后的字符串并进行散列
  • 盐被加到杂烩里
  • 使用base64(使用Convert.ToBase64String())将哈希+salt转换回字符串

  • 很抱歉回复得太晚,但是我在尝试复制企业库的加密块中使用的SHA1哈希逻辑时遇到了类似的情况,但是使用Java

    要回答您的每个问题,请执行以下操作:

  • 如何使用公钥?

    上面配置块中的PublicKeyToken用于标识签名的、强名称的.net程序集。这是公钥的64位哈希,对应于用于对程序集签名的私钥注意:此键与散列数据的实现完全无关。

  • 如何使用salt重新设置密码。

    使用salt创建哈希密码的事件顺序如下:

    • 调用
      Cryptographer.CreateHash(“MYHasher”,value)
      其中,
      “MYHasher”
      是在配置块中指定的已配置的
      System.Security.Cryptography.SHA1Managed
      实例提供程序的名称,
      value
      是要哈希的字符串

    • 上述方法调用
      CreateHash(IHashProvider提供程序,字符串明文)
      ,其中提供了已解析的
      IHashProvider
      。在此方法中,运行以下代码:

    • 开始时传递的
      参数(现在是
      纯文本
      参数)使用Unicode编码转换为字节数组

    • 接下来,使用上面创建的字节数组调用SHA1哈希提供程序的
      CreateHash(bytes)
      方法。在此方法中,将执行以下步骤:

    • this.createHashWithAlt(纯文本,(字节[])null),其中
      明文
      是一个字节数组,包含作为字符串在堆栈顶部传入的原始
      。第二个参数是salt字节数组(为null)。在此方法中,调用以下代码:

    • this.AddSaltToPlainText(ref salt,ref plaintext)
      是有关如何对提供的文本进行盐析的第一条线索。在此方法中,运行以下代码:
    • this.saltEnabled
      变量由配置块中的
      saltEnabled=“true”
      初始化。如果为true,并且您没有提供salt,那么将为您生成一个包含16个随机字节的字节数组(通过调用外部C API)
    • 然后,
      纯文本
      变量的前面加上salt。e、 g.:[盐][纯文本]
  • 这一点需要注意

    • 然后通过调用this.HashCryptographer.ComputeHash(明文)对salt和
      明文的组合进行hash处理。这将产生一个20字节长的数组

    • 然后,通过调用this.AddSaltToHash(salt,ref hash)将salt再次添加到先前创建的20字节数组中,为您提供一个36字节长的数组

    • 返回堆栈将最终导致调用
      return Convert.ToBase64String(hash)
      CreateHash()方法中。这将返回所提供的SHA1 salt哈希值+salt的Base64字符串表示形式

    公式:Base64(盐+SHA1(盐+值))

  • 盐是如何产生的?(例如,当我说saltEnabled=“true”时,会发生什么额外的魔力?

    这在问题2中得到了回答,特别是调用
    CryptographyUtility.GetRandomBytes(16)最终调用C库:

  • [DllImport(“QCall”,CharSet=CharSet.Unicode)]
    私有静态外部无效GetBytes(SafeProvHandle hProv,字节[]随机字节,整数计数)


    希望这对你有所帮助

    谢谢Gareth Stephenson!你的回答已经得到了我需要的所有答案。我完全被这个弄糊涂了。我需要升级使用此企业库的旧模块,但编译时出现了太多问题,我无法调试代码。使代码保持打开状态还有很多其他问题,如依赖项和公钥令牌不匹配/版本不匹配。 所以我重新编写了所需的函数
    
    byte[] bytes = Encoding.Unicode.GetBytes(plaintext);
    byte[] hash = provider.CreateHash(bytes);
    CryptographyUtility.GetRandomBytes(bytes);
    return Convert.ToBase64String(hash);
    
    
    
    this.AddSaltToPlainText(ref salt, ref plaintext);
    byte[] hash = this.HashCryptographer.ComputeHash(plaintext);
    this.AddSaltToHash(salt, ref hash);
    return hash;
    
    
    
    if (!this.saltEnabled)
        return;
      if (salt == null)
        salt = CryptographyUtility.GetRandomBytes(16);
      plaintext = CryptographyUtility.CombineBytes(salt, plaintext);
    
    
    <securityCryptographyConfiguration>
    <hashProviders>
      <add algorithmType="System.Security.Cryptography.SHA1Managed, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
        saltEnabled="true" type="Microsoft.Practices.EnterpriseLibrary.Security.Cryptography.HashAlgorithmProvider, Microsoft.Practices.EnterpriseLibrary.Security.Cryptography, Version=2.0.0.0, Culture=neutral, PublicKeyToken=06300324c959bce8"
        name="ABC" />
    </hashProviders>
    
    //Because of the random salt added, each time you hash a password it will create a new result.
        public static string GetHashedValue(string password)
        {
            //this will create a new hash?
            //Hashed Password Formula: Base64(salt + Sha1(salt + value))
            var crypto = new SHA1CryptoServiceProvider();
            byte[] saltBytes = new byte[16];
            RandomNumberGenerator.Create().GetBytes(saltBytes); 
    
            byte[] checkPasswordBytes = Encoding.Unicode.GetBytes(password);
            byte[] tempResult = crypto.ComputeHash(saltBytes.Concat(checkPasswordBytes).ToArray()); //ComputeHash(salt + value)
            byte[] resultBytes = saltBytes.Concat(tempResult).ToArray();  //salt + ComputeHash(salt + value)
    
            return Convert.ToBase64String(resultBytes);
        }
    
    public static bool IsPasswordValid(string passwordToCheck, string savedPassword)
        {
            bool retVal = false;
    
            var crypto = new SHA1CryptoServiceProvider();
    
            //get the salt, which is part of the saved password. These are the first 16 bytes.
            byte[] storedPasswordBytes = Convert.FromBase64String(savedPassword);
            byte[] saltBytes = new byte[16];
            Array.Copy(storedPasswordBytes, saltBytes, 16);
    
            //hash the password that you want to check with the same salt and the same algoritm:
            byte[] checkPasswordBytes = Encoding.Unicode.GetBytes(passwordToCheck);
            byte[] tempResult = crypto.ComputeHash(saltBytes.Concat(checkPasswordBytes).ToArray()); //ComputeHash(salt + value)
            byte[] resultBytes = saltBytes.Concat(tempResult).ToArray();  //salt + ComputeHash(salt + value)
            string resultString = Convert.ToBase64String(resultBytes);
    
            if (savedPassword == resultString)
            {
                retVal = true;
            }
    
            return retVal;
        }
    
       const saltLength = 16;
    const cryptedPwd = 'm2gFufL1WYJEcjdgnu4Eo0qXHM8+whC75AMnYxCS+uRbiS4OBy5+4TKNQbiSJyTG';
    const pwd = 'myPassword';
    
    let binaryPwd = Buffer.from(cryptedPwd, 'base64');
    
    let salt = binaryPwd.slice(0, saltLength);
    let saltBuffer = [...salt];
    let bytePwd = Buffer.from(pwd, 'utf16le');
    let pwdBuffer = [...bytePwd];
    let saltAndPwd = saltBuffer.concat(pwdBuffer);
    let saltAndPwdBinary = Buffer.from(saltAndPwd).toString('utf16le');
    let cryptedBuffer = Array.from(crypto.createHash('sha256').update(saltAndPwdBinary, 'utf16le').digest());
    let concatCryptedBuffer = saltBuffer.concat(cryptedBuffer);
    let cryptedString = Buffer.from(concatCryptedBuffer).toString('base64');
    
    console.log('cryptedString : ' + cryptedString);
    console.log('same : ' + (cryptedString == cryptedPwd));
    console.log('');