ecdsa学习笔记 / SigningKey、VerifyingKey以及公钥
在我们上一篇文章对比一下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++实现),但是还是相当好玩的。
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.
nice bro!!
It seems very useful, but I don't understand them.
Still, thank your sharing. Upvote you already.
這位猿人,您還是說中文吧!
非常好的文章萨拉姆知道
GOOD POST THANKS
good post my friend