Skip to main content

Python Winternitz 一次性签名(+)实现

项目描述

构建状态 覆盖状态 文件状态 执照:麻省理工学院

Winternitz 一次性签名

Winternitz 一次性签名方案的 Python 实现

描述

Winternitz 一次性签名是 Lamport 一次性签名的扩展。这个python包可以用来执行WOTS操作,包括密钥生成、签名生成和签名验证。目前已实施 WOTS 和 WOTS+。

介绍

Lamport 在 1979 年发明了一种算法,该算法允许人们使用加密安全的单向函数创建一次性签名。它是 Winternitz 一次性签名算法的基础。Winternitz 增加了调整时间复杂度和空间复杂度之间权衡的可能性。

Lamport一次性签名方案

Lamport 建议为将要签名的消息的每一位创建两个密钥。该位可以采用的每个值一个。为了派生验证密钥,每个密钥都被散列一次。现在您有一个密钥和一个验证密钥,它由m个 2 元组值组成,其中m是消息的位数。验证密钥已发布。签名由m价值观。对于消息的每一位,您从相应的密钥中释放一个密钥,具体取决于该位的值。所有这些密钥构成了消息的签名。验证器对您的每个密钥进行一次哈希处理,并将其与该位置的一个验证密钥进行比较,具体取决于该位的值。当且仅当所有派生的验证密钥与您在 2 元组的正确位置(由该位的值确定)处发布的验证密钥匹配时,签名才有效。该算法非常快(与现有的 PQC 算法相比),但签名大小很大。

温特尼茨扩展

