Python中基于P256曲线的ECDSA实现及公钥重构验签方法咨询
Python中基于P256曲线的ECDSA实现及公钥重构验签方法咨询
嗨,你的这个实现思路完全没问题!在Python里不管用ecdsa还是PyCryptodome这两个库,都能轻松搞定「从曲线上的点W重构公钥+验签」的流程,我给你分别写个P256曲线下的可运行示例,你一看就懂:
一、用ecdsa库实现
这个库的API更贴近ECDSA底层逻辑,上手特别直观:
1. 签名端(生成密钥、签名、提取公钥点W)
先模拟签名侧的操作,生成密钥对、签名数据,再把公钥的x/y坐标(也就是你说的W点)、原始数据、签名一起传输:
import ecdsa import hashlib # 生成P256曲线(对应NIST256p标准)的密钥对 sk = ecdsa.SigningKey.generate(curve=ecdsa.NIST256p) vk = sk.get_verifying_key() # 待签名的原始数据 data = b"这是要被签名的业务数据内容" # 用SHA-256哈希后签名(P256曲线标准搭配SHA-256哈希算法) signature = sk.sign(data, hashfunc=hashlib.sha256) # 提取公钥的W点坐标(x和y都是整数格式) pub_key_x = vk.pubkey.point.x() pub_key_y = vk.pubkey.point.y() # 这里可以把x/y转成十六进制字符串或固定长度字节流,和data、signature一起传输
2. 验签端(重构公钥+验证签名)
到了验签侧,拿到传输过来的参数后,就可以重构公钥并验签了:
import ecdsa import hashlib # 假设从传输通道解析得到的参数(实际场景替换成你接收的真实数据) received_data = b"这是要被签名的业务数据内容" received_signature = b"..." # 签名端传来的签名字节流 received_x = 123456... # 签名端传来的公钥x坐标整数 received_y = 789012... # 签名端传来的公钥y坐标整数 # 从x/y坐标重构P256曲线的公钥 curve = ecdsa.NIST256p pub_key_point = curve.curve.point(received_x, received_y) reconstructed_vk = ecdsa.VerifyingKey.from_public_point(pub_key_point, curve=curve) # 执行签名验证 try: reconstructed_vk.verify(received_signature, received_data, hashfunc=hashlib.sha256) print("签名验证通过!") except ecdsa.BadSignatureError: print("签名验证失败!")
二、用PyCryptodome库实现
这个库的封装更偏向通用密码学操作,代码风格也很规整:
1. 签名端(生成密钥、签名、提取公钥点W)
from Crypto.PublicKey import ECC from Crypto.Signature import DSS from Crypto.Hash import SHA256 # 生成P256曲线的密钥对 sk = ECC.generate(curve='P-256') vk = sk.public_key() # 待签名的原始数据 data = b"这是要被签名的业务数据内容" # 用SHA-256哈希后签名 hash_obj = SHA256.new(data) signer = DSS.new(sk, 'fips-186-3') signature = signer.sign(hash_obj) # 提取公钥的W点坐标(整数格式) pub_key_x = vk.pointQ.x pub_key_y = vk.pointQ.y # 同样可以把x/y转成易传输的格式,和data、signature一起发送
2. 验签端(重构公钥+验证签名)
from Crypto.PublicKey import ECC from Crypto.Signature import DSS from Crypto.Hash import SHA256 # 假设从传输通道解析得到的参数 received_data = b"这是要被签名的业务数据内容" received_signature = b"..." # 签名端传来的签名字节流 received_x = 123456... # 签名端传来的公钥x坐标整数 received_y = 789012... # 签名端传来的公钥y坐标整数 # 从x/y坐标重构P256曲线的公钥 reconstructed_vk = ECC.construct( curve='P-256', point_x=received_x, point_y=received_y ) # 执行签名验证 hash_obj = SHA256.new(received_data) verifier = DSS.new(reconstructed_vk, 'fips-186-3') try: verifier.verify(hash_obj, received_signature) print("签名验证通过!") except ValueError: print("签名验证失败!")
最后给你几个实用小提示:
- 传输公钥坐标时,建议转成32字节的大端字节流(P256的x/y都是32字节长度)或十六进制字符串,这样跨端解析不容易出错
- 不管用哪个库,验签时的哈希算法必须和签名端完全一致(P256配SHA-256是标准组合)
- 如果你的W点是压缩格式的公钥(比如仅含x坐标+一个奇偶位),也可以直接用库的解析方法,比如
ecdsa.VerifyingKey.from_string(压缩公钥字节, curve=ecdsa.NIST256p),或者PyCryptodome的ECC.import_key(压缩公钥字节)




