Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

ecdsa

Package Overview
Dependencies
Maintainers
5
Versions
11
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ecdsa - npm Package Compare versions

Comparing version 0.6.0 to 0.7.0

lib/ecsignature.js

13

CHANGELOG.md

@@ -0,8 +1,11 @@

0.7.0 / 2015-12-13
------------------
- extracted bitcoinjs-lib `ecdsa`. Fixes a number of issues of security issues.
0.6.0 / 2014-09-30
------------------
- dropped alternative curve support, only `secp256k1` for now; if we find we need others in the future we can just grab
- dropped alternative curve support, only `secp256k1` for now; if we find we need others in the future we can just grab
them from Git history
- upgraded from `"ecurve": "^0.6.0"`to `"ecurve": "^1.0.0"`
0.5.3 / 2014-07-04

@@ -48,3 +51,3 @@ ------------------

* renamed `calcPubkeyRecoveryParam()` to `calcPubKeyRecoveryParam()`, changed signature
* added Testling support
* added Testling support

@@ -62,3 +65,3 @@

* moved from 4 spaces to 2 spaces (Node style)
* made class based so that multiple instantiations can be made with different curves, i.e. not just tied to `secp256k1`. Closes #2
* made class based so that multiple instantiations can be made with different curves, i.e. not just tied to `secp256k1`. Closes #2
BREAKING CHANGE. Set `ECDSA.ecparams` before using `ECDSA`.

@@ -81,3 +84,3 @@

------------------
* changed package name
* changed package name
* removed AMD support

@@ -84,0 +87,0 @@

@@ -1,104 +0,155 @@

