javascript - secp256k1/schnorr 库不会相互通信

标签 javascript python cryptography secp256k1

我目前正在浏览器中生成私钥,并使用 noble-secp256k1 派生其公钥。 JavaScript 库:

const privKey = secp.utils.randomPrivateKey()
const pubKey = Buffer.from(secp.schnorr.getPublicKey(privKey)).toString('hex')

然后,我将公钥发送到我的服务器,该服务器使用 secp256k1库来验证我传递的有效负载签名。当我尝试实例化公钥时失败:

pub_key = secp256k1.PublicKey(binascii.unhexlify(hex_pub_key), raw=True)

如果我使用 python 库(python -m secp256k1 privkey -p)构建 key 对,则此方法有效,但如果我发送在客户端上生成的 key ,服务器会引发错误:

Exception: unknown public key size (expected 33 or 65)

Python 库生成 66 个字符的十六进制编码的公钥。客户端使用 secp.schnorr.getPublicKey 方法生成 64 字符的十六进制编码的公钥,并使用 secp.getPublicKey 方法生成 130 字符的十六进制编码的公钥。方法。有没有办法让我的Python库接受前端生成的schnorr pubkey?有没有什么地方可以让我了解 secp256k1 和 schnorr 之间的半重叠是怎么回事?

最佳答案

NodeJS 库 ( noble-secp256k1 ) 的 32 字节公钥必须扩展为 33 字节并以 0x02 开头,然后可由 Python 库 ( secp256k1 ) 导入:

...we pick that option for P, and thus our X-only public keys become equivalent to a compressed public key that is the X-only key prefixed by the byte 0x02...

来自 BIP0340 的文档,秒。 设计隐式 Y 坐标


测试:

以下 NodeJS 代码使用 NodeJS 库并生成 key 对和 Schnorr 签名:

var secp = require("@noble/secp256k1");

(async () => {
    const privateKey = secp.utils.randomPrivateKey();
    const publicKey = secp.schnorr.getPublicKey(privateKey) 
    const msgHash = await secp.utils.sha256("hello world");
    const signature = await secp.schnorr.sign(msgHash, privateKey);
    const isValid = await secp.schnorr.verify(signature, msgHash, publicKey);  
    console.log("Public key (hex):", Buffer.from(publicKey).toString('hex'))
    console.log("Signature (hex) :", Buffer.from(signature).toString('hex'))
    console.log("Verified        :", isValid);
})();

可能的输出如下:

Public key (hex): f9a10a9bbb93e14a35d82c514f4eb052734ba55b93f6553f12366d6e887b76ee
Signature (hex) : b08a0e9d02da2bbb3e2220b90e591c82ebcfc337aaac36ebe2f91eec288c79b3b9513b1018126526f99697abb78c60041f0683bbce6760b8ff76cb53a4c87137
Verified        : true

以下 Python 代码使用 Python 库,并使用 NodeJS 代码导出的 key (由前导 0x02 扩展)验证 Schnorr 签名:

import secp256k1
import hashlib

publicKeyHexFromNodeJS = 'f9a10a9bbb93e14a35d82c514f4eb052734ba55b93f6553f12366d6e887b76ee'
signatureHexFromNodeJS = 'b08a0e9d02da2bbb3e2220b90e591c82ebcfc337aaac36ebe2f91eec288c79b3b9513b1018126526f99697abb78c60041f0683bbce6760b8ff76cb53a4c87137'

digest = hashlib.sha256()
digest.update(b'hello world')
msgHash = digest.digest()

publicKey = secp256k1.PublicKey(bytes.fromhex('02' + publicKeyHexFromNodeJS), raw=True)
signature = bytes.fromhex(signatureHexFromNodeJS)
isValid = publicKey.schnorr_verify(msgHash, signature, '', raw=True)
print("Verified: " + str(isValid))

输出:

Verified: True

即验证成功。


注意:即使前面添加了 0x03(而不是 0x02),验证也会成功。库可能只检查 key 是否被压缩(0x02 或 0x03),如果是,则简单地 chop 前导字节。

关于javascript - secp256k1/schnorr 库不会相互通信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72396085/

相关文章:

c++ - 如何使用 salsa20(或 ChaCha)?

javascript - 从按钮中间打开下拉菜单

c# - 我们如何在 ASP.NET 中对文件上传控件应用客户端验证来检查文件名是否包含特殊字符?

javascript - 在 React 中更新子组件后更改父状态?

c# - 加密随机唯一字符串

c# - AES 加密解密的文本有多余的空格

javascript - 无法获取 Odoo 9 中 javascript 文件的内容

python - 使用 Flask 显示特定目录中的文件内容

python - 列出和追加元素

python - 使用常规 python 脚本运行 Nose 测试