密码哈希函数是一类特殊的哈希函数,具有某些属性,使其适合用于密码学。它是一种数学算法,可将任意大小的数据映射到固定大小的位字符串(哈希函数),该字符串也被设计为单向函数,即不可行求反的函数。在本文中,让我们了解一种具有可变哈希大小的哈希类型。
传统的RSA签名方案基于以下步骤序列:
- 获取要进行数字签名的消息-M
- 使用SHA或其他某种哈希算法来生成消息摘要– H = Hash(M)
- 使用签名者的私钥对消息摘要进行加密。加密结果是消息的签名– S = E(PrivateKey,H)
上述方案中的一个潜在缺陷是RSA系统最终未得到充分利用。让我们假设RSA模数约为2048位。这意味着输入可以是最多2048位的任何值。但是,在签名方案中,RSA系统的输入始终是相同的大小,即哈希摘要的大小。因此,例如,如果在签名方案中使用SHA-512 ,则RSA函数的所有输入将始终为512位。这使得大部分(在这种情况下> 99% )RSA输入空间未被利用。由于输入空间使用不足,其结果是降低了RSA系统的总体安全级别。
RSA签名方案中的全域散列(FDH)方案通过将消息散列到RSA密码系统的整个域上来缓解这种未充分利用的情况。因此,FDH的目标是:
Hash a message using a function whose image-size/digest-size equals the size of the RSA modulus
实现可以产生任意大小的摘要的函数的两种基本方法是:
- 反复对消息进行哈希处理(稍作修改)并进行串联
- 使用可扩展输出函数(XOF)哈希方法
串联重复哈希
尽管传统的哈希算法(例如SHA1,SHA256,SHA512)几乎没有足够的范围来覆盖RSA系统的输入域,但我们可以通过重复应用这些哈希函数来构建完整的域哈希方法。标准哈希函数(例如SHA512)反复应用于消息,每次都将结果串联在一起。直到完成所需的位数为止。
为了引入哈希函数的随机行为,而不是重复哈希相同的消息,在执行哈希之前,每次迭代都会对消息进行一些修改。这样的修改的一个示例是在哈希之前将迭代计数连接到消息。因此,FDH函数实现为:
如果SHA512哈希被计算并连接了N次,则整个哈希将具有N * 512的位大小。假设该值大于所需的位数“ K” ,我们可以提取前K个位,以获得所需的长度哈希。
下面是上述方法的实现:
# Python program to demonstrate
# repeated hashing with
# concatenation
import binascii
from math import ceil
from hashlib import sha256
# Function to perform Full Domain
# Hash of 'message' using
# SHA512 with a digest of
# N bits
def fdh(message, n):
result = []
# Produce enough SHA512 digests
# to make a composite digest
# greater than or equal to N bits
for i in range(ceil(n / 256)):
# Append iteration count
# to the message
currentMsg = str(message) + str(i)
# Add currrent hash to results list
result.append(sha256((currentMsg).encode()).hexdigest())
# Append all the computed hashes
result = ''.join(result)
# Obtaining binary representating
resAsBinary = ''.join(format(ord(x), 'b') for x in result)
# Trimming the hash to the
# required size by taking
# only the leading bits
resAsBinary = resAsBinary[:n]
# Converting back to the
# ASCII from binary format
return binascii.unhexlify('00%x' % int(resAsBinary, 2)).hex()
# Driver code
if __name__ == '__main__':
# Message to be hashed
message = "GeeksForGeeks"
# Generate a 600 bit
# hash using SHA256
print(fdh(message, 600))
00cf161c36df4db9e30d79cf9cb3d72e1934cbaeb9eb8638f0d71f1872679e1df9c3932c77c70c98efa64d34e3166c5b698738b36d9b36b87261c5ae3c61873c98e19b362db1c73658f0e4c9
使用可扩展输出函数(XOF)哈希方法
可扩展输出函数是一类哈希函数,与传统的哈希函数不同,它可以在消息摘要中生成任意大的比特序列。这与由固定输出大小定义的常规散列函数形成强烈反差。在最近引入的SHA-3方案中,使用SHAKE128和SHAKE256算法提供XOF。它们遵循海绵构造的一般特性。海绵函数可以生成任意长度的输出。如FIPS 202的A.1和A.2节所述,其名称中的128和256表示其最大安全级别(以位为单位)。
为了在Python利用SHA-3的功能,可以如下使用PyCryptodome库:
# Python program to demonstrate
# the SHA-3 algorithm
from Crypto.Hash import SHAKE256
from binascii import hexlify
# Instantiate the SHAKE256 object
shake = SHAKE256.new()
# Set the message to be hashed
shake.update(b'GeeksForGeeks')
# Print a hash output of 50 bits size
print(hexlify(shake.read(50)))
输出:
b’65d6df8d88198de69b3cf59b859d72971b93f102ca20af812b931714a558c7a134cb3bb085835f470c890bd1d50928355358′
注意:上面的代码不会在在线IDE上运行,因为在线IDE缺少Crypto库。