ecdsa加密签名库(纯python)

ecdsa的Python项目详细描述


纯python ecdsa

构建状态覆盖状态最新版本

这是ecdsa密码(椭圆曲线)的一个易于使用的实现 数字签名算法),纯用python实现,发布于 麻省理工学院的执照。使用此库,您可以快速创建密钥对(签名 密钥和验证密钥)、签名消息和验证签名。钥匙 签名很短,便于处理和合并 其他协议。

功能

这个库为5个 流行的NIST"套件B"GF(P)曲线,关键长度为192、224、256、384, 521位。这些曲线的"短名称",如openssl所知 工具(openssl ecparam--list_curves)是:prime192v1,secp224r1, prime256v1、secp384r1和secp521r1。它还包括使用的256位曲线 比特币,简称secp256k1。不包括其他曲线,但 再加一点也不难。

依赖关系

这个库只使用python。它需要python2.6或更高版本的 python2.x系列。它还与python3.2和3.3兼容。

要运行OpenSSL兼容性测试,必须在 $路径。这个版本已经在openssl 0.9.8o上测试成功 和1.0.0A。

速度

下表显示了此库生成密钥对所需的时间 (keygen=),对数据签名(sign=),并验证这些签名(verify=),打开 我的2008 Mac笔记本电脑。所有时间都以秒为单位。它还显示了 签名(字节):验证("public")密钥通常相同 长度作为签名,签名("私有")密钥是该长度的一半。使用"python setup.py speed"在您自己的计算机上生成此表。

  • NIST192P:siglen=48,keygen=0.160s,sign=0.058s,verify=0.116s
  • NIST224P:siglen=56,keygen=0.230s,sign=0.086s,verify=0.165s
  • nist256p:siglen=64,keygen=0.305s,sign=0.112s,verify=0.220s
  • NIST384P:siglen=96,keygen=0.801s,sign=0.289s,verify=0.558s
  • NIST521P:siglen=132,keygen=1.582s,sign=0.584s,verify=1.152s

比较,典型的ECDSA(Cuffto++)的质量C++实现 在2.88ms内计算NIST256P签名,在8.53ms内计算验证,关于 快30-40倍。

密钥和签名可以以不同的方式序列化(参见下面的用法)。 对于NIST192P密钥,三个基本表示需要 以下长度(字节):

to_string:  signkey= 24, verifykey= 48, signature=48
DER:        signkey=106, verifykey= 80, signature=55
PEM:        signkey=278, verifykey=162, (no support for PEM signatures)

历史记录

2006年,peter pearson在 发送给sci.crypt的消息,可从他的下载站点获得。2010, Brian Warner为这段代码编写了一个包装器,使它更容易 使用更安全。您正在查看此包装的自述文件。

测试

有四个测试套件,三个用于原始皮尔逊模块,还有一个 更多关于wrapp的信息呃.要运行它们,请执行以下操作:

python setup.py test

在我的2014款Mac Mini上,综合测试大约需要20秒才能运行。在一 2.4GHz P4 Linux盒,需要81秒。

