Signature
ethers.js 錯誤的簽名
從 ethers.js 和 secp256k1 中的相同私鑰,我得到相同的 eth 地址。但是,如果我簽署一條消息,我會在 ethers.js 中得到一個不同的(錯誤的)簽名。我的程式碼有什麼問題?
import { createKeyPair, sign } from '@erebos/secp256k1' import { pubKeyToAddress } from '@erebos/keccak256' import { ethers, Wallet } from 'ethers'; async function testsig(message){ // ethers: var ethersprivateKey = '0x0123456789012345678901234567890123456789012345678901234567890123'; var etherswallet = new ethers.Wallet(ethersprivateKey); console.log(etherswallet.address) //0x14791697260E4c9A71f18484C9f997B308e59325 var s_ethers= await etherswallet.signMessage(message) console.log( ethers.utils.arrayify(s_ethers) ) //int8Array(65) [166, 122, 63, 76, 122, 170, 175, 139, 106, 144, 156, 80, 245, 237, 145, 126, 24, 132, 20, 93, 157, 42, 208, 8, 158, 115, 23, 196, 253, 183, 157, 249, 8, 20, 82, 203, 147, 90, 139, 78, 10, 22, 10, 133, 199, 161, 228, 217, 234, 204, 197, 207, 9, 37, 149, 16, 151, 230, 159, 30, 25, 171, 24, 176, 27] // secp256k1: var secp256k1privateKey = '0123456789012345678901234567890123456789012345678901234567890123'; let secp256k1keyPair = createKeyPair(secp256k1privateKey); const secp256k1user = pubKeyToAddress(secp256k1keyPair.getPublic('array')) console.log(secp256k1user) //0x14791697260e4c9a71f18484c9f997b308e59325 var s_secp256k1=sign(message, secp256k1keyPair) console.log( s_secp256k1) //(65) [93, 182, 197, 217, 33, 175, 143, 115, 43, 243, 207, 2, 160, 182, 26, 117, 218, 181, 239, 132, 22, 133, 182, 155, 86, 25, 151, 186, 76, 167, 48, 228, 23, 78, 253, 193, 86, 243, 164, 96, 149, 68, 209, 43, 122, 6, 186, 68, 147, 74, 110, 71, 175, 197, 222, 132, 208, 223, 168, 84, 46, 81, 141, 73, 1] } testsig("abc")
Ethers.js 在簽名
\x19Ethereum Signed Message:\n<message length>
之前為簽名添加前綴,並對消息的雜湊進行簽名。這相當於personal_sign
JSON-RPC 方法。要將 Ethers.js 的行為與 secp256k1 庫匹配,您必須:
- 使用獲取消息 (
e
)的雜湊值Keccak256(message)
。- 雜湊
e
,使用Keccak256("\x19Ethereum Signed Message:\n32" + e)
. 我們可以在這裡硬編碼 32 的長度,因為 Keccak-256 雜湊總是 32 字節(= 256 位)長。- 使用私鑰對生成的雜湊進行簽名。
簽名
{r, s, v}
應該是有效的乙太坊簽名,其中r
和s
分別是前 32 個字節和後 32 個字節,v
是最後一個字節(也稱為恢復 ID)。請注意,您可能必須將 27 添加到v
參數中,才能獲得v
27 或 28(乙太坊使用的)。