UNPKG

@noble/curves

Version:

Audited & minimal JS implementation of elliptic curve cryptography

320 lines 13.4 kB
/** * Twisted Edwards curve. The formula is: ax² + y² = 1 + dx²y². * For design rationale of types / exports, see weierstrass module documentation. * Untwisted Edwards curves exist, but they aren't used in real-world protocols. * @module */ /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ import { type FHash, type TArg, type TRet } from '../utils.ts'; import { type AffinePoint, type CurveLengths, type CurvePoint, type CurvePointCons } from './curve.ts'; import { type IField } from './modular.ts'; /** Extended Edwards point with X/Y/Z/T coordinates. */ export interface EdwardsPoint extends CurvePoint<bigint, EdwardsPoint> { /** extended X coordinate. Different from affine x. */ readonly X: bigint; /** extended Y coordinate. Different from affine y. */ readonly Y: bigint; /** extended Z coordinate */ readonly Z: bigint; /** extended T coordinate */ readonly T: bigint; } /** Constructor and decoding helpers for extended Edwards points. */ export interface EdwardsPointCons extends CurvePointCons<EdwardsPoint> { /** Create a point from extended X/Y/Z/T coordinates without validation. */ new (X: bigint, Y: bigint, Z: bigint, T: bigint): EdwardsPoint; /** * Return the curve parameters used by this point constructor. * @returns Curve parameters. */ CURVE(): EdwardsOpts; /** * Decode a point from bytes, optionally using ZIP-215 rules. * @param bytes - Encoded point bytes. * @param zip215 - Whether to accept ZIP-215 encodings. * @returns Decoded Edwards point. */ fromBytes(bytes: Uint8Array, zip215?: boolean): EdwardsPoint; /** * Decode a point from hex, optionally using ZIP-215 rules. * @param hex - Encoded point hex. * @param zip215 - Whether to accept ZIP-215 encodings. * @returns Decoded Edwards point. */ fromHex(hex: string, zip215?: boolean): EdwardsPoint; } /** * Twisted Edwards curve options. * * * a: formula param * * d: formula param * * p: prime characteristic (order) of finite field, in which arithmetics is done * * n: order of prime subgroup a.k.a total amount of valid curve points * * h: cofactor. h*n is group order; n is subgroup order * * Gx: x coordinate of generator point a.k.a. base point * * Gy: y coordinate of generator point */ export type EdwardsOpts = Readonly<{ /** Base-field modulus. */ p: bigint; /** Prime subgroup order. */ n: bigint; /** Curve cofactor. */ h: bigint; /** Edwards curve parameter `a`. */ a: bigint; /** Edwards curve parameter `d`. */ d: bigint; /** Generator x coordinate. */ Gx: bigint; /** Generator y coordinate. */ Gy: bigint; }>; /** * Extra curve options for Twisted Edwards. * * * Fp: redefined Field over curve.p * * Fn: redefined Field over curve.n * * uvRatio: helper function for decompression, calculating √(u/v) */ export type EdwardsExtraOpts = Partial<{ /** Optional base-field override. */ Fp: IField<bigint>; /** Optional scalar-field override. */ Fn: IField<bigint>; /** Whether field encodings are little-endian. */ FpFnLE: boolean; /** Square-root ratio helper used during point decompression. */ uvRatio: (u: bigint, v: bigint) => { isValid: boolean; value: bigint; }; }>; /** * EdDSA (Edwards Digital Signature algorithm) options. * * * hash: hash function used to hash secret keys and messages * * adjustScalarBytes: clears bits to get valid field element * * domain: Used for hashing * * mapToCurve: for hash-to-curve standard * * prehash: RFC 8032 pre-hashing of messages to sign() / verify() * * randomBytes: function generating random bytes, used for randomSecretKey */ export type EdDSAOpts = Partial<{ /** Clamp or otherwise normalize secret-scalar bytes before reducing mod `n`. */ adjustScalarBytes: (bytes: TArg<Uint8Array>) => TRet<Uint8Array>; /** Domain-separation helper for contexts and prehash mode. */ domain: (data: TArg<Uint8Array>, ctx: TArg<Uint8Array>, phflag: boolean) => TRet<Uint8Array>; /** Optional hash-to-curve mapper for protocols like Ristretto hash-to-group. */ mapToCurve: (scalar: bigint[]) => AffinePoint<bigint>; /** Optional prehash function used before signing or verifying messages. */ prehash: FHash; /** Default verification decoding policy. ZIP-215 is more permissive than RFC 8032 / NIST. */ zip215: boolean; /** RNG override used by helper constructors. */ randomBytes: (bytesLength?: number) => TRet<Uint8Array>; }>; /** * EdDSA (Edwards Digital Signature algorithm) helper namespace. * Allows creating and verifying signatures, and deriving public keys. */ export interface EdDSA { /** * Generate a secret/public key pair. * @param seed - Optional seed material. * @returns Secret/public key pair. */ keygen: (seed?: TArg<Uint8Array>) => { secretKey: TRet<Uint8Array>; publicKey: TRet<Uint8Array>; }; /** * Derive the public key from a secret key. * @param secretKey - Secret key bytes. * @returns Encoded public key. */ getPublicKey: (secretKey: TArg<Uint8Array>) => TRet<Uint8Array>; /** * Sign a message with an EdDSA secret key. * @param message - Message bytes. * @param secretKey - Secret key bytes. * @param options - Optional signature tweaks: * - `context` (optional): Domain-separation context for Ed25519ctx/Ed448. * @returns Encoded signature bytes. */ sign: (message: TArg<Uint8Array>, secretKey: TArg<Uint8Array>, options?: TArg<{ context?: Uint8Array; }>) => TRet<Uint8Array>; /** * Verify a signature against a message and public key. * @param sig - Encoded signature bytes. * @param message - Message bytes. * @param publicKey - Encoded public key. * @param options - Optional verification tweaks: * - `context` (optional): Domain-separation context for Ed25519ctx/Ed448. * - `zip215` (optional): Whether to accept ZIP-215 encodings. * @returns Whether the signature is valid. */ verify: (sig: TArg<Uint8Array>, message: TArg<Uint8Array>, publicKey: TArg<Uint8Array>, options?: TArg<{ context?: Uint8Array; zip215?: boolean; }>) => boolean; /** Point constructor used by this signature scheme. */ Point: EdwardsPointCons; /** Helper utilities for key validation and Montgomery conversion. */ utils: { /** * Generate a valid random secret key. * Optional seed bytes are only length-checked and returned unchanged. */ randomSecretKey: (seed?: TArg<Uint8Array>) => TRet<Uint8Array>; /** Check whether a secret key has the expected encoding. */ isValidSecretKey: (secretKey: TArg<Uint8Array>) => boolean; /** Check whether a public key decodes to a valid point. */ isValidPublicKey: (publicKey: TArg<Uint8Array>, zip215?: boolean) => boolean; /** * Converts ed public key to x public key. * * There is NO `fromMontgomery`: * - There are 2 valid ed25519 points for every x25519, with flipped coordinate * - Sometimes there are 0 valid ed25519 points, because x25519 *additionally* * accepts inputs on the quadratic twist, which can't be moved to ed25519 * * @example * Converts ed public key to x public key. * * ```js * const someonesPub_ed = ed25519.getPublicKey(ed25519.utils.randomSecretKey()); * const someonesPub = ed25519.utils.toMontgomery(someonesPub); * const aPriv = x25519.utils.randomSecretKey(); * const shared = x25519.getSharedSecret(aPriv, someonesPub) * ``` */ toMontgomery: (publicKey: TArg<Uint8Array>) => TRet<Uint8Array>; /** * Converts ed secret key to x secret key. * @example * Converts ed secret key to x secret key. * * ```js * const someonesPub = x25519.getPublicKey(x25519.utils.randomSecretKey()); * const aPriv_ed = ed25519.utils.randomSecretKey(); * const aPriv = ed25519.utils.toMontgomerySecret(aPriv_ed); * const shared = x25519.getSharedSecret(aPriv, someonesPub) * ``` */ toMontgomerySecret: (secretKey: TArg<Uint8Array>) => TRet<Uint8Array>; /** Return the expanded private key components used by RFC8032 signing. */ getExtendedPublicKey: (key: TArg<Uint8Array>) => { head: TRet<Uint8Array>; prefix: TRet<Uint8Array>; scalar: bigint; point: EdwardsPoint; pointBytes: TRet<Uint8Array>; }; }; /** Byte lengths for keys and signatures exposed by this scheme. */ lengths: CurveLengths; } /** * @param params - Curve parameters. See {@link EdwardsOpts}. * @param extraOpts - Optional helpers and overrides. See {@link EdwardsExtraOpts}. * @returns Edwards point constructor. Generator validation here only checks * that `(Gx, Gy)` satisfies the affine Edwards equation. * RFC 8032 base-point constraints like `B != (0,1)` and `[L]B = 0` * are left to the caller's chosen parameters, since eager subgroup * validation here adds about 10-15ms to heavyweight imports like ed448. * The returned constructor also eagerly marks `Point.BASE` for W=8 * precompute caching. Some code paths still assume * `Fp.BYTES === Fn.BYTES`, so mismatched byte lengths are not fully audited here. * @throws If the curve parameters or Edwards overrides are invalid. {@link Error} * @example * ```ts * import { edwards } from '@noble/curves/abstract/edwards.js'; * import { jubjub } from '@noble/curves/misc.js'; * // Build a point constructor from explicit curve parameters, then use its base point. * const Point = edwards(jubjub.Point.CURVE()); * Point.BASE.toHex(); * ``` */ export declare function edwards(params: TArg<EdwardsOpts>, extraOpts?: TArg<EdwardsExtraOpts>): EdwardsPointCons; /** * Base class for prime-order points like Ristretto255 and Decaf448. * These points eliminate cofactor issues by representing equivalence classes * of Edwards curve points. Multiple Edwards representatives can describe the * same abstract wrapper element, so wrapper validity is not the same thing as * the hidden representative being torsion-free. * @param ep - Backing Edwards point. * @example * Base class for prime-order points like Ristretto255 and Decaf448. * * ```ts * import { ristretto255 } from '@noble/curves/ed25519.js'; * const point = ristretto255.Point.BASE.multiply(2n); * ``` */ export declare abstract class PrimeEdwardsPoint<T extends PrimeEdwardsPoint<T>> implements CurvePoint<bigint, T> { static BASE: PrimeEdwardsPoint<any>; static ZERO: PrimeEdwardsPoint<any>; static Fp: IField<bigint>; static Fn: IField<bigint>; protected readonly ep: EdwardsPoint; /** * Wrap one internal Edwards representative directly. * This is not a canonical encoding boundary: alternate Edwards * representatives may still describe the same abstract wrapper element. */ constructor(ep: EdwardsPoint); abstract toBytes(): Uint8Array; abstract equals(other: T): boolean; static fromBytes(_bytes: Uint8Array): any; static fromHex(_hex: string): any; get x(): bigint; get y(): bigint; clearCofactor(): T; assertValidity(): void; /** * Return affine coordinates of the current internal Edwards representative. * This is a convenience helper, not a canonical Ristretto/Decaf encoding. * Equal abstract elements may expose different `x` / `y`; use * `toBytes()` / `fromBytes()` for canonical roundtrips. */ toAffine(invertedZ?: bigint): AffinePoint<bigint>; toHex(): string; toString(): string; isTorsionFree(): boolean; isSmallOrder(): boolean; add(other: T): T; subtract(other: T): T; multiply(scalar: bigint): T; multiplyUnsafe(scalar: bigint): T; double(): T; negate(): T; precompute(windowSize?: number, isLazy?: boolean): T; abstract is0(): boolean; protected abstract assertSame(other: T): void; protected abstract init(ep: EdwardsPoint): T; } /** * Initializes EdDSA signatures over given Edwards curve. * @param Point - Edwards point constructor. * @param cHash - Hash function. * @param eddsaOpts - Optional signature helpers. See {@link EdDSAOpts}. * @returns EdDSA helper namespace. * @throws If the hash function, options, or derived point operations are invalid. {@link Error} * @example * Initializes EdDSA signatures over given Edwards curve. * * ```ts * import { eddsa } from '@noble/curves/abstract/edwards.js'; * import { jubjub } from '@noble/curves/misc.js'; * import { sha512 } from '@noble/hashes/sha2.js'; * const sigs = eddsa(jubjub.Point, sha512); * const { secretKey, publicKey } = sigs.keygen(); * const msg = new TextEncoder().encode('hello noble'); * const sig = sigs.sign(msg, secretKey); * const isValid = sigs.verify(sig, msg, publicKey); * ``` */ export declare function eddsa(Point: EdwardsPointCons, cHash: TArg<FHash>, eddsaOpts?: TArg<EdDSAOpts>): EdDSA; //# sourceMappingURL=edwards.d.ts.map