js-ecutils
Version:
JavaScript Library for Elliptic Curve Cryptography: key exchanges (Diffie-Hellman, Massey-Omura), ECDSA signatures, and Koblitz encoding. Suitable for crypto education and secure systems.
130 lines (127 loc) • 17.5 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.affineAdd = affineAdd;
exports.affineDouble = affineDouble;
exports.affineMul = affineMul;
var _math = require("../../utils/math.js");
function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
function _arrayWithHoles(r) { if (Array.isArray(r)) return r; } /**
* Elliptic curve arithmetic in affine coordinates.
*
* In affine coordinates a point on the curve y² = x³ + ax + b (mod p) is
* represented directly by its (x, y) pair. Each addition or doubling
* requires one modular inversion, making this system straightforward but
* slower than projective alternatives for scalar multiplication.
*
* Note: these routines are NOT constant-time and should not be used in
* production contexts where timing side-channels are a concern.
* See RFC 6090, Section 4 for background on secure implementation
* considerations.
*/
/**
* Double a point in affine coordinates.
*
* Computes 2P using the tangent-line formula:
*
* λ = (3x₁² + a) · (2y₁)⁻¹ (mod p)
* x₃ = λ² - 2x₁ (mod p)
* y₃ = λ(x₁ - x₃) - y₁ (mod p)
*
* Returns [null, null] (identity) if the input is the identity or if
* 2y₁ ≡ 0 (mod p) (vertical tangent).
*
* @param {BigInt|null} px - x-coordinate (null for identity).
* @param {BigInt|null} py - y-coordinate (null for identity).
* @param {CurveParams} curve
* @returns {[BigInt|null, BigInt|null]}
*/
function affineDouble(px, py, curve) {
if (px === null || py === null) return [null, null];
var p = curve.p;
var num = (0, _math.modulus)(3n * px * px + curve.a, p);
var den = (0, _math.modulus)(2n * py, p);
if (den === 0n) return [null, null];
var inv = (0, _math.modInverse)(den, p);
var s = num * inv % p;
var x3 = (0, _math.modulus)(s * s - 2n * px, p);
var y3 = (0, _math.modulus)(s * (px - x3) - py, p);
return [x3, y3];
}
/**
* Add two distinct points in affine coordinates.
*
* Given P₁ = (x₁, y₁) and P₂ = (x₂, y₂) with P₁ ≠ P₂, the chord-line
* formula is:
*
* λ = (y₂ - y₁) · (x₂ - x₁)⁻¹ (mod p)
* x₃ = λ² - x₁ - x₂ (mod p)
* y₃ = λ(x₁ - x₃) - y₁ (mod p)
*
* If P₁ = P₂ the call is forwarded to {@link affineDouble}.
*
* @param {BigInt|null} p1x
* @param {BigInt|null} p1y
* @param {BigInt|null} p2x
* @param {BigInt|null} p2y
* @param {CurveParams} curve
* @returns {[BigInt|null, BigInt|null]}
*/
function affineAdd(p1x, p1y, p2x, p2y, curve) {
if (p1x === null || p1y === null) return [p2x, p2y];
if (p2x === null || p2y === null) return [p1x, p1y];
if (p1x === p2x && p1y === p2y) return affineDouble(p1x, p1y, curve);
var p = curve.p;
var num = (0, _math.modulus)(p2y - p1y, p);
var den = (0, _math.modulus)(p2x - p1x, p);
if (den === 0n) return [null, null];
var inv = (0, _math.modInverse)(den, p);
var s = num * inv % p;
var x3 = (0, _math.modulus)(s * s - p1x - p2x, p);
var y3 = (0, _math.modulus)(s * (p1x - x3) - p1y, p);
return [x3, y3];
}
/**
* Scalar multiplication in affine coordinates (double-and-add).
*
* Computes k·P by scanning the bits of k from LSB to MSB,
* accumulating the result and doubling the base at each step.
* Runs in O(log k) doublings and at most O(log k) additions.
*
* Warning: the double-and-add algorithm is NOT constant-time: the number
* of additions depends on the Hamming weight of k. For
* constant-time requirements see RFC 6090, Section 4.
*
* @param {BigInt} k - Scalar multiplier.
* @param {BigInt|null} px - x-coordinate of the base point.
* @param {BigInt|null} py - y-coordinate of the base point.
* @param {CurveParams} curve
* @returns {[BigInt|null, BigInt|null]}
*/
function affineMul(k, px, py, curve) {
if (px === null || py === null || k === 0n) return [null, null];
var rx = null,
ry = null;
while (k > 0n) {
if (k & 1n) {
;
var _affineAdd = affineAdd(rx, ry, px, py, curve);
var _affineAdd2 = _slicedToArray(_affineAdd, 2);
rx = _affineAdd2[0];
ry = _affineAdd2[1];
}
;
var _affineDouble = affineDouble(px, py, curve);
var _affineDouble2 = _slicedToArray(_affineDouble, 2);
px = _affineDouble2[0];
py = _affineDouble2[1];
k >>= 1n;
}
return [rx, ry];
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfbWF0aCIsInJlcXVpcmUiLCJfc2xpY2VkVG9BcnJheSIsInIiLCJlIiwiX2FycmF5V2l0aEhvbGVzIiwiX2l0ZXJhYmxlVG9BcnJheUxpbWl0IiwiX3Vuc3VwcG9ydGVkSXRlcmFibGVUb0FycmF5IiwiX25vbkl0ZXJhYmxlUmVzdCIsIlR5cGVFcnJvciIsImEiLCJfYXJyYXlMaWtlVG9BcnJheSIsInQiLCJ0b1N0cmluZyIsImNhbGwiLCJzbGljZSIsImNvbnN0cnVjdG9yIiwibmFtZSIsIkFycmF5IiwiZnJvbSIsInRlc3QiLCJsZW5ndGgiLCJuIiwibCIsIlN5bWJvbCIsIml0ZXJhdG9yIiwiaSIsInUiLCJmIiwibyIsIm5leHQiLCJPYmplY3QiLCJkb25lIiwicHVzaCIsInZhbHVlIiwiaXNBcnJheSIsImFmZmluZURvdWJsZSIsInB4IiwicHkiLCJjdXJ2ZSIsInAiLCJudW0iLCJtb2R1bHVzIiwiZGVuIiwiaW52IiwibW9kSW52ZXJzZSIsInMiLCJ4MyIsInkzIiwiYWZmaW5lQWRkIiwicDF4IiwicDF5IiwicDJ4IiwicDJ5IiwiYWZmaW5lTXVsIiwiayIsInJ4IiwicnkiLCJfYWZmaW5lQWRkIiwiX2FmZmluZUFkZDIiLCJfYWZmaW5lRG91YmxlIiwiX2FmZmluZURvdWJsZTIiXSwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvY29yZS9hcml0aG1ldGljL2FmZmluZS5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEVsbGlwdGljIGN1cnZlIGFyaXRobWV0aWMgaW4gYWZmaW5lIGNvb3JkaW5hdGVzLlxuICpcbiAqIEluIGFmZmluZSBjb29yZGluYXRlcyBhIHBvaW50IG9uIHRoZSBjdXJ2ZSB5wrIgPSB4wrMgKyBheCArIGIgKG1vZCBwKSBpc1xuICogcmVwcmVzZW50ZWQgZGlyZWN0bHkgYnkgaXRzICh4LCB5KSBwYWlyLiAgRWFjaCBhZGRpdGlvbiBvciBkb3VibGluZ1xuICogcmVxdWlyZXMgb25lIG1vZHVsYXIgaW52ZXJzaW9uLCBtYWtpbmcgdGhpcyBzeXN0ZW0gc3RyYWlnaHRmb3J3YXJkIGJ1dFxuICogc2xvd2VyIHRoYW4gcHJvamVjdGl2ZSBhbHRlcm5hdGl2ZXMgZm9yIHNjYWxhciBtdWx0aXBsaWNhdGlvbi5cbiAqXG4gKiBOb3RlOiB0aGVzZSByb3V0aW5lcyBhcmUgTk9UIGNvbnN0YW50LXRpbWUgYW5kIHNob3VsZCBub3QgYmUgdXNlZCBpblxuICogcHJvZHVjdGlvbiBjb250ZXh0cyB3aGVyZSB0aW1pbmcgc2lkZS1jaGFubmVscyBhcmUgYSBjb25jZXJuLlxuICogU2VlIFJGQyA2MDkwLCBTZWN0aW9uIDQgZm9yIGJhY2tncm91bmQgb24gc2VjdXJlIGltcGxlbWVudGF0aW9uXG4gKiBjb25zaWRlcmF0aW9ucy5cbiAqL1xuXG5pbXBvcnQgeyBtb2R1bHVzLCBtb2RJbnZlcnNlIH0gZnJvbSAnLi4vLi4vdXRpbHMvbWF0aC5qcydcblxuLyoqXG4gKiBEb3VibGUgYSBwb2ludCBpbiBhZmZpbmUgY29vcmRpbmF0ZXMuXG4gKlxuICogQ29tcHV0ZXMgMlAgdXNpbmcgdGhlIHRhbmdlbnQtbGluZSBmb3JtdWxhOlxuICpcbiAqICAgICDOuyAgPSAoM3jigoHCsiArIGEpIMK3ICgyeeKCgSnigbvCuSAgKG1vZCBwKVxuICogICAgIHjigoMgPSDOu8KyIC0gMnjigoEgICAgICAgICAgICAgIChtb2QgcClcbiAqICAgICB54oKDID0gzrsoeOKCgSAtIHjigoMpIC0geeKCgSAgICAgIChtb2QgcClcbiAqXG4gKiBSZXR1cm5zIFtudWxsLCBudWxsXSAoaWRlbnRpdHkpIGlmIHRoZSBpbnB1dCBpcyB0aGUgaWRlbnRpdHkgb3IgaWZcbiAqIDJ54oKBIOKJoSAwIChtb2QgcCkgKHZlcnRpY2FsIHRhbmdlbnQpLlxuICpcbiAqIEBwYXJhbSB7QmlnSW50fG51bGx9IHB4IC0geC1jb29yZGluYXRlIChudWxsIGZvciBpZGVudGl0eSkuXG4gKiBAcGFyYW0ge0JpZ0ludHxudWxsfSBweSAtIHktY29vcmRpbmF0ZSAobnVsbCBmb3IgaWRlbnRpdHkpLlxuICogQHBhcmFtIHtDdXJ2ZVBhcmFtc30gY3VydmVcbiAqIEByZXR1cm5zIHtbQmlnSW50fG51bGwsIEJpZ0ludHxudWxsXX1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFmZmluZURvdWJsZShweCwgcHksIGN1cnZlKSB7XG4gIGlmIChweCA9PT0gbnVsbCB8fCBweSA9PT0gbnVsbCkgcmV0dXJuIFtudWxsLCBudWxsXVxuICBjb25zdCBwID0gY3VydmUucFxuICBjb25zdCBudW0gPSBtb2R1bHVzKDNuICogcHggKiBweCArIGN1cnZlLmEsIHApXG4gIGNvbnN0IGRlbiA9IG1vZHVsdXMoMm4gKiBweSwgcClcbiAgaWYgKGRlbiA9PT0gMG4pIHJldHVybiBbbnVsbCwgbnVsbF1cbiAgY29uc3QgaW52ID0gbW9kSW52ZXJzZShkZW4sIHApXG4gIGNvbnN0IHMgPSAobnVtICogaW52KSAlIHBcbiAgY29uc3QgeDMgPSBtb2R1bHVzKHMgKiBzIC0gMm4gKiBweCwgcClcbiAgY29uc3QgeTMgPSBtb2R1bHVzKHMgKiAocHggLSB4MykgLSBweSwgcClcbiAgcmV0dXJuIFt4MywgeTNdXG59XG5cbi8qKlxuICogQWRkIHR3byBkaXN0aW5jdCBwb2ludHMgaW4gYWZmaW5lIGNvb3JkaW5hdGVzLlxuICpcbiAqIEdpdmVuIFDigoEgPSAoeOKCgSwgeeKCgSkgYW5kIFDigoIgPSAoeOKCgiwgeeKCgikgd2l0aCBQ4oKBIOKJoCBQ4oKCLCB0aGUgY2hvcmQtbGluZVxuICogZm9ybXVsYSBpczpcbiAqXG4gKiAgICAgzrsgID0gKHnigoIgLSB54oKBKSDCtyAoeOKCgiAtIHjigoEp4oG7wrkgIChtb2QgcClcbiAqICAgICB44oKDID0gzrvCsiAtIHjigoEgLSB44oKCICAgICAgICAgICAgICAobW9kIHApXG4gKiAgICAgeeKCgyA9IM67KHjigoEgLSB44oKDKSAtIHnigoEgICAgICAgICAgIChtb2QgcClcbiAqXG4gKiBJZiBQ4oKBID0gUOKCgiB0aGUgY2FsbCBpcyBmb3J3YXJkZWQgdG8ge0BsaW5rIGFmZmluZURvdWJsZX0uXG4gKlxuICogQHBhcmFtIHtCaWdJbnR8bnVsbH0gcDF4XG4gKiBAcGFyYW0ge0JpZ0ludHxudWxsfSBwMXlcbiAqIEBwYXJhbSB7QmlnSW50fG51bGx9IHAyeFxuICogQHBhcmFtIHtCaWdJbnR8bnVsbH0gcDJ5XG4gKiBAcGFyYW0ge0N1cnZlUGFyYW1zfSBjdXJ2ZVxuICogQHJldHVybnMge1tCaWdJbnR8bnVsbCwgQmlnSW50fG51bGxdfVxuICovXG5leHBvcnQgZnVuY3Rpb24gYWZmaW5lQWRkKHAxeCwgcDF5LCBwMngsIHAyeSwgY3VydmUpIHtcbiAgaWYgKHAxeCA9PT0gbnVsbCB8fCBwMXkgPT09IG51bGwpIHJldHVybiBbcDJ4LCBwMnldXG4gIGlmIChwMnggPT09IG51bGwgfHwgcDJ5ID09PSBudWxsKSByZXR1cm4gW3AxeCwgcDF5XVxuICBpZiAocDF4ID09PSBwMnggJiYgcDF5ID09PSBwMnkpIHJldHVybiBhZmZpbmVEb3VibGUocDF4LCBwMXksIGN1cnZlKVxuICBjb25zdCBwID0gY3VydmUucFxuICBjb25zdCBudW0gPSBtb2R1bHVzKHAyeSAtIHAxeSwgcClcbiAgY29uc3QgZGVuID0gbW9kdWx1cyhwMnggLSBwMXgsIHApXG4gIGlmIChkZW4gPT09IDBuKSByZXR1cm4gW251bGwsIG51bGxdXG4gIGNvbnN0IGludiA9IG1vZEludmVyc2UoZGVuLCBwKVxuICBjb25zdCBzID0gKG51bSAqIGludikgJSBwXG4gIGNvbnN0IHgzID0gbW9kdWx1cyhzICogcyAtIHAxeCAtIHAyeCwgcClcbiAgY29uc3QgeTMgPSBtb2R1bHVzKHMgKiAocDF4IC0geDMpIC0gcDF5LCBwKVxuICByZXR1cm4gW3gzLCB5M11cbn1cblxuLyoqXG4gKiBTY2FsYXIgbXVsdGlwbGljYXRpb24gaW4gYWZmaW5lIGNvb3JkaW5hdGVzIChkb3VibGUtYW5kLWFkZCkuXG4gKlxuICogQ29tcHV0ZXMga8K3UCBieSBzY2FubmluZyB0aGUgYml0cyBvZiBrIGZyb20gTFNCIHRvIE1TQixcbiAqIGFjY3VtdWxhdGluZyB0aGUgcmVzdWx0IGFuZCBkb3VibGluZyB0aGUgYmFzZSBhdCBlYWNoIHN0ZXAuXG4gKiBSdW5zIGluIE8obG9nIGspIGRvdWJsaW5ncyBhbmQgYXQgbW9zdCBPKGxvZyBrKSBhZGRpdGlvbnMuXG4gKlxuICogV2FybmluZzogdGhlIGRvdWJsZS1hbmQtYWRkIGFsZ29yaXRobSBpcyBOT1QgY29uc3RhbnQtdGltZTogdGhlIG51bWJlclxuICogb2YgYWRkaXRpb25zIGRlcGVuZHMgb24gdGhlIEhhbW1pbmcgd2VpZ2h0IG9mIGsuICBGb3JcbiAqIGNvbnN0YW50LXRpbWUgcmVxdWlyZW1lbnRzIHNlZSBSRkMgNjA5MCwgU2VjdGlvbiA0LlxuICpcbiAqIEBwYXJhbSB7QmlnSW50fSBrICAgLSBTY2FsYXIgbXVsdGlwbGllci5cbiAqIEBwYXJhbSB7QmlnSW50fG51bGx9IHB4IC0geC1jb29yZGluYXRlIG9mIHRoZSBiYXNlIHBvaW50LlxuICogQHBhcmFtIHtCaWdJbnR8bnVsbH0gcHkgLSB5LWNvb3JkaW5hdGUgb2YgdGhlIGJhc2UgcG9pbnQuXG4gKiBAcGFyYW0ge0N1cnZlUGFyYW1zfSBjdXJ2ZVxuICogQHJldHVybnMge1tCaWdJbnR8bnVsbCwgQmlnSW50fG51bGxdfVxuICovXG5leHBvcnQgZnVuY3Rpb24gYWZmaW5lTXVsKGssIHB4LCBweSwgY3VydmUpIHtcbiAgaWYgKHB4ID09PSBudWxsIHx8IHB5ID09PSBudWxsIHx8IGsgPT09IDBuKSByZXR1cm4gW251bGwsIG51bGxdXG4gIGxldCByeCA9IG51bGwsXG4gICAgcnkgPSBudWxsXG4gIHdoaWxlIChrID4gMG4pIHtcbiAgICBpZiAoayAmIDFuKSB7XG4gICAgICA7W3J4LCByeV0gPSBhZmZpbmVBZGQocngsIHJ5LCBweCwgcHksIGN1cnZlKVxuICAgIH1cbiAgICA7W3B4LCBweV0gPSBhZmZpbmVEb3VibGUocHgsIHB5LCBjdXJ2ZSlcbiAgICBrID4+PSAxblxuICB9XG4gIHJldHVybiBbcngs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