https://medium.com/@antonassocareer/web3-secp256k1-%E7%B0%BD%E7%AB%A0%E8%88%87solidity%E9%A9%97%E7%AB%A0-26ded518cfdc

phone vs secp256k1 vs ethereumjs-util

那代表 phone 產生的是符合ethereum的格式

但因為 signed的長度不符合標準的 secp256k1 ,所以只能用ethereumjs-util的工具,從fromRpcSig 匯入處理,取得 s r v ,後就能進行處理了!

Elliptic 和 secp256k1 各別需要不同的方式,請閱code

  
const secp256k1 = require('secp256k1')  
const ejsu = require('ethereumjs-util')  
  
Web3 = require("web3")  
var web3 = new Web3(Web3.givenProvider || 'ws://some.local-or-remote.node:8546');  
  
// phone  
// private key   
// address 0xAD44A8ea9A9Bb5eF66F041BB921A687331729eB4  
// Message Signature Has 0xa05ac71b16172777f683edbc48e9709cffd713a82630232d7c98e0f0df5201d60329658dba83b53fed49307e03d9663c0d2e4476c8b7925c2ed02cc7f881f5271b  
// Message Hello  
// public key 034e17dc4aef81e0ce6d16686be5e194274795375fc5525f1cdc46fe0b4643d5d6  
  
console.log("\n----- phone -----\n")  
  
var buf_Signed = Buffer.from(web3.utils.hexToBytes("0xa05ac71b16172777f683edbc48e9709cffd713a82630232d7c98e0f0df5201d60329658dba83b53fed49307e03d9663c0d2e4476c8b7925c2ed02cc7f881f5271b"))  
var buf_pubkey = Buffer.from(web3.utils.hexToBytes("0x034e17dc4aef81e0ce6d16686be5e194274795375fc5525f1cdc46fe0b4643d5d6"))  
  
console.log("\x1b[32m Public Key: \x1b[0m %s \nlength: %s \n", web3.utils.bytesToHex(buf_pubkey), buf_pubkey.length)  
console.log("\x1b[32m singature: \x1b[0m %o \nlength: %s \n", buf_Signed, buf_Signed.length)   
  
// ethereumjs-util import signature  fromRpcSig  
console.log("\n===== ethereumjs-util =====\n")  
  
var fromSigned = ejsu.fromRpcSig(buf_Signed)  
console.log("\x1b[32m fromSigned: %o \n", fromSigned)   
  
var message = "Hello"  
prefix = '\x19Ethereum Signed Message:\n' + message.length.toString()  
console.log("\x1b[32m prefix: \x1b[0m %s \n", prefix)  
  
var message2 = prefix + message  
var buf_msgHash2 = ejsu.keccak256(message2); // this is ok  
  
var buf_msgHash = Buffer.from(web3.utils.hexToBytes(web3.utils.soliditySha3(prefix, message)))  
var ecrecover_public_key = ejsu.ecrecover(buf_msgHash, fromSigned.v, fromSigned.r, fromSigned.s)  
console.log("\x1b[32m ecrecover_public_key: \x1b[0m %s \n", web3.utils.bytesToHex(ecrecover_public_key))  
  
var address = ejsu.pubToAddress(ecrecover_public_key)  
console.log("\x1b[32m address: \x1b[0m %s \n", web3.utils.bytesToHex(address))  
console.log("\x1b[32m toChecksumAddress address: \x1b[0m %s \n", ejsu.toChecksumAddress(web3.utils.bytesToHex(address)))  
console.log("\x1b[32m address is same address: \x1b[0m %s \n", ejsu.toChecksumAddress(web3.utils.bytesToHex(address)) == '0xAD44A8ea9A9Bb5eF66F041BB921A687331729eB4')  
  
  
// Elliptic   
console.log("\n===== Elliptic-util =====\n")  
var EC = require('elliptic').ec;  
var ec = new EC('secp256k1');  
//var key = ec.genKeyPair();  
var key = ec.keyFromPublic(buf_pubkey); // No Private Key  
  
