抗量子签名示例
本例将演示 SPHINCS+ 签名库。它实现了基于哈希的签名,其设计目标是具备抗量子能力。请注意,截至 2018 年 11 月,SPHINCS+ 签名仍处于试验阶段。由于它们相对较新,尚未得到密码学家的充分分析,其安全性也尚未获得无可争议的证明。
下面演示用于基于哈希的数字签名的 SPHINCS+ 密码系统,更准确地说,是它的两种配置:
- SPHINCS+-128f – 64 字节私钥、32 字节公钥、~16.9KB 签名;密钥生成即时完成,签名速度快(< 1 秒),验证即时完成;安全级别为 128 位
- SPHINCS+-128s – 64 字节私钥、32 字节公钥、~ 8KB 签名;密钥生成即时完成,签名速度慢(~ 数秒),验证即时完成;安全级别为 133 位
要安装适用于 Python 的官方 SPHINCS+ 签名库 PySPX,请使用以下命令:
pip install pyspx
pyspx 软件包在 Windows 中(使用 Visual C++ 编译器时)可能无法编译,因此推荐使用 Linux(或者 PythonAnywhere、Repl.it 等 Python 虚拟机)。
下面使用 Python 示例演示采用 shake256_128f 参数集的 SPHINCS+ 签名(SPHINCS+,使用 SHAKE256-128 作为哈希函数,并采用快速模式):
import pyspx.shake256_128f as sphincs
import os, binascii
# Key generation: private + public key
seed = os.urandom(sphincs.crypto_sign_SEEDBYTES)
public_key, secret_key = sphincs.generate_keypair(seed)
print("Public key:", binascii.hexlify(public_key))
print("Private key:", binascii.hexlify(secret_key))
# Sign message and verify signature
message = b'Message for SPHINCS+ shake256_128f signing'
signature = sphincs.sign(message, secret_key)
valid = sphincs.verify(message, signature, public_key)
print("Message:", message)
print("Signature:", binascii.hexlify(signature))
print("Signature valid?", valid)
# Verify tampered message + signature
message = b'Tampered msg'
valid = sphincs.verify(message, signature, public_key)
print("Tampered message:", message)
print("Tampered signature valid?", valid)
运行上述代码示例:https://repl.it/@nakov/SPHINCSplus-signature-in-Python。
上述代码运行得很快,不到一秒即可完成。其输出如下:
Public key: b'73004fe93b401a2ab9e0f3ccebbb9d8fe38b0080033eb80a9ecd8028451bbbcb'
Private key: b'e2e5f5f4574cc2774ee4b30c21f4067321a619d54dd92e539b6adcf6f932c6c573004fe93b401a2ab9e0f3ccebbb9d8fe38b0080033eb80a9ecd8028451bbbcb'
Message: b'Message for SPHINCS+ shake256_128f signing'
Signature: b'fbdb1d37371b7f18fb8b1cb2ae452f2aea3c17b4b5c2cee564ee6617915ba3aa813c1eb418e8b2e191b6d15bbcbf47bea4682d1a842dc8b8f589c8108bdea153506e1ee245530b2ad3cec6a6955bc691c8b4aa777...cc276446ea6'
Signature valid? True
Tampered message: b'Tampered msg'
Tampered signature valid? False
从上述输出可以看出,对于 shake256_128f 参数集,SPHINCS+ 公钥很短(32 字节),私钥也很短(64 字节),但签名很大(16976 字节,~16.9 KB,上面仅显示了一部分)。这使 SPHINCS+ 签名并不是后量子签名的理想解决方案。此外,其签名计算速度明显慢于 RSA 和 ECDSA。
下面调整 SPHINCS+ 算法参数,使用 shake256_128s 参数集(SPHINCS+,使用 SHAKE256-128 作为哈希函数,并采用慢速模式)来获得更短的签名。这种较短的签名会使签名计算耗时增加数倍。按如下方式更改算法参数(实际上只有第一行的更改至关重要):
import pyspx.shake256_128s as sphincs
import os, binascii
# Key generation: private + public key
seed = os.urandom(sphincs.crypto_sign_SEEDBYTES)
public_key, secret_key = sphincs.generate_keypair(seed)
print("Public key:", binascii.hexlify(public_key))
print("Private key:", binascii.hexlify(secret_key))
# Sign message and verify signature
message = b'Message for SPHINCS+ shake256_128s signing'
signature = sphincs.sign(message, secret_key)
valid = sphincs.verify(message, signature, public_key)
print("Message:", message)
print("Signature:", binascii.hexlify(signature))
print("Signature valid?", valid)
# Verify tampered message + signature
message = b'Tampered msg'
valid = sphincs.verify(message, signature, public_key)
print("Tampered message:", message)
print("Tampered signature valid?", valid)
运行上述代码示例:https://repl.it/@nakov/SPHINCSplus-signature-smaller-size-in-Python。
现在生成的签名更小(~ 8KB,下面仅显示了一部分),但生成签名的时间大幅增加(签名需要几秒钟,密钥生成和签名验证仍然很快):
Public key: b'd2ac35f1a6124b4a45d196b3fa9292b9bb3245f8c0dbdb586ea5879eb22487f0'
Private key: b'8dc8e4cf3dc6fd28cb14a46fa2350dd41acdfb351c49e8caea86ca95ee2184ddd2ac35f1a6124b4a45d196b3fa9292b9bb3245f8c0dbdb586ea5879eb22487f0'
Message: b'Message for SPHINCS+ shake256_128s signing'
Signature: b'a92bbecfae693e3fdc15fa0f5d9f4a941a7ae98822be6ca0d194db3930e45fe5cb429b29757f4539dcb444652224d3ab0d0fca2c792b7acf597b632880bf9a6feb0dc444491a9e9ef902...0abeb7a42cb262'
Signature valid? True
Tampered message: b'Tampered msg'
Tampered signature valid? False
可以得出结论,在后量子计算时代,SPHINCS+ 签名等抗量子数字签名算法可能会取代 ECDSA 和 EdDSA,但它们仍有一个很大的缺点:签名体积庞大。对于某些应用,签名大小可能不是问题;但对另一些应用而言,更短的签名至关重要。