📜  在Python具有可变哈希大小的全域哈希

📅  最后修改于: 2021-05-04 18:40:03             🧑  作者: Mango

密码哈希函数是一类特殊的哈希函数,具有某些属性,使其适合用于密码学。它是一种数学算法,可将任意大小的数据映射到固定大小的位字符串(哈希函数),该字符串也被设计为单向函数,即不可行求反的函数。在本文中,让我们了解一种具有可变哈希大小的哈希类型。

传统的RSA签名方案基于以下步骤序列:

  1. 获取要进行数字签名的消息-M
  2. 使用SHA或其他某种哈希算法来生成消息摘要– H = Hash(M)
  3. 使用签名者的私钥对消息摘要进行加密。加密结果是消息的签名– S = E(PrivateKey,H)

上述方案中的一个潜在缺陷是RSA系统最终未得到充分利用。让我们假设RSA模数约为2048位。这意味着输入可以是最多2048位的任何值。但是,在签名方案中,RSA系统的输入始终是相同的大小,即哈希摘要的大小。因此,例如,如果在签名方案中使用SHA-512 ,则RSA函数的所有输入将始终为512位。这使得大部分(在这种情况下> 99% )RSA输入空间未被利用。由于输入空间使用不足,其结果是降低了RSA系统的总体安全级别。

RSA签名方案中的全域散列(FDH)方案通过将消息散列到RSA密码系统的整个域上来缓解这种未充分利用的情况。因此,FDH的目标是:

实现可以产生任意大小的摘要的函数的两种基本方法是:

  1. 反复对消息进行哈希处理(稍作修改)并进行串联
  2. 使用可扩展输出函数(XOF)哈希方法

串联重复哈希

尽管传统的哈希算法(例如SHA1,SHA256,SHA512)几乎没有足够的范围来覆盖RSA系统的输入域,但我们可以通过重复应用这些哈希函数来构建完整的域哈希方法。标准哈希函数(例如SHA512)反复应用于消息,每次都将结果串联在一起。直到完成所需的位数为止。

为了引入哈希函数的随机行为,而不是重复哈希相同的消息,在执行哈希之前,每次迭代都会对消息进行一些修改。这样的修改的一个示例是在哈希之前将迭代计数连接到消息。因此,FDH函数实现为:
   FDH(m) =\ h(m\lvert\lvert0)\ ||\ h(m||1)\ ||\ h(m||2)\ || \dotso

如果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))
输出:

使用可扩展输出函数(XOF)哈希方法

可扩展输出函数是一类哈希函数,与传统的哈希函数不同,它可以在消息摘要中生成任意大的比特序列。这与由固定输出大小定义的常规散列函数形成强烈反差。在最近引入的SHA-3方案中,使用SHAKE128SHAKE256算法提供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)))

输出:

注意:上面的代码不会在在线IDE上运行,因为在线IDE缺少Crypto库。