C# 如何在Python中重现System.Security.Cryptography.SHA1管理结果
交易是这样的:我正在将一个.NET网站迁移到Python。我有一个数据库,使用System.Security.Cryptography.SHA1Managed实用程序对密码进行哈希处理 我使用以下代码在.NET中创建哈希: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
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)来重现哈希过程,但我没有运气
我的问题是:
谢谢 根据,这应该类似于sha1(密码+盐)+盐。SHA-1输出为20字节,因此对于48字节,这应该是28字节的salt,而不是8字节的salt,除非使用某种编码。当使用
字符串CreateHash(字符串,字符串)
重载时,会发生以下情况:
很抱歉回复得太晚,但是我在尝试复制企业库的加密块中使用的SHA1哈希逻辑时遇到了类似的情况,但是使用Java 要回答您的每个问题,请执行以下操作:
- 调用
Cryptographer.CreateHash(“MYHasher”,value)代码> 其中,
是在配置块中指定的已配置的“MYHasher”
实例提供程序的名称,System.Security.Cryptography.SHA1Managed
是要哈希的字符串value
- 上述方法调用
,其中提供了已解析的CreateHash(IHashProvider提供程序,字符串明文)
。在此方法中,运行以下代码:IHashProvider
- 开始时传递的
参数(现在是值
参数)使用Unicode编码转换为字节数组纯文本
- 接下来,使用上面创建的字节数组调用SHA1哈希提供程序的
方法。在此方法中,将执行以下步骤:CreateHash(bytes)
this.createHashWithAlt(纯文本,(字节[])null)调用code>,其中
是一个字节数组,包含作为字符串在堆栈顶部传入的原始明文
。第二个参数是salt字节数组(为null)。在此方法中,调用以下代码:值
是有关如何对提供的文本进行盐析的第一条线索。在此方法中,运行以下代码:this.AddSaltToPlainText(ref salt,ref plaintext)
变量由配置块中的this.saltEnabled
初始化。如果为true,并且您没有提供salt,那么将为您生成一个包含16个随机字节的字节数组(通过调用外部C API)saltEnabled=“true”
- 然后,
变量的前面加上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字符串表示形式
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('');