py的一个组件通过 运行"openssl"cli工具。如果这个工具不在你的$路径上,你可以 想注释这个测试(最简单的方法是添加一行 "del openssl"到test_pyecdsa.py的末尾。

安全性

此库无法防止定时攻击。不允许攻击者 测量生成密钥对或签名消息所需的时间。 这个库依赖于一个强大的随机数源。不要用它 一个os.urandom()很弱的系统。

用法

首先创建一个signingkey。通过传递 在数据字符串中并获取签名(也是字符串)。你也可以 请一个签名密钥给你相应的验证密钥。验证密钥 可用于验证签名,方法是将数据字符串和 签名字符串:返回true或引发BadSignatureRor。

from ecdsa import SigningKey
sk = SigningKey.generate() # uses NIST192p
vk = sk.get_verifying_key()
signature = sk.sign("message")
assert vk.verify(signature, "message")

每个signingkey/verifyingkey都与一个特定的曲线相关联,比如 NIST192P(默认)。较长的曲线更安全,但是 使用并生成更长的密钥和签名。

from ecdsa import SigningKey, NIST384p
sk = SigningKey.generate(curve=NIST384p)
vk = sk.get_verifying_key()
signature = sk.sign("message")
assert vk.verify(signature, "message")

signingkey可以序列化为几种不同的格式:最短的 是调用s=sk.to_string(),然后用 signingkey.from_string(s,curve)。这个简短的表格没有记录 曲线,因此必须确保从字符串()中分辨出用于 原来的钥匙。基于NIST192P的签名密钥的缩写形式只有24 字节长。

from ecdsa import SigningKey, NIST384p
sk = SigningKey.generate(curve=NIST384p)
sk_string = sk.to_string()
sk2 = SigningKey.from_string(sk_string, curve=NIST384p)
# sk and sk2 are the same key

sk.to_pem()sk.to_der()将签名密钥序列化为 OpenSSL使用的格式。pem文件看起来像熟悉的ascii装甲 "———开始EC私钥——"base64编码格式,以及DER格式 是相同数据的较短二进制形式。 signingkey.from_pem()/.from_der()将撤消此序列化。这些 格式包括曲线名称,因此不需要传入曲线 反序列化程序的标识符。

from ecdsa import SigningKey, NIST384p
sk = SigningKey.generate(curve=NIST384p)
sk_pem = sk.to_pem()
sk2 = SigningKey.from_pem(sk_pem)
# sk and sk2 are the same key

同样,verifyingkey也可以以同样的方式序列化: vk.to_string()/verifyingkey.from_string()to_pem()/from_pem(),以及 到'u der()/从'u der()。需要相同的curve=参数 verifyingkey.from_string()

from ecdsa import SigningKey, VerifyingKey, NIST384p
sk = SigningKey.generate(curve=NIST384p)
vk = sk.get_verifying_key()
vk_string = vk.to_string()
vk2 = VerifyingKey.from_string(vk_string, curve=NIST384p)
# vk and vk2 are the same key

from ecdsa import SigningKey, VerifyingKey, NIST384p
sk = SigningKey.generate(curve=NIST384p)
vk = sk.get_verifying_key()
vk_pem = vk.to_pem()
vk2 = VerifyingKey.from_pem(vk_pem)
# vk and vk2 are the same key

有两种不同的方法来计算签名。从根本上说, ecdsa接受一个表示要签名的数据的数字,并返回一个 代表签名的一对数字。hashfunc=参数 sk.sign()vk.verify()用于将任意字符串转换为 固定长度摘要,然后将其转换为ecdsa可以签名的数字, 签名和验证必须使用相同的方法。默认值为 hashlib.sha1,但是如果使用nist256p或更长的曲线,则可以使用 取而代之的是hashlib.sha256。

还有多种方式来表示签名。默认值 sk.sign()vk.verify()方法将其表示为一个短字符串,用于 简单和最少的开销。若要使用其他方案,请使用 sk.sign(signode=)vk.verify(sigdode=)参数。有帮手 "ecdsa.util"模块中可在此处使用的功能。

也可以从"seed"创建一个signingkey,它是 确定性。这可以用于要派生的协议中 来自其他机密的一致签名密钥,例如 三个独立的密钥,只想存储一个主密钥。你应该 从一个均匀分布的不可求种子开始,使用about curve.baselen 字节的熵,然后使用ecdsa.util中的一个helper函数 将其转换为in在正确的范围内,然后最后通过 进入signingkey.from_secret_exponent(),如下所示:

from pyecdsa import NIST384p, SigningKey
from pyecdsa.util import randrange_from_seed__trytryagain

def make_key(seed):
  secexp = randrange_from_seed__trytryagain(seed, NIST384p.order)
  return SigningKey.from_secret_exponent(secexp, curve=NIST384p)

seed = os.urandom(NIST384p.baselen) # or other starting point
sk1a = make_key(seed)
sk1b = make_key(seed)
# note: sk1a and sk1b are the same key
sk2 = make_key("2-"+seed)  # different key

OpenSSL兼容性

生成可由openssl工具验证的签名,或验证 由这些工具生成的签名,请使用:

# openssl ecparam -name secp224r1 -genkey -out sk.pem
# openssl ec -in sk.pem -pubout -out vk.pem
# openssl dgst -ecdsa-with-SHA1 -sign sk.pem -out data.sig data
# openssl dgst -ecdsa-with-SHA1 -verify vk.pem -signature data.sig data
# openssl dgst -ecdsa-with-SHA1 -prverify sk.pem -signature data.sig data

sk.sign(msg, hashfunc=hashlib.sha1, sigencode=ecdsa.util.sigencode_der)
vk.verify(sig, msg, hashfunc=hashlib.sha1, sigdecode=ecdsa.util.sigdecode_der)

openssl处理的密钥可以如下读写:

to_string:  signkey= 24, verifykey= 48, signature=48
DER:        signkey=106, verifykey= 80, signature=55
PEM:        signkey=278, verifykey=162, (no support for PEM signatures)
0

使用signing key.generate()创建签名密钥需要某种形式的 熵(与from_secret_exponent/from_string/from_der/from_pem相反, 它们是确定性的,不需要熵源)。默认值 源代码是os.urandom(),但您可以传递任何其他行为 就像os.urandom的熵=做一些不同的事情。这可能 在想要获得可重复结果的单元测试中非常有用。这个 ecdsa.util.prng实用程序在这里很方便:它接受一个种子并生成一个强 来自它的伪随机流:

to_string:  signkey= 24, verifykey= 48, signature=48
DER:        signkey=106, verifykey= 80, signature=55
PEM:        signkey=278, verifykey=162, (no support for PEM signatures)
1

同样,ecdsa签名生成需要一个随机数,并且每个 签名必须使用不同的数字(使用相同的数字两次将 立即显示私有签名密钥)。sk.sign()方法接受 熵=参数,其行为与signingkey.generate(熵=)相同

确定性特征

如果您调用signingkey.sign_deterministic(data)而不是。sign(data), 代码将生成一个确定性签名,而不是随机签名。 这使用rfc6979中的算法来安全地生成一个唯一的k值, 从私钥和正在签名的消息派生。每次你签字 同一个消息具有相同的密钥,您将获得相同的签名(使用 相同的k)。

在将来的版本中,这可能成为默认值,因为它不易受到 熵源失效。

示例

创建NIST192P密钥对并立即将它们保存到磁盘:

to_string:  signkey= 24, verifykey= 48, signature=48
DER:        signkey=106, verifykey= 80, signature=55
PEM:        signkey=278, verifykey=162, (no support for PEM signatures)
2

从磁盘加载签名密钥,使用它对消息进行签名,然后写入 签名到磁盘:

to_string:  signkey= 24, verifykey= 48, signature=48
DER:        signkey=106, verifykey= 80, signature=55
PEM:        signkey=278, verifykey=162, (no support for PEM signatures)
3

从磁盘加载验证密钥、消息和签名,并验证 签名:

to_string:  signkey= 24, verifykey= 48, signature=48
DER:        signkey=106, verifykey= 80, signature=55
PEM:        signkey=278, verifykey=162, (no support for PEM signatures)
4

创建NIST521P密钥对

to_string:  signkey= 24, verifykey= 48, signature=48
DER:        signkey=106, verifykey= 80, signature=55
PEM:        signkey=278, verifykey=162, (no support for PEM signatures)
5

从主种子创建三个独立的签名密钥:

to_string:  signkey= 24, verifykey= 48, signature=48
DER:        signkey=106, verifykey= 80, signature=55
PEM:        signkey=278, verifykey=162, (no support for PEM signatures)
6

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
如何下载多个。java中的PDF文件   linux Java打开文件,形成实际用户主页~/   java如何在时间线内维护TableView选择?   java Hibernate注释@Where vs@WhereJoinTable   Java读/写访问异常FileNotFoundException(访问被拒绝)   继承在Java中是否可以扩展最后一个类?   Android HttpClient使用java使应用程序崩溃。lang.OutOfMemoryError:pthread_create   java为什么即使我在proguardproject中添加了jar文件,也会出现这种错误。txt?   如果添加JButton,swing Java FocusListener和KeyListener将无法工作   java使用solrj检索json格式的SolrDocument   使用Microsoft Visual Studio代码进行Java编程   java NoClassDefFoundError:org/apache/log4j/Logger   哈希集中包含相等对象的java   java中的参数化构造函数是否需要有一个主体?   java类似于NetBeans不必要的代码检测器   Java实践问题   java Blackberry“[projectname].调试文件丢失”和“I/O错误:找不到程序”jar