ecdsa学习笔记 / SigningKey、VerifyingKey以及公钥

in #python7 years ago

在我们上一篇文章对比一下ecdsa与secp256k1-py从私钥生成公钥中,我们介绍了由私钥通过ecdsa以及secp256k1-py生成公钥的代码。

其中ecdsa生成公钥的代码是我从steem-python库中扒出来的,咳咳,一直挺好用的,我也就懒得看它具体是咋做的啦。


(图源 :pixabay)

ecdsa 生成校验Key(VerifyingKey)

但是今天看ecdsa,发现从签名Key(SigningKey)生成校验Key(VerifyingKey)还是很方便的。比如拿我们之前用Hello World生成的私钥,那么生成校验Key(VerifyingKey)的代码如下:

import ecdsa
from binascii import hexlify, unhexlify
secret = 'a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e'
sk = ecdsa.SigningKey.from_string(unhexlify(secret), curve=ecdsa.SECP256k1)
vk = sk.get_verifying_key()
print(hexlify(vk.to_string()).decode())

以字符串形式输入如下:

98c39ac0d91ff4cea6e79ae5836e50868c47191bca0fbfd2a6838d303665f506ad0a9ccb60c7758ce4c2759b8f7b0f731f0d8d90caf3778c4a65a0c53cf94210

对比公钥压缩流程,可知

ecdsa输出的字符串就是把x, y串接到一起。

也就是说,如果vk.to_string()加上个参数format,分别是raw、compressed、uncompressed比较易于理解了。

ecdsa 生成公钥

知道了上述事实,在看我们之前使用ecdsa生成公钥的代码,就觉得可读性太差了。

import ecdsa
from binascii import hexlify, unhexlify
secret = unhexlify('a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e')
order = ecdsa.SigningKey.from_string(secret, curve=ecdsa.SECP256k1).curve.generator.order()
p = ecdsa.SigningKey.from_string(secret, curve=ecdsa.SECP256k1).verifying_key.pubkey.point
x_str = ecdsa.util.number_to_string(p.x(), order)
y_str = ecdsa.util.number_to_string(p.y(), order)
compressed = hexlify(bytes(chr(2 + (p.y() & 1)), 'ascii') + x_str).decode('ascii')
uncompressed = hexlify(bytes(chr(4), 'ascii') + x_str + y_str).decode('ascii')
print(compressed)
print(uncompressed)

为了生成公钥,我们需要知道以下要素:

  • SigningKey: 可由私钥生成
  • order: 由我们指定的曲线生成
  • p:公钥点

那么我们把上述代码改进为更加便于阅读的方式:

import ecdsa
from binascii import hexlify, unhexlify
secret = unhexlify('a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e')

导入必要的库以及指定私钥

sk = ecdsa.SigningKey.from_string(unhexlify(secret), curve=ecdsa.SECP256k1)
vk = sk.get_verifying_key()

由私钥生成SigningKey,并进而生成VerifyingKey

order = ecdsa.SECP256k1.generator.order()
p = vk.pubkey.point

取出order和p (order还可以从order = vk.pubkey.order语句获得)

x_str = ecdsa.util.number_to_string(p.x(), order)
y_str = ecdsa.util.number_to_string(p.y(), order)

生成点p的x和y

剩下的就和我们之前的代码没什么区别了。

由VerifyingKey生成的字符串生成公钥

在文章开头,我们用

print(hexlify(vk.to_string()).decode())
生成了VerifyingKey的字符串表示,也就是x_str+y_str

那么能否从这个字符串生成公钥呢?

一种方式是从字符串生成VerifyingKey,再用我们上述方法生成公钥。

而另外一种方式是直接将字符串拆分成x部和y部
vk_b = unhexlify(vk_str)
xs = vk_b[:ecdsa.SECP256k1.baselen]
ys = vk_b[ecdsa.SECP256k1.baselen:]

剩下的步骤就不用多说啦。

结论

Python ECDSA是 ECDSA的纯Python实现,尽管速度要慢一些(相比ECDSA的C++实现),但是还是相当好玩的。

相关文章

Sort:  

That is the best post in Steemit.. now I vote for you.. nice? :)

Wow your post is very educative, am following now. Thanks for this post

Nice post beautiful presented and explained. detail oriented with nice information. thank you for sharing

When I look at your post is very interesting and useful.
The proof of many people who upvote your post.

It seems very useful, but I don't understand them.
Still, thank your sharing. Upvote you already.

這位猿人,您還是說中文吧!

非常好的文章萨拉姆知道

GOOD POST THANKS

good post my friend

Coin Marketplace

STEEM 0.20
TRX 0.14
JST 0.030
BTC 64155.87
ETH 3422.91
USDT 1.00
SBD 2.59