我目前正在浏览器中生成私钥,并使用 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/