Curves and points
Define the curve
import { defineCurve } from "@agntn/curves";
defineCurve({ a: -3n, b: 20n, p: 17n }); // { a: 14n, b: 3n, p: 17n }
a and b take any integer and come back reduced mod p. So a = -3 works and turns into 14. p has to be a prime above 3, checked with Baillie-PSW. And the curve can't be singular, so 4a³ + 27b² mod p can't be 0.
defineCurve({ a: 0n, b: 0n, p: 17n }) // The curve is singular: 4a^3 + 27b^2 is 0 mod p
defineCurve({ a: 1n, b: 1n, p: 21n }) // p must be a prime above 3
The result is frozen and remembered. Every other function takes it without checking it again. Plain { a, b, p } works too, it just gets checked on every call.
Arithmetic
import { addPoints, doublePoint, multiplyPoint, negatePoint } from "@agntn/curves";
const curve = defineCurve({ a: 2n, b: 2n, p: 17n });
const G = { x: 5n, y: 1n };
doublePoint(curve, G); // { x: 6n, y: 3n }
addPoints(curve, G, { x: 6n, y: 3n }); // { x: 10n, y: 6n }
negatePoint(curve, G); // { x: 5n, y: 16n }
multiplyPoint(curve, G, 19n); // null
multiplyPoint(curve, G, -2n); // { x: 6n, y: 14n }
null is the point at infinity, and it goes in too. A negative scalar multiplies the negation. Zero gives infinity.
Checking a point
isOnCurve answers true or false. Every other function refuses a point off the curve before it touches it:
isOnCurve(curve, { x: 5n, y: 2n }) // false
doublePoint(curve, { x: 5n, y: 2n }) // RangeError: The point is not on the curve; coordinates run from 0 to p minus 1
Why so strict? An invalid curve attack starts exactly there. Feed a point from another curve and you get answers on that curve, quietly. Here you get an error.
Over MCP
curves_compute takes the same thing as strings. Points are { "x": "5", "y": "1" }, integers decimal or 0x hex:
{ "operation": "multiply", "a": "2", "b": "2", "p": "17", "point": { "x": "5", "y": "1" }, "scalar": "2" }
{"operation":"multiply","point":{"x":"6","y":"3"}}