【发布时间】:2022-12-14 23:07:41
【问题描述】:
我有一个代表一个独特的现实世界对象的类,它的名字是个人身份信息(如果你感兴趣的话,是一个车牌)所以作为基本的第一步,我将散列名称并使用它。 (我知道 - 需要盐等 - 这只是一个基础)
我有一个测试,它使用固定输入(测试名称 - “A”)实例化对象,并断言 Id(散列输出的 Base 64 字符串)符合预期。但是,它偶尔会失败(!!)
我进行了更深入的挖掘,这里是一个条件断点的屏幕截图,该断点仅在哈希输出不正常时才会中断。输入仍然符合预期('bytes' 变量包含 { 65 },但输出不同于正常的 sha384 输出哈希(通常为“rRSq8lAgvvL9Tj617AxQJyzf1mB0sO0DfJoRJUMhqsBymYU3S+6qW4ClBNBIvhhk”)
第 19-25 行被分开了一点以便于调试,但除此之外,这个类应该是这样的。
任何关于这是如何可能的线索都将非常受欢迎。运行 Windows 11,使用 .NET 7 和最新版本的 Visual Studio Enterprise。
如果有人想尝试重现它,这里是代码(注意它不一致:它只是偶尔)
using System.Security.Cryptography;
using System.Text;
namespace Domain.Models.Object
{
/// <summary>
/// One-way identifier
/// </summary>
public record ObjectIdentifier
{
private static SHA384 hash = SHA384.Create();
public ObjectIdentifier(string name)
{
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
var bytes = Encoding.UTF8.GetBytes(name);
Id = Convert.ToBase64String(hash.ComputeHash(bytes));
int x = 0;
x++;
}
public string Id { get; init; }
public override string ToString()
{
return Id;
}
}
}
这是测试:
[Fact]
public void ObjectIdentifier_AsExpected()
{
// arrange
var obj = new ObjectIdentifier("A");
// assert
Assert.Equal("rRSq8lAgvvL9Tj617AxQJyzf1mB0sO0DfJoRJUMhqsBymYU3S+6qW4ClBNBIvhhk", obj.Id);
}
我还注意到新的哈希值并不始终相同:这是另一个失败的结果,输出与之前的屏幕截图不同:
我还注意到将它添加到第 20 行会导致不一致完全停止发生...... 不幸的是,这不是一个合适的修复方法 :P
Debug.Assert(bytes.Length == 1 && bytes[0] == 65)
更新无效输出似乎只是上面提供的两个,我没有观察到任何其他变体。
此外,将其更改为类(而不是记录)也没有任何区别。
我也在测试控制台应用程序中观察到这种效果,该应用程序只提供了两个标识符,但实际上输出了两个以上的哈希值:
【问题讨论】:
-
可能是线程问题吗?
HashAlgorithm.ComputeHash()不是线程安全的。你可以通过在你的类中添加一个锁定对象字段static object locker = new object();并在你调用hash.ComputeHash(bytes)时锁定它来测试它 -
好点,我会试一试并相应地更新。我的测试设置为并行运行... - 谢谢 :)
-
是的,就是这样 - 再次感谢 :)
标签: c# .net cryptography