var crypto = require('crypto')
var assert = require('assert')
var createHmac = require('create-hmac')
var typeforce = require('typeforce')
var types = require('./types')
var ecurve = require('ecurve')
var Point = ecurve.Point
var BigInteger = require('bigi')
var ECSignature = require('./ecsignature')
var util = require('./util')
var ZERO = new Buffer([0])
var ONE = new Buffer([1])
//dropped support for all others
var curve = ecurve.getCurveByName('secp256k1')
var ecurve = require('ecurve')
var secp256k1 = ecurve.getCurveByName('secp256k1')
// https://tools.ietf.org/html/rfc6979#section-3.2
function deterministicGenerateK (hash, x, checkSig) {
typeforce(types.tuple(
types.Hash256bit,
types.Buffer256bit,
types.Function
), arguments)
/**
* Calculate pubkey extraction parameter.
*
* When extracting a pubkey from a signature, we have to
* distinguish four different cases. Rather than putting this
* burden on the verifier, Bitcoin includes a 2-bit value with the
* signature.
*
* This function simply tries all four cases and returns the value
* that resulted in a successful pubkey recovery.
*/
function calcPubKeyRecoveryParam(e, signature, Q) {
for (var i = 0; i < 4; i++) {
var Qprime = recoverPubKey(e, signature, i)
var k = new Buffer(32)
var v = new Buffer(32)
if (Qprime.equals(Q)) {
return i
}
// Step A, ignored as hash already provided
// Step B
v.fill(1)
// Step C
k.fill(0)
// Step D
k = createHmac('sha256', k)
.update(v)
.update(ZERO)
.update(x)
.update(hash)
.digest()
// Step E
v = createHmac('sha256', k).update(v).digest()
// Step F
k = createHmac('sha256', k)
.update(v)
.update(ONE)
.update(x)
.update(hash)
.digest()
// Step G
v = createHmac('sha256', k).update(v).digest()
// Step H1/H2a, ignored as tlen === qlen (256 bit)
// Step H2b
v = createHmac('sha256', k).update(v).digest()
var T = BigInteger.fromBuffer(v)
// Step H3, repeat until T is within the interval [1, n - 1] and is suitable for ECDSA
while (T.signum() <= 0 || T.compareTo(secp256k1.n) >= 0 || !checkSig(T)) {
k = createHmac('sha256', k)
.update(v)
.update(ZERO)
.digest()
v = createHmac('sha256', k).update(v).digest()
// Step H1/H2a, again, ignored as tlen === qlen (256 bit)
// Step H2b again
v = createHmac('sha256', k).update(v).digest()
T = BigInteger.fromBuffer(v)
}
throw new Error('Unable to find valid recovery factor')
return T
}
function deterministicGenerateK(hash, D) {
assert(Buffer.isBuffer(hash), 'Hash must be a Buffer, not ' + hash)
assert.equal(hash.length, 32, 'Hash must be 256 bit')
assert(BigInteger.isBigInteger(D, true), 'Private key must be a BigInteger')
var N_OVER_TWO = secp256k1.n.shiftRight(1)
var x = D.toBuffer(32)
var k = new Buffer(32)
var v = new Buffer(32)
k.fill(0)
v.fill(1)
function sign (hash, d) {
typeforce(types.tuple(types.Hash256bit, types.BigInt), arguments)
k = util.hmacSHA256(Buffer.concat([v, new Buffer([0]), x, hash]), k)
v = util.hmacSHA256(v, k)
var x = d.toBuffer(32)
var e = BigInteger.fromBuffer(hash)
var n = secp256k1.n
var G = secp256k1.G
k = util.hmacSHA256(Buffer.concat([v, new Buffer([1]), x, hash]), k)
v = util.hmacSHA256(v, k)
v = util.hmacSHA256(v, k)
var r, s
deterministicGenerateK(hash, x, function (k) {
var Q = G.multiply(k)
var n = curve.n
var kB = BigInteger.fromBuffer(v).mod(n)
assert(kB.compareTo(BigInteger.ONE) > 0, 'Invalid k value')
assert(kB.compareTo(curve.n) < 0, 'Invalid k value')
if (secp256k1.isInfinity(Q)) return false
return kB
r = Q.affineX.mod(n)
if (r.signum() === 0) return false
s = k.modInverse(n).multiply(e.add(d.multiply(r))).mod(n)
if (s.signum() === 0) return false
return true
})
// enforce low S values, see bip62: 'low s values in signatures'
if (s.compareTo(N_OVER_TWO) > 0) {
s = n.subtract(s)
}
return new ECSignature(r, s)
}
function parseSig(buffer) {
assert.equal(buffer.readUInt8(0), 0x30, 'Not a DER sequence')
assert.equal(buffer.readUInt8(1), buffer.length - 2, 'Invalid sequence length')
function verify (hash, signature, Q) {
typeforce(types.tuple(
types.Hash256bit,
types.ECSignature,
types.ECPoint
), arguments)
assert.equal(buffer.readUInt8(2), 0x02, 'Expected a DER integer')
var rLen = buffer.readUInt8(3)
var rB = buffer.slice(4, 4 + rLen)
var n = secp256k1.n
var G = secp256k1.G
var offset = 4 + rLen
assert.equal(buffer.readUInt8(offset), 0x02, 'Expected a DER integer (2)')
var sLen = buffer.readUInt8(1 + offset)
var sB = buffer.slice(2 + offset)
offset += 2 + sLen
var r = signature.r
var s = signature.s
assert.equal(offset, buffer.length, 'Invalid DER encoding')
// 1.4.1 Enforce r and s are both integers in the interval [1, n − 1]
if (r.signum() <= 0 || r.compareTo(n) >= 0) return false
if (s.signum() <= 0 || s.compareTo(n) >= 0) return false
return { r: BigInteger.fromDERInteger(rB), s: BigInteger.fromDERInteger(sB) }
}
// 1.4.2 H = Hash(M), already done by the user
// 1.4.3 e = H
var e = BigInteger.fromBuffer(hash)
function parseSigCompact(buffer) {
assert.equal(buffer.length, 65, 'Invalid signature length')
var i = buffer.readUInt8(0) - 27
// Compute s^-1
var sInv = s.modInverse(n)
// At most 3 bits
assert.equal(i, i & 7, 'Invalid signature parameter')
var compressed = !!(i & 4)
// 1.4.4 Compute u1 = es^−1 mod n
// u2 = rs^−1 mod n
var u1 = e.multiply(sInv).mod(n)
var u2 = r.multiply(sInv).mod(n)
// Recovery param only
i = i & 3
// 1.4.5 Compute R = (xR, yR)
// R = u1G + u2Q
var R = G.multiplyTwo(u1, Q, u2)
var r = BigInteger.fromBuffer(buffer.slice(1, 33))
var s = BigInteger.fromBuffer(buffer.slice(33))
// 1.4.5 (cont.) Enforce R is not at infinity
if (secp256k1.isInfinity(R)) return false
return {
signature: {
r: r,
s: s
},
i: i,
compressed: compressed
}
// 1.4.6 Convert the field element R.x to an integer
var xR = R.affineX
// 1.4.7 Set v = xR mod n
var v = xR.mod(n)
// 1.4.8 If v = r, output "valid", and if v != r, output "invalid"
return v.equals(r)
}

@@ -114,13 +165,16 @@

*/
function recoverPubKey(e, signature, i) {
assert.strictEqual(i & 3, i, 'Recovery param is more than two bits')
function recoverPubKey (e, signature, i) {
typeforce(types.tuple(
types.BigInt,
types.ECSignature,
types.UInt2
), arguments)
var n = curve.n
var G = curve.G
var n = secp256k1.n
var G = secp256k1.G
var r = signature.r
var s = signature.s
assert(r.signum() > 0 && r.compareTo(n) < 0, 'Invalid r value')
assert(s.signum() > 0 && s.compareTo(n) < 0, 'Invalid s value')
if (r.signum() <= 0 || r.compareTo(n) >= 0) throw new Error('Invalid r value')
if (s.signum() <= 0 || s.compareTo(n) >= 0) throw new Error('Invalid s value')

@@ -136,8 +190,11 @@ // A set LSB signifies that the y-coordinate is odd

var x = isSecondKey ? r.add(n) : r
var R = curve.pointFromX(isYOdd, x)
var R = secp256k1.pointFromX(isYOdd, x)
// 1.4 Check that nR is at infinity
var nR = R.multiply(n)
assert(curve.isInfinity(nR), 'nR is not a valid curve point')
if (!secp256k1.isInfinity(nR)) throw new Error('nR is not a valid curve point')
// Compute r^-1
var rInv = r.modInverse(n)
// Compute -e from e

@@ -148,135 +205,46 @@ var eNeg = e.negate().mod(n)

// Q = r^-1 (sR + -eG)
var rInv = r.modInverse(n)
var Q = R.multiplyTwo(s, G, eNeg).multiply(rInv)
curve.validate(Q)
secp256k1.validate(Q)
return Q
}
/**
* Calculate pubkey extraction parameter.
*
* When extracting a pubkey from a signature, we have to
* distinguish four different cases. Rather than putting this
* burden on the verifier, Bitcoin includes a 2-bit value with the
* signature.
*
* This function simply tries all four cases and returns the value
* that resulted in a successful pubkey recovery.
*/
function calcPubKeyRecoveryParam (e, signature, Q) {
typeforce(types.tuple(
types.BigInt,
types.ECSignature,
types.ECPoint
), arguments)
function serializeSig(signature) {
//var rBa = r.toByteArraySigned();
//var sBa = s.toByteArraySigned();
var rBa = signature.r.toDERInteger()
var sBa = signature.s.toDERInteger()
for (var i = 0; i < 4; i++) {
var Qprime = recoverPubKey(e, signature, i)
var sequence = [];
sequence.push(0x02); // INTEGER
sequence.push(rBa.length);
sequence = sequence.concat(rBa);
sequence.push(0x02); // INTEGER
sequence.push(sBa.length);
sequence = sequence.concat(sBa);
sequence.unshift(sequence.length);
sequence.unshift(0x30); // SEQUENCE
return sequence;
}
function serializeSigCompact(signature, i, compressed) {
if (compressed) {
i += 4
// 1.6.2 Verify Q
if (Qprime.equals(Q)) {
return i
}
}
i += 27
var buffer = new Buffer(65)
buffer.writeUInt8(i, 0)
signature.r.toBuffer(32).copy(buffer, 1)
signature.s.toBuffer(32).copy(buffer, 33)
return buffer
throw new Error('Unable to find valid recovery factor')
}
function sign(hash, privateKey) {
if (Buffer.isBuffer(privateKey))
var D = BigInteger.fromBuffer(privateKey)
else
var D = privateKey //big integer for legacy compatiblity
var k = deterministicGenerateK(hash, D)
var n = curve.n
var G = curve.G
var Q = G.multiply(k)
var e = BigInteger.fromBuffer(hash)
var r = Q.affineX.mod(n)
assert.notEqual(r.signum(), 0, 'Invalid R value')
var s = k.modInverse(n).multiply(e.add(D.multiply(r))).mod(n)
assert.notEqual(s.signum(), 0, 'Invalid S value')
var N_OVER_TWO = n.shiftRight(1)
// enforce low S values, see bip62: 'low s values in signatures'
if (s.compareTo(N_OVER_TWO) > 0) {
s = n.subtract(s)
}
return {r: r, s: s}
}
function verify(hash, signature, pubkey) {
assert(signature.r && signature.s, "Invalid signature.")
var Q;
if (Buffer.isBuffer(pubkey)) {
Q = Point.decodeFrom(curve, pubkey);
} else {
throw new Error("Invalid format for pubkey value, must be Buffer");
}
var e = BigInteger.fromBuffer(hash);
return verifyRaw(e, {r: signature.r, s: signature.s}, Q)
}
function verifyRaw(e, signature, Q) {
var n = curve.n
var G = curve.G
var r = signature.r
var s = signature.s
// 1.4.1 Enforce r and s are both integers in the interval [1, n − 1]
if (r.signum() <= 0 || r.compareTo(n) >= 0) return false
if (s.signum() <= 0 || s.compareTo(n) >= 0) return false
// c = s^-1 mod n
var c = s.modInverse(n)
// 1.4.4 Compute u1 = es^−1 mod n
// u2 = rs^−1 mod n
var u1 = e.multiply(c).mod(n)
var u2 = r.multiply(c).mod(n)
// 1.4.5 Compute R = (xR, yR) = u1G + u2Q
var R = G.multiplyTwo(u1, Q, u2)
var v = R.affineX.mod(n)
// 1.4.5 (cont.) Enforce R is not at infinity
if (curve.isInfinity(R)) return false
// 1.4.8 If v = r, output "valid", and if v != r, output "invalid"
return v.equals(r)
}
module.exports = {
curve: curve,
calcPubKeyRecoveryParam: calcPubKeyRecoveryParam,
deterministicGenerateK: deterministicGenerateK,
parseSig: parseSig,
parseSigCompact: parseSigCompact,
recoverPubKey: recoverPubKey,
serializeSig: serializeSig,
serializeSigCompact: serializeSigCompact,
sign: sign,
verify: verify,
verifyRaw: verifyRaw
curve: secp256k1
}
var crypto = require('crypto')
function hmacSHA256 (v, k) {
return crypto.createHmac('sha256', k).update(v).digest()
}
module.exports = {
hmacSHA256: hmacSHA256
}
function hmacSHA256(v, k) {
return crypto.createHmac('sha256', k).update(v).digest()
}
{
"name": "ecdsa",
"version": "0.6.0",
"description": "Elliptical Curve Cryptography Digital Signing",
"version": "0.7.0",
"description": "Elliptic Curve Cryptography Digital Signing",
"keywords": [

@@ -10,3 +10,3 @@ "cryptography",

"litecoin",
"elliptical",
"elliptic",
"curve",

@@ -18,9 +18,10 @@ "digital",

"devDependencies": {
"mocha": "1.*",
"terst": "~0.1.0",
"coveralls": "^2.10.0",
"electron-mocha": "^0.6.3",
"istanbul": "^0.2.10",
"mocha": "^2.3.4",
"mocha-lcov-reporter": "0.0.1",
"istanbul": "^0.2.10",
"secure-random": "^0.2.1",
"mochify": "^1.1.3"
"sinon": "^1.17.2",
"standard": "^5.4.1"
},

@@ -31,8 +32,14 @@ "repository": {

},
"main": "./lib/ecdsa.js",
"license": "MIT",
"main": "./lib/index.js",
"dependencies": {
"bigi": "^1.2.1",
"ecurve": "^1.0.0"
"bip66": "^1.1.0",
"create-hmac": "^1.1.4",
"ecurve": "^1.0.0",
"typeforce": "^1.6.1"
},
"scripts": {
"browser-test": "electron-mocha",
"standard": "standard",
"test": "mocha --ui bdd",

@@ -39,0 +46,0 @@ "unit": "./node_modules/.bin/mocha",

@@ -7,16 +7,6 @@ ecdsa

JavaScript component for Elliptical Curve Cryptography signing and verification. This module is important to sign transactions. Works
JavaScript component for Elliptic Curve Cryptography signing and verification. This module is important to sign transactions. Works
with both Node.js and the browser.
### Official documentation:
http://cryptocoinjs.com/modules/crypto/ecdsa/
**This has been extracted from [bitcoinjs-lib@2.1.4](https://github.com/bitcoinjs/bitcoinjs-lib/tree/v2.1.4) and will track
it for the foreseeable future.**

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc