我正在寻找一种从Ruby中的json字符串生成SHA-512哈希的方法,独立于其中元素的位置,并且独立于嵌套,数组,嵌套数组等。我只想将原始数据及其密钥哈希。
我尝试了一些将JSON转换为ruby哈希的方法,通过键对它们进行深度排序,将所有内容追加到一个长字符串中并对其进行哈希处理。但我敢打赌,我的解决方案不是最有效的解决方案,并且必须有更好的方法来实现这一目标。
修改
到目前为止,我将JSON转换为Ruby哈希。然后我尝试使用此函数来获得规范表示:
def self.canonical_string_from_hash value, key=nil
str = ""
if value.is_a? Hash
value.keys.sort.each do |k|
str += canonical_string_from_hash(value[k], k)
end
elsif value.is_a? Array
str += key.to_s
value.each do |v|
str += canonical_string_from_hash(v)
end
else
str += key ? "#{key}#{value}" : value.to_s
end
return str
end
但我不确定,如果这是一种很好的有效方法。
例如,这个哈希
hash = {
id: 3,
zoo: "test",
global: [
{ukulele: "ringding", blub: 3},
{blub: nil, ukulele: "rangdang", guitar: "stringstring"}
],
foo: {
ids: [3,4,5],
bar: "asdf"
}
}
转换为此字符串:
barasdfids345globalblub3ukuleleringdingblubguitarstringstringukulelerangdangid3zootest
答案 0 :(得分:1)
但我不确定,如果这是一种很好的有效方法。
取决于你想要做什么。您的规范/等效结构需要表示对您来说重要的比较。如果您考虑具有不同结构但相同字符串值的两个项目,则删除对象结构等细节是有意义的。
根据您的评论,您正在尝试签署从一个系统转移到另一个系统的请求。换句话说,您需要安全性,而不是用于其他目的的相似度或数字指纹。因此,等效请求是影响您要保护的处理的所有方式相同的请求。锁定在两个系统之间传输的原始数据字节更简单,也更安全。
在这种情况下,您的整个方法需要重新思考。其原因可能最好在security.stackoverflow.com
上讨论然而,简而言之:
使用HMAC例程(HMAC-SHA512),它是专为您的目的而设计的。而不是盐,这使用了一个秘密,这实际上是相同的事情(实际上你需要在你的实现中保持你的盐秘密,这对于一种叫盐的东西来说是不寻常的),但是已经与SHA结合了这种方式可以使其对几种攻击形式具有弹性,可以防止简单连接,然后是SHA。最糟糕的是,可以扩展数据并在处理时生成相同的SHA,而无需知道salt 。换句话说,攻击者可以接受已知的有效请求并使用它来伪造其他请求,这些请求将通过您的安全检查。您建议的解决方案看起来很容易受到这种形式的攻击。</ p>
解压缩请求并分析详细信息以获取请求的“规范”视图不是必需的,并且还会降低解决方案的安全性。这样做的唯一原因是,由于某种原因,一旦将请求序列化为JSON,您就无法处理该请求,并且只能在两端系统的一端或另一端使用反序列化请求。如果这纯粹是一种知识或方便的事情,那么解决这个问题,而不是尝试使用SHA-512推出自己的安全协议。
您应该对请求进行签名,并针对完全序列化的JSON字符串检查签名。如果您需要对“中间人”攻击中的数据进行反序列化,那么您可能已经通过解析器暴露了一些攻击。您应该在对任何数据处理进行任何数据处理之前拒绝可疑请求。
TL; DR - 虽然不是您问题的直接答案,但正确的解决方案是不要编写此代码 。相反,您需要将您的安全签名代码放在您需要相互信任的两个服务的细节之内。