//r s https://github.com/ethereumjs/ethereumjs-util/blob/599ba5b1c7043a7e155e6032c50d7a01fc63aaf1/src/signature.ts#L70  
var r = buf_Signed.slice(0, 32);  
var s = buf_Signed.slice(32, 64);  
console.log("\x1b[32m Elliptic verify: \x1b[0m %s \n", key.verify(buf_msgHash, {r: r, s: s}));  
  
  
//secp256k1  
console.log("\n===== secp256k1 =====\n")  
var DER_signature = secp256k1.signatureExport(buf_Signed.slice(0, 64))  
var signature = secp256k1.signatureImport(DER_signature)  
console.log("\x1b[32m phone Signed -> DER Signed -> signatureImport: \x1b[0m %s \nlength: %s \n", web3.utils.bytesToHex(signature), signature.length)  
console.log("\x1b[32m secp256k1 verify: \x1b[0m %s \n", secp256k1.verify(buf_msgHash, signature, buf_pubkey));  
  
console.log("\n----- phone End -----\n")  
  
  
// secp256k1  
// private key random => 0x9fc00a13bf199dc5606da92d61438c680eeddec04f7a1833405c1466a81c9bd7  
  
console.log("\n----- secp256k1 -----\n")  
  
var buf_PrivateKey = Buffer.from(web3.utils.hexToBytes('0x9fc00a13bf199dc5606da92d61438c680eeddec04f7a1833405c1466a81c9bd7'))  
var buf_PublicKey = secp256k1.publicKeyCreate(buf_PrivateKey)  
console.log("\x1b[32m Public Key: \x1b[0m %s \nlength: %s \n", web3.utils.bytesToHex(buf_PublicKey), buf_PublicKey.length)  
  
var buf_msg = Buffer.alloc(32, "Hello")  
var singature = secp256k1.sign(buf_msg, buf_PrivateKey)  
console.log("\x1b[32m singature: \x1b[0m %o \nlength: %s \n", singature, singature.signature.length)   
console.log("\x1b[32m singature: \x1b[0m %s \n", web3.utils.bytesToHex(singature.signature))  
  
var recover_public_key = secp256k1.recover(buf_msg, singature.signature, singature.recovery)  
console.log("\x1b[32m Get Back Pubkey: \x1b[0m %s \n", web3.utils.bytesToHex(recover_public_key))  
console.log("\x1b[32m recover_public_key is same PublicKey: \x1b[0m %s", web3.utils.bytesToHex(recover_public_key) == web3.utils.bytesToHex(buf_PublicKey))  
  
console.log("\n----- secp256k1 End -----\n")  
  
  
// ganache  
// private key 0x75b25b96be4313c5a102bd4daa6bbeb71414f23e0ae15c0f93fa6d17866003da  
// addresss 0xf8d3A2033ebfc7778CD59f676235a8E431b6eeD7  
  
console.log("\n----- ganache -----\n")  
  
// ganache part is OK  
var buf_PrivateKey = Buffer.from(web3.utils.hexToBytes('0x75b25b96be4313c5a102bd4daa6bbeb71414f23e0ae15c0f93fa6d17866003da'))  
var buf_PublicKey = ejsu.privateToPublic(buf_PrivateKey)  
var buf_Address = ejsu.privateToAddress(buf_PrivateKey)  
console.log("\x1b[32m Public Key: \x1b[0m %s \nlength: %s \n", web3.utils.bytesToHex(buf_PublicKey), buf_PublicKey.length)  
console.log("\x1b[32m Address: \x1b[0m %s \nlength: %s \n", web3.utils.bytesToHex(buf_Address), buf_Address.length)  
  
var message = "Hello"  
var buf_msgHash = ejsu.keccak256(message);  
var singature = ejsu.ecsign(buf_msgHash, buf_PrivateKey)  
console.log("\x1b[32m singature: \x1b[0m %o \n", singature)  // have r s v  
  
var ecrecover_public_key = ejsu.ecrecover(buf_msgHash, singature.v, singature.r, singature.s)  
console.log("\x1b[32m ecrecover_public_key: \x1b[0m %s \n", web3.utils.bytesToHex(ecrecover_public_key))  
console.log("\x1b[32m ecrecover_public_key is same PublicKey: \x1b[0m %s", web3.utils.bytesToHex(ecrecover_public_key) == web3.utils.bytesToHex(buf_PublicKey))  
  
console.log("\n----- ganache End -----\n")  

Result

  
----- phone -----  
  
 Public Key:  0x034e17dc4aef81e0ce6d16686be5e194274795375fc5525f1cdc46fe0b4643d5d6  
