Skip to content

Commit 0030854

Browse files
committed
wip
1 parent d47ed2c commit 0030854

File tree

6 files changed

+163
-125
lines changed

6 files changed

+163
-125
lines changed

src/ecdsa.js

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -237,13 +237,65 @@ function calcPubKeyRecoveryParam (e, signature, Q) {
237237
throw new Error('Unable to find valid recovery factor')
238238
}
239239

240+
function intAdd (a, b) {
241+
typeforce(types.tuple(types.Buffer, types.Buffer), arguments)
242+
243+
var A = BigInteger.fromBuffer(a)
244+
var B = BigInteger.fromBuffer(b)
245+
246+
return A.add(B).toBuffer(32)
247+
}
248+
249+
function intCheck (a) {
250+
typeforce(types.tuple(types.Buffer), arguments)
251+
252+
var A = BigInteger.fromBuffer(a)
253+
254+
return A.signum() > 0 && A.compareTo(secp256k1.n) < 0
255+
}
256+
257+
function intSign (a) {
258+
typeforce(types.tuple(types.Buffer), arguments)
259+
260+
return BigInteger.fromBuffer(a).signum()
261+
}
262+
263+
function pointAdd (p, q) {
264+
typeforce(types.tuple(types.Buffer, types.Buffer), arguments)
265+
266+
var P = ecurve.Point.decodeFrom(p)
267+
var Q = ecurve.Point.decodeFrom(q)
268+
var R = P.add(Q)
269+
270+
if (secp256k1.isInfinity(R)) return null
271+
return R.getEncoded(P.compressed)
272+
}
273+
274+
function pointDerive (d, compressed) {
275+
typeforce(types.tuple(types.Buffer, types.Boolean), arguments)
276+
277+
d = BigInteger.fromBuffer(d)
278+
return secp256k1.G.multiply(d).getEncoded(compressed)
279+
}
280+
281+
function pointVerify (q) {
282+
typeforce(types.tuple(types.Buffer), arguments)
283+
var Q = ecurve.Point.decodeFrom(q)
284+
285+
return secp256k1.validate(Q)
286+
}
287+
240288
module.exports = {
241289
calcPubKeyRecoveryParam: calcPubKeyRecoveryParam,
242290
deterministicGenerateK: deterministicGenerateK,
243291
recoverPubKey: recoverPubKey,
244292
sign: sign,
245293
verify: verify,
246294

247-
// TODO: remove
248-
__curve: secp256k1
295+
intAdd: intAdd,
296+
intCheck: intCheck,
297+
intSign: intSign,
298+
pointAdd: pointAdd,
299+
pointDerive: pointDerive,
300+
pointVerify: pointVerify
249301
}

src/ecpair.js

Lines changed: 53 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,56 @@
1+
var baddress = require('./address')
12
var bcrypto = require('./crypto')
23
var bs58check = require('bs58check')
3-
var ecdsa = require('./ecdsa')
44
var randomBytes = require('randombytes')
5+
var secp256k1 = require('./ecdsa')
56
var typeforce = require('typeforce')
67
var types = require('./types')
78
var wif = require('wif')
89

910
var NETWORKS = require('./networks')
10-
var BigInteger = require('bigi')
11-
12-
var ecurve = require('ecurve')
13-
var secp256k1 = ecdsa.__curve
1411

1512
function ECPair (d, Q, options) {
1613
if (options) {
1714
typeforce({
1815
compressed: types.maybe(types.Boolean),
19-
network: types.maybe(types.Network)
16+
network: types.maybe(types.Network),
17+
validate: types.maybe(types.Boolean)
2018
}, options)
19+
} else {
20+
options = {}
2121
}
2222

23-
options = options || {}
23+
options.network = options.network || NETWORKS.bitcoin
2424

2525
if (d) {
26-
if (d.signum() <= 0) throw new Error('Private key must be greater than 0')
27-
if (d.compareTo(secp256k1.n) >= 0) throw new Error('Private key must be less than the curve order')
28-
if (Q) throw new TypeError('Unexpected publicKey parameter')
26+
typeforce(types.Buffer256bit, d)
2927

30-
this.d = d
31-
} else {
32-
typeforce(types.ECPoint, Q)
28+
if (Q) throw new TypeError('Unexpected public key parameter')
29+
if (!secp256k1.intCheck(d)) throw new TypeError('Private key must be within the interval [1, n - 1]')
3330

34-
this.__Q = Q
35-
}
31+
this.__d = d
32+
this.__compressed = options.compressed === undefined ? true : options.compressed
33+
} else if (Q) {
34+
typeforce(types.Buffer, Q)
3635

37-
this.compressed = options.compressed === undefined ? true : options.compressed
38-
this.network = options.network || NETWORKS.bitcoin
39-
}
36+
if (options.validate) {
37+
secp256k1.pointVerify(Q)
38+
}
4039