Winternitz 扩展了 lamports 算法,提供了决定将有多少位一起签名的可能性。这些位可以表示的数字量称为 Winternitz 参数 ( w = 2^{bits} )。这种方法提供了巨大的优势,即该算法的用户可以选择时间和空间的权衡(速度或存储容量是否更相关)。将要签名的消息的指纹被分成ceil(log_2(w))位组。这些组中的每一个都获得一个密钥。每个验证密钥是通过将每个组的密钥散列2^{w-1}​​次得出的。所有的验证密钥都会被公开,代表一个统一的验证密钥。签名消息时,消息的指纹被分成几组ceil(log2(w))位。为了创建签名,每个位组的私钥被哈希bitgroup_value次,其中bitgroup_value是位组的值。此外,附加了一个(逆和)校验和,它拒绝了中间人攻击。校验和根据签名计算,分成ceil(log2(w))位的位组,并签名。为了验证签名,首先将消息的指纹分成ceil(log2(w) 个比特的比特组。基本思想是取每个比特组的签名,从中计算验证密钥,最后比较已发布的验证密钥。由于签名是经过哈希 处理的bitgroup_value时间,从签名计算验证密钥所需要做的就是将签名散列2^{w-1} ​​- bitgroup_value - 1次。除了验证消息之外,验证者还必须计算校验和并进行验证。

设置

要求:Python >= 3.4

安装包:pip install winternitz
安装测试工具:pip install winternitz[TEST]
安装 linter(用于毒性测试):pip install winternitz[LINT]
安装文档工具:pip install winternitz[DOCS]
安装一切:pip install winternitz[ALL]

测试

没有毒物(没有 linter 检查):python setup.py test
使用毒药:python -m tox

生成文档

python setup.py 文档

用法

Winternitz包含一个名为signatures的模块。在这个包中,您可以找到 WOTS 和 WOTSPLUS 类。这些类可以开箱即用地签署或验证消息

WOTS

import winternitz.signatures
# Create signature and verify it with the same object
wots = winternitz.signatures.WOTS()
message = "My message in bytes format".encode("utf-8")
sig = wots.sign(message)
success = wots.verify(message=message, signature=sig["signature"])
print("Verification success: " + str(success))
# Output: Verification success: True

如果您在 WOTS 的构造函数中没有指定任何值,它将使用 Winternitz 参数 16 和哈希函数sha512作为默认参数。私钥将由熵生成。在通过wots.pubkey或在 wots.sign(message)函数调用返回的 dict 中收到公钥后,您将其发布。确认它没有被修改。在最好的情况下,通过应用程序的设计,修改您的公钥的中间人攻击是不可能的。最后一步是发布您的消息以及wots.sign(message)返回的字典中的所有信息,除了公钥(因为它已经发布)。发布指纹是可选的,因为它对于签名验证不是必需的。签名字典包含以下值:

{
    "w":            winternitz parameter (Type: int),
    "fingerprint":  message hash (Type: bytes),
    "hashalgo":     hash algorithm (Type: str),
    "digestsize":   hash byte count (Type: int),
    "pubkey":       public key (Type: List[bytes]),
    "signature":    signature (Type: List[bytes])
}

使用该数据,其他人可以验证您的消息的真实性:

# Another person or machine wants to verify your signature:
# get required hash function by comparing the name
# published with local implementaitons
if sig["hashalgo"] == "openssl_sha512":
    hashfunc = winternitz.signatures.openssl_sha512
elif sig["hashalgo"] == "openssl_sha256":
    hashfunc = winternitz.signautres.openssl_sha256
else:
    raise NotImplementedError("Hash function not implemented")

wots_other = winternitz.signatures.WOTS(w=sig["w"], hashfunction=hashfunc,
                                        digestsize=sig["digestsize"], pubkey=sig["pubkey"])
success = wots_other.verify(message=message, signature=sig["signature"])
print("Verification success: " + str(success))
# Output: Verification success: True

在某些情况下,可能不希望使用正在执行的 WOTS 对象中的公钥来验证派生的公钥。例如,当验证发生在包装结构(如 XMSS 树)中时,可能就是这种情况。在这种情况下,可以使用函数 wots.getPubkeyFromSignature(message=message, signature=signature)从消息和签名中派生公钥

WOTSPLUS

import winternitz.signatures
wotsplus = winternitz.signatures.WOTSPLUS()
message = "My message in bytes format".encode("utf-8")
sig = wotsplus.sign(message)
success = wotsplus.verify(message=message, signature=sig["signature"])
print("Verification success: " + str(success))
# Output: Verification success: True

如果您在 WOTSPLUS 的构造函数中没有指定任何值,它将使用 Winternitz 参数 16 并且哈希函数默认为sha256。它还需要一个伪随机函数,默认为HMAC-sha256,以及一个同样由熵生成的种子。有关函数及其参数的更多信息,请访问本文档中的模块参考。由于 WOTS+ 使用伪随机函数和种子来派生签名和公钥,因此它们也必须被发布。除了 WOTS 的签名之外,返回的 dict 还包含以下值:

{
    # ...
    "prf":          pseudo random function (Type: str),
    "seed":         Seed used in prf (Type: bytes)
}

除了在 WOTS 中指定的参数之外,这些参数还必须在 WOTSPLUS 的构造函数中指定。

杂项

WOTS 类具有一些将在以下部分中解释的特性。

完全可配置

WOTS 类是完全可参数化的。您可以指定描述算法的论文中指定的任何内容,包括 Winternitz 参数、散列函数、伪随机函数 (WOTSPLUS)、种子 (WOTSPLUS)、私钥和公钥。同时指定私钥和公钥会导致公钥被丢弃。

按需生成密钥

如果未指定私钥或未指定公钥,则它们将设置为 None。wots+ 中的种子也是如此。只有在需要它们时,才会生成或派生它们。这意味着只要您不执行repr(obj)str(obj)obj1 == obj2obj1 != obj2obj.pubkeyobj.privkeyobj.sign(...)obj。 verify(...),其中 obj 是 WOTS 对象,键将保持为无。

WOTS 对象的代码表示

您可以调用repr(obj),其中 obj 是 WOTS 对象,以获取包含初始化另一个对象的所有信息的代码行,以便它等于 obj。执行obj2 = eval(repr(obj)) 会执行 repr(obj) 返回的代码,最终将其副本存储在obj2中。

人类可读的字符串表示

您可以调用str(obj)来获取包含该对象的人类可读表示的字符串。

对象比较

您可以比较此类obj1 == obj2obj1 != obj2中的两个对象

优化

代码经过精心编写以减少执行时间。它肯定不是完美的并且仍然可以优化,进一步的时间关键部分可以编码为 C 扩展,但是在当前状态下它应该提供相当有效的实现。它定义了__slots__以减少类内的执行时间和存储要求。并行化的实现是有计划的,但它只在使用巨大的 Winternitz 参数时才有用,因为如果你生成一个新进程,python 只能并行执行代码,并且派生一个新的 python 解释器的开销是不可忽略的。

笔记

这个项目是使用 PyScaffold 3.1 建立的。有关 PyScaffold 的详细信息和使用信息,请参阅https://pyscaffold.org/

项目详情


下载文件

下载适用于您平台的文件。如果您不确定要选择哪个,请了解有关安装包的更多信息。

源分布

Winternitz-1.0.2.tar.gz (32.6 kB 查看哈希)

已上传 source

内置分布

Winternitz-1.0.2-py2.py3-none-any.whl (12.5 kB 查看哈希

已上传 py2 py3