Protobuf的GetHashCode是不是到处都一样?
Is GetHashCode of Protobuf the same everywhere?
我注意到我从 .proto
文件生成的 C# class 中有 GetHashCode()
。为了使篡改数据更加困难,我想计算哈希码并将其与数据一起发送。然后我可以在目的地再次计算哈希值。
我的方法是在原型定义中有一个散列字段,但在计算散列之前,我将其保留为 0,计算它,将其放入并序列化。在目的地将记住哈希值,将其设为 0,然后计算新哈希值以检查完整性。
接收端是JavaScript:
- 目的地的哈希生成函数会产生相同的结果吗?
- 如果
.proto
文件更新了新字段,到处都会生成新的 class,旧消息的散列结果是否相同?
我知道MD5,但我认为它需要在二进制文件完成后生成,如果这样做我不能将MD5与数据一起包含。
我仍然会在此之上进行加密,但以防万一有人设法解密数据,他不能轻易更改其中的某些部分来欺骗接收者。
不,你不能那样使用 GetHashCode()
。它不是 protobuf 概念,而是存在于所有 .NET 托管类型中。首先,并不是每个对象都重写这个方法,如果不是,那么对于 class 它代表 reference/instance,而不是内容(就像 Equals
默认情况下所做的那样)。如果它被覆盖,那么在同一个应用程序域中每次都应该产生相同的值,但不要求它在不同的[=53]中产生相同的值=]秒。它是否确实取决于实现和您使用的确切框架(假设使用 string.GetHashCode
之类的东西)。
但另一个问题是 目标框架 中的代码没有匹配的方法,即使有:也无法访问相同的实现,例如string.GetHashCode
.
所以不:不要将其用于该目的。它不会那样做。
举个具体的例子:string.GetHashCode
之类的东西会根据 OS 和 .NET 版本 为同一字符串 生成不同的值。它甚至不会完全在 .NET 端点上执行您想要的操作。
作为一个简单的例子,考虑:
static void Main()
{
Console.WriteLine("abc".GetHashCode());
Console.WriteLine("abc".GetHashCode());
Console.WriteLine("abc".GetHashCode());
}
如果我 运行 这一次,我得到:
518228267
518228267
518228267
所以你可能会想 "ah, yes, GetHashCode()
gives the same value each time"。然而,它比这更微妙。在最新版本的 .NET 上,这是在应用程序启动 时播种的 ,所以如果我再次 运行 它,我会得到:
-177712234
-177712234
-177712234
然后
-59760352
-59760352
-59760352
等这样做部分是为了避免人们依赖 GetHashCode()
在 运行 之间是相同的,部分是为了防止人们能够使用已知具有相同哈希码的字符串集作为攻击矢量对字典施加压力(迫使它们使用回退行为)——例如 DDOS 攻击网络服务器。如果无法通过静态外部代码预测散列,则此攻击向量就会消失。
我注意到我从 .proto
文件生成的 C# class 中有 GetHashCode()
。为了使篡改数据更加困难,我想计算哈希码并将其与数据一起发送。然后我可以在目的地再次计算哈希值。
我的方法是在原型定义中有一个散列字段,但在计算散列之前,我将其保留为 0,计算它,将其放入并序列化。在目的地将记住哈希值,将其设为 0,然后计算新哈希值以检查完整性。
接收端是JavaScript:
- 目的地的哈希生成函数会产生相同的结果吗?
- 如果
.proto
文件更新了新字段,到处都会生成新的 class,旧消息的散列结果是否相同?
我知道MD5,但我认为它需要在二进制文件完成后生成,如果这样做我不能将MD5与数据一起包含。
我仍然会在此之上进行加密,但以防万一有人设法解密数据,他不能轻易更改其中的某些部分来欺骗接收者。
不,你不能那样使用 GetHashCode()
。它不是 protobuf 概念,而是存在于所有 .NET 托管类型中。首先,并不是每个对象都重写这个方法,如果不是,那么对于 class 它代表 reference/instance,而不是内容(就像 Equals
默认情况下所做的那样)。如果它被覆盖,那么在同一个应用程序域中每次都应该产生相同的值,但不要求它在不同的[=53]中产生相同的值=]秒。它是否确实取决于实现和您使用的确切框架(假设使用 string.GetHashCode
之类的东西)。
但另一个问题是 目标框架 中的代码没有匹配的方法,即使有:也无法访问相同的实现,例如string.GetHashCode
.
所以不:不要将其用于该目的。它不会那样做。
举个具体的例子:string.GetHashCode
之类的东西会根据 OS 和 .NET 版本 为同一字符串 生成不同的值。它甚至不会完全在 .NET 端点上执行您想要的操作。
作为一个简单的例子,考虑:
static void Main()
{
Console.WriteLine("abc".GetHashCode());
Console.WriteLine("abc".GetHashCode());
Console.WriteLine("abc".GetHashCode());
}
如果我 运行 这一次,我得到:
518228267
518228267
518228267
所以你可能会想 "ah, yes, GetHashCode()
gives the same value each time"。然而,它比这更微妙。在最新版本的 .NET 上,这是在应用程序启动 时播种的 ,所以如果我再次 运行 它,我会得到:
-177712234
-177712234
-177712234
然后
-59760352
-59760352
-59760352
等这样做部分是为了避免人们依赖 GetHashCode()
在 运行 之间是相同的,部分是为了防止人们能够使用已知具有相同哈希码的字符串集作为攻击矢量对字典施加压力(迫使它们使用回退行为)——例如 DDOS 攻击网络服务器。如果无法通过静态外部代码预测散列,则此攻击向量就会消失。