Signature

ethers.js 錯誤的簽名

  • September 24, 2020

從 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_signJSON-RPC 方法。要將 Ethers.js 的行為與 secp256k1 庫匹配,您必須:

  1. 使用獲取消息 ( e)的雜湊值Keccak256(message)
  2. 雜湊e,使用Keccak256("\x19Ethereum Signed Message:\n32" + e). 我們可以在這裡硬編碼 32 的長度,因為 Keccak-256 雜湊總是 32 字節(= 256 位)長。
  3. 使用私鑰對生成的雜湊進行簽名。

簽名{r, s, v}應該是有效的乙太坊簽名,其中rs分別是前 32 個字節和後 32 個字節,v是最後一個字節(也稱為恢復 ID)。請注意,您可能必須將 27 添加到v參數中,才能獲得v27 或 28(乙太坊使用的)。

引用自:https://ethereum.stackexchange.com/questions/87743