我需要从一组嵌套的配置值中创建标识令牌。该令牌可以成为URL的一部分,因此为了使处理更容易,它应只包含十六进制数字(或类似的内容)。配置值是嵌套元组,其元素为可哈希类型,例如
我的想法是使用内置的
这将产生长度可变的令牌,但这并不重要。然而,令我困扰的是令牌可能包含一个负号,因为
int
、bool
、str
等。我的想法是使用内置的
hash()
函数,因为即使配置结构改变,它仍将继续工作。这是我的第一次尝试:def token(config):
h = hash(config)
return '{:X}'.format(h)
这将产生长度可变的令牌,但这并不重要。然而,令我困扰的是令牌可能包含一个负号,因为
hash()
的返回值是有符号整数。
为了避免符号,我想到了以下解决方法,即向哈希值添加一个常量。
这个常量应该是取值范围的一半,hash()
的取值范围取决于平台(例如32位/64位系统)。HALF_HASH_RANGE = 2**(sys.hash_info.width-1)
这是一个明智且可移植的解决方案吗?还是说我会被它绊倒?
我还看到有人建议使用struct.pack()
(它返回一个bytes
对象,可以在其上调用.hex()
方法),但它也需要预先知道哈希值的范围(以选择正确的格式字符)。
补充说明:
加密强度或偶然碰撞都不是问题。
hashlib
库在此场景中的缺点是需要编写转换器来遍历输入结构并将所有内容转换为bytes
表示形式,这很繁琐。
mask = (1<<sys.hash_info.width) - 1
h = hash(config) & mask
。 - PM 2Ring[i&0xf for i in range(-8,8)]
。顺便说一句,这是将有符号整数转换为无符号整数的相当标准的Python习语。 - PM 2Ringrepr()
来序列化整个结构!为什么我之前没有想到呢... - lenzhash()
函数——它不能保证在所有的Python版本中都以相同的方式计算,并且在某个时候,字符串哈希开始有意地在每个程序运行时随机化。 - jasonharper