如何将SHA1哈希字符串截断为32位字符串

3
我希望创建一个32位的字符串作为加密密钥。这个字符串/密钥应该从一个明文字符串中派生,例如:
'I am a string'

我的方法首先是将其哈希:

hashed_string = Digest::SHA1.hexdigest('I am a string') # => 'bd82fb0e81ee9f15f5929e0564093bc9f8015f1d'

然后只使用前32个字符:

hashed_string[0..31] # => 'bd82fb0e81ee9f15f5929e0564093bc9'

然而,我感觉必须有更好的方法,但我不确定是否存在两个输入字符串产生相似密钥的风险。
什么是更好的方法?我看到了this post,它提到了截断,但我在那里找不到满意的答案。

宝石pbkdf2在你的情况下可能很有用 - 因为通常人们使用这样的函数从口令派生密钥。 - Wand Maker
5
关于比特与字节,你似乎有些混淆。SHA1哈希值为160比特。hexdigest返回这些比特的十六进制表示。每个十六进制数字代表4比特,因此当你取前32个字符时,你得到了32×4=128比特。无论如何,是的,肯定有更好的方法,但首先我们必须知道你要解决什么问题。你想生成一个“加密密钥”,但是为了什么目的?你正在加密什么以及你如何加密它?为什么只有32比特(对于一个加密密钥来说非常短)? - Jordan Running
改变问题怎么样?“32位字符串”和“32个字符长度的字符串”是两个不同的东西。 - lcguida
此外,无论您对原始字符串进行何种操作,它都不会改变其成为弱密码的事实。它已经少于32位的熵。请参见https://xkcd.com/936/。 - Eric Duminil
1个回答

5
如果你想从你的(弱)密码中得到一个32位的字符串:
Digest::SHA1.digest('I am a string').unpack('B32').first
#=> "10111101100000101111101100001110"

同样的信息也可以用8个十六进制数字来显示:
Digest::SHA1.hexdigest('I am a string')[0,8]
#=> "bd82fb0e"

或者4个ASCII字符:
Digest::SHA1.digest('I am a string')[0,4]
#=> "\xBD\x82\xFB\x0E"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接