如何验证特雷莎钱包的签名

问题描述 投票:0回答:1

我想验证由我的Trezor硬件钱包签名的消息。基本上我有这些信息。

.venv/bin/trezorctl btc get-public-node -n 0
Passphrase required: 
Confirm your passphrase: 
node.depth: 1
node.fingerprint: ea66f037
node.child_num: 0
node.chain_code: e02030f2a7dfb474d53a96cb26febbbe3bd3b9756f4e0a820146ff1fb4e0bd99
node.public_key: 026b4cc594c849a0d9a124725997604bc6a0ec8f100b621b1eaed4c6094619fc46
xpub: xpub69cRfCiJ5BVzesfFdsTgEb29SskY74wYfjTRw5kdctGN2xp1HF4udTP21t68PAQ4CBq1Rn3wAsWr84wiDiRmmSZLwkEkv4qK5T5Y7EXebyQ

$ .venv/bin/trezorctl btc sign-message 'aaa' -n 0
Please confirm action on your Trezor device
Passphrase required: 
Confirm your passphrase: 
message: aaa
address: 17DB2Q3oZVkQAffkpFvF4cwsXggu39iKdQ
signature: IHQ7FDJy6zjwMImIsFcHGdhVxAH7ozoEoelN2EfgKZZ0JVAbvnGN/w8zxiMivqkO8ijw8fXeCMDt0K2OW7q2GF0=

我想使用python3-ecdsa。当我想用任何有效的公钥来验证签名时,我得到一个AssertionError:(65,64),因为签名的base64.b64decode是65个字节,但是应该是64个字节。当我想将node.public_key加载到ecdsa.VerifyingKey中时,我得到一个AssertionError:(32,64),因为bytes.fromhex返回了32个字节,但是我发现的每个示例都使用64个字节作为公共密钥。可能我需要将bip32 xpub转换为公钥,但我真的不知道如何。

cryptography digital-signature bitcoin ecdsa cryptocurrency
1个回答
0
投票

公钥。从数学上讲,椭圆曲线公钥是曲线上的一个点。对于比特币,secp256k1以及其他X9样式(Weierstrass形式)使用的椭圆曲线,存在(实际上)最初由X9.62建立并已被许多其他人重用的two标准表示形式:

  • 非压缩格式:由一个值0x04的八位字节组成,后跟两个大小等于包含(仿射)X和Y坐标的曲线顺序大小的块。对于secp256k1,这是1 + 32x2 = 65个八位字节

  • 压缩格式:由一个八位字节组成,其值0x02或0x03指示Y坐标的奇偶性,后跟一个大小相等的块,包含X坐标的曲线顺序。对于secp256k1,这是1 + 32 = 33个八位字节

您的Trezor输出的公钥是第二种形式,0x02 + 32个八位位组= 33个八位位组。不是32。

我从没见过X9EC库(ECDSA和/或ECDH)至少不接受标准的未压缩形式,而且通常都不接受。可以想象,您的python库只希望未压缩的形式而没有前导0x04,但是如果这样的话,除非文档或代码中提供了很好的解释,否则这种无偿且颇具风险的非标准性会使我怀疑其质量。如果确实需要将压缩形式转换为非压缩形式,则必须实现曲线方程式,对于secp256k1可以在标准参考文献中找到,更不用说许多实现了。计算x^3 + a*x + b,取F_p的平方根,然后选择具有正确奇偶校验的正值或负值(在此同意前​​导字节0x02)。

'xpub'是hierarchical确定性密钥的base58check编码,它不仅是EC(DSA)密钥,而且还为密钥派生过程添加了元数据。如果您对它进行base58解码并删除了支票,则会得到(以十六进制表示):

0488B21E01EA66F03700000000E02030F2A7DFB474D53A96CB26FEBBBE3BD3B9756F4E0A820146FF1FB4E0BD99026B4CC594C849A0D9A124725997604BC6A0EC8F100B621B1EAED4C6094619FC46good

它完全按照您的显示方式分解:

0488B21E  fixed prefix 
01  .depth 
EA66F037  .fingerprint
00000000  .child_num
E02030F2A7DFB474D53A96CB26FEBBBE3BD3B9756F4E0A820146FF1FB4E0BD99  .chain_code
026B4CC594C849A0D9A124725997604BC6A0EC8F100B621B1EAED4C6094619FC46  .public_key

确认这一点,(即示于十六进制的字节)的SHA256的RIPEMD160 026B4CC594C849A0D9A124725997604BC6A0EC8F100B621B1EAED4C6094619FC46是(示出的在十六进制字节为)441e1d2adf9ff2a60​​75d71d0d8782228e0df47f8,和前缀的版本字节00 mainnet到和base58check编码给出了地址17DB2Q3oZVkQAffkpFvF4cwsXggu39iKdQ如显示。

Signature。数学上,X9.62类型的ECDSA签名是两个整数,分别称为r和s。有两种different标准来表示它们,而比特币使用两种标准:

  • ASN.1 DER格式。 DER是一种通用编码,其中包含“标签”和“长度”元数据以及可变长度数据,具体取决于数字值(此处为r和s);通常,对于secp256k1,此编码通常为70到72个八位位组,但偶尔会更少。但是,为了避免某些“恶意”攻击,当前的比特币需要使用小于曲线顺序一半的“ s”值(通常称为“ low-s”),从而将ASN.1 DER编码的最大长度减少到71个八位位组。比特币将其用于transaction签名,并在其后立即添加一个“ sighash”字节(在“ scriptsig”又称为赎回脚本中),指示有关如何计算签名的某些选项(因此应进行验证)。

  • 'plain'或P1363格式。这是固定长度的,仅由r和s值组成固定长度的块;对于secp256k1,这是64个八位位组。比特币将其用于消息签名,但它在[[beginning上添加'恢复'字节',从而允许在必要时根据消息和签名确定公钥,从而形成65个八位字节。

请参见https://bitcoin.stackexchange.com/questions/38351/ecdsa-v-r-s-what-is-v/38909https://bitcoin.stackexchange.com/questions/12554/why-the-signature-is-always-65-13232-bytes-long

如果您的python库是为通用ECDSA(而不是比特币)设计的,并且想要一个64字节的签名,那几乎可以肯定是“普通”格式,该格式与第一个字节对应于比特币消息签名(此处是从base64解码)已删除。

© www.soinside.com 2019 - 2024. All rights reserved.