UNPKG

ecdsa-node-ts

Version:

TypeScript implementation of the Elliptic Curve Digital Signature Algorithm (ECDSA)

113 lines (112 loc) 4.58 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.multiply = multiply; exports.add = add; exports.inv = inv; const point_1 = require("./point"); const integer_1 = require("./utils/integer"); const big_integer_1 = __importDefault(require("big-integer")); function multiply(p, n, N, A, P) { // Fast way to multiply point and scalar in elliptic curves return fromJacobian(jacobianMultiply(toJacobian(p), n, N, A, P), P); } function add(p, q, A, P) { // Fast way to add two points in elliptic curves return fromJacobian(jacobianAdd(toJacobian(p), toJacobian(q), A, P), P); } function inv(x, n) { // Extended Euclidean Algorithm. It's the 'division' in elliptic curves if (x.eq(0)) { return (0, big_integer_1.default)(0); } let lm = (0, big_integer_1.default)(1); let hm = (0, big_integer_1.default)(0); let low = (0, integer_1.modulo)(x, n); let high = n; let r, nm, newLow; while (low.greater(1)) { r = high.over(low); // bigint division floors result automatically nm = hm.minus(lm.multiply(r)); newLow = high.minus(low.multiply(r)); high = low; hm = lm; low = newLow; lm = nm; } return (0, integer_1.modulo)(lm, n); } function toJacobian(p) { // Convert point to Jacobian coordinates return new point_1.Point(p.x, p.y, (0, big_integer_1.default)(1)); } function fromJacobian(p, P) { // Convert point back from Jacobian coordinates let z = inv(p.z, P); return new point_1.Point((0, integer_1.modulo)(p.x.multiply(z.pow(2)), P), (0, integer_1.modulo)(p.y.multiply(z.pow(3)), P)); } function jacobianDouble(p, A, P) { // Double a point in elliptic curves if (p.y.equals(0)) { return new point_1.Point((0, big_integer_1.default)(0), (0, big_integer_1.default)(0), (0, big_integer_1.default)(0)); } let ysq = (0, integer_1.modulo)(p.y.pow(2), P); let S = (0, integer_1.modulo)(p.x.multiply(ysq).multiply(4), P); let M = (0, integer_1.modulo)(p.x .pow(2) .multiply(3) .add(A.multiply(p.z.pow(4))), P); let nx = (0, integer_1.modulo)(M.pow(2).minus(S.multiply(2)), P); let ny = (0, integer_1.modulo)(M.multiply(S.minus(nx)).minus(ysq.pow(2).multiply(8)), P); let nz = (0, integer_1.modulo)(p.y.multiply(p.z).multiply(2), P); return new point_1.Point(nx, ny, nz); } function jacobianAdd(p, q, A, P) { // Add two points in elliptic curves if (p.y.equals(0)) { return q; } if (q.y.equals(0)) { return p; } let U1 = (0, integer_1.modulo)(p.x.multiply(q.z.pow(2)), P); let U2 = (0, integer_1.modulo)(q.x.multiply(p.z.pow(2)), P); let S1 = (0, integer_1.modulo)(p.y.multiply(q.z.pow(3)), P); let S2 = (0, integer_1.modulo)(q.y.multiply(p.z.pow(3)), P); if (U1.eq(U2)) { if (S1.neq(S2)) { return new point_1.Point((0, big_integer_1.default)(0), (0, big_integer_1.default)(0), (0, big_integer_1.default)(1)); } return jacobianDouble(p, A, P); } let H = U2.minus(U1); let R = S2.minus(S1); let H2 = (0, integer_1.modulo)(H.multiply(H), P); let H3 = (0, integer_1.modulo)(H.multiply(H2), P); let U1H2 = (0, integer_1.modulo)(U1.multiply(H2), P); let nx = (0, integer_1.modulo)(R.pow(2).minus(H3).minus(U1H2.multiply(2)), P); let ny = (0, integer_1.modulo)(R.multiply(U1H2.minus(nx)).minus(S1.multiply(H3)), P); let nz = (0, integer_1.modulo)(H.multiply(p.z).multiply(q.z), P); return new point_1.Point(nx, ny, nz); } function jacobianMultiply(p, n, N, A, P) { // Multiply point and scalar in elliptic curves if (p.y.equals(0) || n.eq(0)) { return new point_1.Point((0, big_integer_1.default)(0), (0, big_integer_1.default)(0), (0, big_integer_1.default)(1)); } if (n.eq(1)) { return p; } if (n.lesser(0) || n.greaterOrEquals(N)) { return jacobianMultiply(p, (0, integer_1.modulo)(n, N), N, A, P); } if ((0, integer_1.modulo)(n, (0, big_integer_1.default)(2)).eq(0)) { return jacobianDouble(jacobianMultiply(p, n.over(2), N, A, P), A, P); } if ((0, integer_1.modulo)(n, (0, big_integer_1.default)(2)).eq(1)) { return jacobianAdd(jacobianDouble(jacobianMultiply(p, n.over(2), N, A, P), A, P), p, A, P); } throw new Error(`logical failure: p: ${p}, n: ${n}, N: ${N}, A: ${A}, P: ${P}`); }