我正在使用python ecdsa
库为区块链交易签署消息,在区块链规范中,对于secp256r1
,签名长度应为65字节,其中:
签名的长度必须为65字节,格式为[r,s,v],其中前32个字节为r,后32个字节为s,最后一个字节为v。
以及
v表示恢复ID,必须将其标准化为0、1、2或3。请注意,与EIP-155不同,链ID不用于计算v值
我总是使用以下方法获取前64个字节:sign_deterministic(data, hashfunc=hashlib.sha256)
但是不确定ecdsa保存在哪里,或者我可以计算出v
字节?
我在区块链上使用的源代码(Rust fastcrypto)中看到它正在做的事情:
// Compute recovery id and normalize signature
let is_r_odd = y.is_odd();
let is_s_high = sig.s().is_high();
let is_y_odd = is_r_odd ^ is_s_high;
let sig_low = sig.normalize_s().unwrap_or(sig);
let recovery_id = RecoveryId::new(is_y_odd.into(), false);
但是在ecdsa
中,所有这些都隐藏在上面提到的签名函数后面。
1条答案
按热度按时间fwzugrvs1#
例如,这里解释了使用ECDSA签名。在下面,本文中使用的术语适用:
k
值,这是可能的,因为您正在根据RFC 6979使用 deterministic ECDSA。此处k
取决于散列的定义。消息和私有签名密钥。运行
sign_deterministic(data, hashfunc=hashlib.sha256)
时,将执行以下逻辑来确定k
:对应的代码位置可以在这里找到。注意
sign_deterministic(data, hashfunc=hashlib.sha256)
调用使用额外熵的默认值(extra_entropy=b""
),并允许截断太大的哈希值(allow_truncate=True
)。对于
k
,R
可以被确定为k
和生成点G
的乘积,形式上,k
可以被认为是原始私钥,而R
可以被认为是原始公钥,因此可以使用密钥的现有功能,并且R
可以被容易地确定如下:对于已知的
R
,恢复ID可以如下导出:有关最后一个逻辑的解释,请参见here(包括注解)。注意,恢复ID为2和3的概率非常小。
然后,可以使用 ecdsa 库生成包括恢复ID的签名,例如如下:
为了验证结果,也为了证明存在用于生成具有恢复ID的签名的更方便的库,使用以下pycoin代码,该代码仅需要库函数
sign_with_recid()
,该函数返回具有r
、s
和恢复ID的元组。此方法内部使用来自RFC6979的k
派生(即,也应用于 ecdsa 示例中的逻辑):当使用相同的签名密钥、相同的消息和相同的摘要时,这些值是相同的。
当前的问题是关于确定性ECDSA的,但即使对于非确定性ECDSA,ecdsa库也允许确定恢复ID(并且比确定性ECDSA的情况下容易得多)。由于不能访问签名中使用的随机
k
,k
的生成被简单地移到外部,然后使用该k
生成签名(支持该k
,参见sign()
):对于已知的
k
、R
和最终的恢复ID,可以如上所述确定。