length: 33  
  
 singature:  <Buffer a0 5a c7 1b 16 17 27 77 f6 83 ed bc 48 e9 70 9c ff d7 13 a8 26 30 23 2d 7c 98 e0 f0 df 52 01 d6 03 29 65 8d ba 83 b5 3f ed 49 30 7e 03 d9 66 3c 0d 2e ... >  
length: 65  
  
  
===== ethereumjs-util =====  
  
 fromSigned: { v: 27,  
  r:  
   <Buffer a0 5a c7 1b 16 17 27 77 f6 83 ed bc 48 e9 70 9c ff d7 13 a8 26 30 23 2d 7c 98 e0 f0 df 52 01 d6>,  
  s:  
   <Buffer 03 29 65 8d ba 83 b5 3f ed 49 30 7e 03 d9 66 3c 0d 2e 44 76 c8 b7 92 5c 2e d0 2c c7 f8 81 f5 27> }  
  
 prefix:   Ethereum Signed Message:  
5  
  
 ecrecover_public_key:  0x4e17dc4aef81e0ce6d16686be5e194274795375fc5525f1cdc46fe0b4643d5d66dcc58b79553ea878b6b514b8bd2552090d0fc810bd6f9b4d585f4709f43ed41  
  
 address:  0xad44a8ea9a9bb5ef66f041bb921a687331729eb4  
  
 toChecksumAddress address:  0xAD44A8ea9A9Bb5eF66F041BB921A687331729eB4  
  
 address is same address:  true  
  
  
===== Elliptic-util =====  
  
 Elliptic verify:  true  
  
  
===== secp256k1 =====  
  
 phone Signed -> DER Signed -> signatureImport:  0xa05ac71b16172777f683edbc48e9709cffd713a82630232d7c98e0f0df5201d60329658dba83b53fed49307e03d9663c0d2e4476c8b7925c2ed02cc7f881f527  
length: 64  
  
 secp256k1 verify:  true  
  
  
----- phone End -----  
  
  
----- secp256k1 -----  
  
 Public Key:  0x037ff17f569a94f4b91317a36b54dc9a77cdd6ce004a00821ca0ebc12acaa5188d  
length: 33  
  
 singature:  { signature:  
   <Buffer 79 a4 11 c0 85 bd 1a 2d 7b bd a5 eb 1e 19 d6 75 f1 40 07 27 f7 83 82 9f 1d f6 2a d2 86 3c 8a eb 62 04 03 78 64 96 f9 10 27 61 d0 ea 79 2b 40 65 d5 45 ... >,  
  recovery: 1 }  
length: 64  
  
 singature:  0x79a411c085bd1a2d7bbda5eb1e19d675f1400727f783829f1df62ad2863c8aeb620403786496f9102761d0ea792b4065d545608d7905af427ffa2b181b103e28  
  
 Get Back Pubkey:  0x037ff17f569a94f4b91317a36b54dc9a77cdd6ce004a00821ca0ebc12acaa5188d  
  
 recover_public_key is same PublicKey:  true  
  
----- secp256k1 End -----  
  
  
----- ganache -----  
  
 Public Key:  0xba5ca43c6d8c8ec41a0449ddc35dfee96afd0a112c4667b9d09925913799be627d1a779b6114c8541650c3b31bf88d360b1e3ebc973267003c7452fef6f2da2e  
length: 64  
  
 Address:  0xf8d3a2033ebfc7778cd59f676235a8e431b6eed7  
length: 20  
  
 singature:  { r:  
   <Buffer b7 f7 ff 3c 78 8f 10 db e5 46 d4 10 2a 17 cd 99 1f d3 2c 5a c8 86 e9 31 83 bc 53 8d 5f 92 8f 81>,  
  s:  
   <Buffer 6d c1 0d 0e 71 42 73 f5 64 64 96 af d4 e1 3d 49 18 09 5f 42 27 e0 0b ae 1f 5a 59 ec af 39 fd e2>,  
  v: 27 }  
  
 ecrecover_public_key:  0xba5ca43c6d8c8ec41a0449ddc35dfee96afd0a112c4667b9d09925913799be627d1a779b6114c8541650c3b31bf88d360b1e3ebc973267003c7452fef6f2da2e  
  
 ecrecover_public_key is same PublicKey:  true  
  
----- ganache End -----