secp256k1

secp256k1

Posted by hello2mao on September 26, 2019

1. 概述

Secp256k1 是指比特币中使用的 ECDSA(椭圆曲线数字签名算法)曲线的参数,并且在高效密码学标准(Certicom Research,http://www.secg.org/sec2-v2.pdf )中进行了定义。

Secp256k1 为基于 Fp 有限域上的椭圆曲线,由于其特殊构造的特殊性,其优化后的实现比其他曲线性能上可以特高 30%,有明显以下两个优点:

  • 占用很少的带宽和存储资源,密钥的长度很短。
  • 让所有的用户都可以使用同样的操作完成域运算。

2. 签名格式

Signarure(M) = (r,s)

3. ECDSA Signature R|S to ASN1 DER Encoding

0x30|b1|0x02|b2|r|0x02|b3|s
b1 = Length of remaining data,1-byte
b2 = Length of r,1-byte
b3 = Length of s,1-byte

e.g.

r|s =
6f0156091cbe912f2d5d1215cc3cd81c0963c8839b93af60e0921b61a19c5430 c71006dd93f3508c432daca21db0095f4b16542782b7986f48a5d0ae3c583d4

==>

304402206f0156091cbe912f2d5d1215cc3cd81c0963c8839b93af60e0921b61a19c543002200c71006dd93f3508c432daca21db0095f4b16542782b7986f48a5d0ae3c583d4

=>

30
44
02
20
6f0156091cbe912f2d5d1215cc3cd81c0963c8839b93af60e0921b61a19c5430
02
20
0c71006dd93f3508c432daca21db0095f4b16542782b7986f48a5d0ae3c583d4

注:rs 会有 padding

4. js sample code

var EC = require("elliptic").ec;
require("buffer");

// Create and initialize EC context
// (better do it once and reuse it)
var ec = new EC("secp256k1");

// Generate keys
var key = ec.genKeyPair();

// Sign the message's hash (input must be an array, or a hex-string)
var msgHash = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var signature = key.sign(msgHash);

// Export DER encoded signature in Array
var derSign = signature.toDER();
console.log("derSign:" + Buffer.from(derSign).toString("hex"));

// Verify signature
console.log(key.verify(msgHash, derSign));

// CHECK WITH NO PRIVATE KEY

var pubPoint = key.getPublic();
var x = pubPoint.getX();
var y = pubPoint.getY();

// Public Key MUST be either:
// 1) '04' + hex string of x + hex string of y; or
// 2) object with two hex string properties (x and y); or
// 3) object with two buffer properties (x and y)
var pub = pubPoint.encode("hex"); // case 1
var pub = { x: x.toString("hex"), y: y.toString("hex") }; // case 2
var pub = { x: x.toBuffer(), y: y.toBuffer() }; // case 3
var pub = { x: x.toArrayLike(Buffer), y: y.toArrayLike(Buffer) }; // case 3

// Import public key
var key = ec.keyFromPublic(pub, "hex");

// Signature MUST be either:
// 1) DER-encoded signature as hex-string; or
// 2) DER-encoded signature as buffer; or
// 3) object with two hex-string properties (r and s); or
// 4) object with two buffer properties (r and s)

var signature = "3046022100..."; // case 1
var signature = new Buffer("..."); // case 2
var signature = { r: "b1fc...", s: "9c42..." }; // case 3

// Verify signature
console.log(key.verify(msgHash, signature));