41-
Object.defineProperty(ECPair.prototype, 'Q', {
42-
get: function () {
43-
if (!this.__Q && this.d) {
44-
this.__Q = secp256k1.G.multiply(this.d)
40+
if (options.compressed && Q.length !== 65) {
41+
throw new TypeError('Expected compressed public key')
42+
} else if (Q.length !== 33) {
43+
throw new TypeError('Expected uncompressed public key')
4544
}
4645

47-
return this.__Q
48-
}
49-
})
46+
this.__Q = Q
5047

51-
ECPair.fromPublicKeyBuffer = function (buffer, network) {
52-
var Q = ecurve.Point.decodeFrom(secp256k1, buffer)
48+
// TODO: remove
49+
this.__compressed = (Q.length === 33)
50+
}
5351

54-
return new ECPair(null, Q, {
55-
compressed: Q.compressed,
56-
network: network
57-
})
52+
typeforce(types.Network, options.network)
53+
this.__network = options.network
5854
}
5955

6056
ECPair.fromWIF = function (string, network) {
@@ -69,10 +65,9 @@ ECPair.fromWIF = function (string, network) {
6965
}).pop() || {}
7066
}
7167

72-
var decoded = wif.decodeRaw(network.wif, buffer)
73-
var d = BigInteger.fromBuffer(decoded.d)
68+
var decoded = wif.decode(network.wif, string)
7469

75-
return new ECPair(d, null, {
70+
return new ECPair(decoded.d, null, {
7671
compressed: decoded.compressed,
7772
network: network
7873
})
@@ -82,51 +77,52 @@ ECPair.makeRandom = function (options) {
8277
options = options || {}
8378

8479
var rng = options.rng || randomBytes
85-
8680
var d
8781
do {
88-
var buffer = rng(32)
89-
typeforce(types.Buffer256bit, buffer)
90-
91-
d = BigInteger.fromBuffer(buffer)
92-
} while (d.signum() <= 0 || d.compareTo(secp256k1.n) >= 0)
82+
d = rng(32)
83+
typeforce(types.Buffer256bit, d)
84+
} while (!secp256k1.intCheck(d))
9385

9486
return new ECPair(d, null, options)
9587
}
9688

9789
ECPair.prototype.getAddress = function () {
98-
var pubKey = this.getPublicKeyBuffer()
99-
var pubKeyHash = bcrypto.hash160(pubKey)
90+
return baddress.toBase58Check(bcrypto.hash160(this.getPublic()), this.getNetwork().pubKeyHash)
91+
}
10092

101-
var payload = new Buffer(21)
102-
payload.writeUInt8(this.network.pubKeyHash, 0)
103-
pubKeyHash.copy(payload, 1)
93+
ECPair.prototype.getNetwork = function () {
94+
return this.__network
95+
}
10496

105-
return bs58check.encode(payload)
97+
ECPair.prototype.getPrivate = function () {
98+
if (!this.__d) throw new Error('Missing private key')
99+
return this.__d
106100
}
107101

108-
ECPair.prototype.getNetwork = function () {
109-
return this.network
102+
ECPair.prototype.getPublic = function () {
103+
if (!this.__Q) {
104+
this.__Q = secp256k1.pointDerive(this.getPrivate(), this.isCompressed())
105+
}
106+
107+
return this.__Q
110108
}
111109

112-
ECPair.prototype.getPublicKeyBuffer = function () {
113-
return this.Q.getEncoded(this.compressed)
110+
ECPair.prototype.isCompressed = function () {
111+
return this.__compressed
112+
// return this.getPublic().length === 33
114113
}
115114

116115
ECPair.prototype.sign = function (hash) {
117-
if (!this.d) throw new Error('Missing private key')
118-
119-
return ecdsa.sign(hash, this.d)
116+
return secp256k1.sign(hash, this.getPrivate())
120117
}
121118

122119
ECPair.prototype.toWIF = function () {
123-
if (!this.d) throw new Error('Missing private key')
124-
125-
return wif.encode(this.network.wif, this.d.toBuffer(32), this.compressed)
120+
if (!this.__d) throw new Error('Missing private key')
121+
return wif.encode(this.getNetwork().wif, this.getPrivate(), this.isCompressed())
126122
}
127123

128124
ECPair.prototype.verify = function (hash, signature) {
129-
return ecdsa.verify(hash, signature, this.Q)
125+
return secp256k1.verify(hash, signature, this.getPublic())
130126
}
131127

132128
module.exports = ECPair

0 commit comments

Comments
 (0)