This repository has been archived by the owner on Apr 3, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1k
/
point.js
150 lines (128 loc) · 3.42 KB
/
point.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
'use strict';
var BN = require('./bn');
var BufferUtil = require('../util/buffer');
var EC = require('elliptic').ec;
var ec = new EC('secp256k1');
var ecPoint = ec.curve.point.bind(ec.curve);
var ecPointFromX = ec.curve.pointFromX.bind(ec.curve);
/**
*
* Instantiate a valid secp256k1 Point from the X and Y coordinates.
*
* @param {BN|String} x - The X coordinate
* @param {BN|String} y - The Y coordinate
* @link https://github.com/indutny/elliptic
* @augments elliptic.curve.point
* @throws {Error} A validation error if exists
* @returns {Point} An instance of Point
* @constructor
*/
var Point = function Point(x, y, isRed) {
try {
var point = ecPoint(x, y, isRed);
} catch (e) {
throw new Error('Invalid Point');
}
point.validate();
return point;
};
Point.prototype = Object.getPrototypeOf(ec.curve.point());
/**
*
* Instantiate a valid secp256k1 Point from only the X coordinate
*
* @param {boolean} odd - If the Y coordinate is odd
* @param {BN|String} x - The X coordinate
* @throws {Error} A validation error if exists
* @returns {Point} An instance of Point
*/
Point.fromX = function fromX(odd, x){
try {
var point = ecPointFromX(x, odd);
} catch (e) {
throw new Error('Invalid X');
}
point.validate();
return point;
};
/**
*
* Will return a secp256k1 ECDSA base point.
*
* @link https://en.bitcoin.it/wiki/Secp256k1
* @returns {Point} An instance of the base point.
*/
Point.getG = function getG() {
return ec.curve.g;
};
/**
*
* Will return the max of range of valid private keys as governed by the secp256k1 ECDSA standard.
*
* @link https://en.bitcoin.it/wiki/Private_key#Range_of_valid_ECDSA_private_keys
* @returns {BN} A BN instance of the number of points on the curve
*/
Point.getN = function getN() {
return new BN(ec.curve.n.toArray());
};
Point.prototype._getX = Point.prototype.getX;
/**
*
* Will return the X coordinate of the Point
*
* @returns {BN} A BN instance of the X coordinate
*/
Point.prototype.getX = function getX() {
return new BN(this._getX().toArray());
};
Point.prototype._getY = Point.prototype.getY;
/**
*
* Will return the Y coordinate of the Point
*
* @returns {BN} A BN instance of the Y coordinate
*/
Point.prototype.getY = function getY() {
return new BN(this._getY().toArray());
};
/**
*
* Will determine if the point is valid
*
* @link https://www.iacr.org/archive/pkc2003/25670211/25670211.pdf
* @param {Point} An instance of Point
* @throws {Error} A validation error if exists
* @returns {Point} An instance of the same Point
*/
Point.prototype.validate = function validate() {
if (this.isInfinity()){
throw new Error('Point cannot be equal to Infinity');
}
var p2;
try {
p2 = ecPointFromX(this.getX(), this.getY().isOdd());
} catch (e) {
throw new Error('Point does not lie on the curve');
}
if (p2.y.cmp(this.y) !== 0) {
throw new Error('Invalid y value for curve.');
}
//todo: needs test case
if (!(this.mul(Point.getN()).isInfinity())) {
throw new Error('Point times N must be infinity');
}
return this;
};
Point.pointToCompressed = function pointToCompressed(point) {
var xbuf = point.getX().toBuffer({size: 32});
var ybuf = point.getY().toBuffer({size: 32});
var prefix;
var odd = ybuf[ybuf.length - 1] % 2;
if (odd) {
prefix = Buffer.from([0x03]);
} else {
prefix = Buffer.from([0x02]);
}
return BufferUtil.concat([prefix, xbuf]);
};
module.exports = Point;