CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-noble--curves

Audited & minimal JS implementation of elliptic curve cryptography

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

abstract-primitives.mddocs/

Abstract Cryptographic Primitives

Low-level building blocks for implementing custom elliptic curves, including field arithmetic, point operations, signature schemes, and hash-to-curve functionality.

Capabilities

Weierstrass Curves

Abstract implementation for short Weierstrass curves (y² = x³ + ax + b) with ECDSA signatures.

import { weierstrass, ecdsa, ecdh, weierstrassPoints } from "@noble/curves/abstract/weierstrass";

/**
 * Creates a Weierstrass curve implementation from curve parameters
 * @param c - Curve configuration including field, curve parameters, and options
 * @returns Complete curve implementation with signing, verification, and point operations
 */
function weierstrass(c: CurveType): CurveFn;

/**
 * Creates ECDSA signature implementation for a curve
 * @param Point - Point constructor from curve implementation
 * @param Hash - Hash function (must have blockLen and outputLen properties)
 * @param opts - ECDSA options including lowS canonicalization
 * @returns ECDSA interface with sign, verify, and key operations
 */
function ecdsa(
  Point: WeierstrassPointCons<bigint>,
  Hash: CHash,
  opts?: ECDSAOpts
): ECDSA;

/**
 * Creates ECDH key exchange implementation
 * @param Point - Point constructor from curve implementation
 * @param opts - ECDH options
 * @returns ECDH interface with getSharedSecret
 */
function ecdh(Point: WeierstrassPointCons<bigint>, opts?: ECDHOpts): ECDH;

/**
 * Creates point operations for Weierstrass curves
 * @param c - Curve points configuration
 * @returns Point constructor and utilities
 */
function weierstrassPoints<T>(c: CurvePointsTypeWithLength<T>): CurvePointsRes<T>;

/**
 * Simplified SWU map-to-curve implementation
 * @param Fp - Base field
 * @param opts - SWU parameters (A, B, Z)
 * @returns Function that maps field element to curve point
 */
function mapToCurveSimpleSWU<T>(
  Fp: IField<T>,
  opts: { A: T; B: T; Z: T }
): (u: T) => AffinePoint<T>;

/**
 * Square root ratio for SWU mapping
 * @param Fp - Base field
 * @param Z - SWU parameter Z
 * @returns Function computing sqrt(u/v) or indication if not square
 */
function SWUFpSqrtRatio<T>(
  Fp: IField<T>,
  Z: T
): (u: T, v: T) => { isValid: boolean; value: T };

Weierstrass Types

interface CurveType {
  p: bigint; // Base field modulus
  n: bigint; // Curve order (number of points)
  a: bigint; // Curve parameter a
  b: bigint; // Curve parameter b
  Gx: bigint; // Generator point x coordinate
  Gy: bigint; // Generator point y coordinate
  h?: bigint; // Cofactor (default 1)
  Fp?: IField<bigint>; // Base field implementation
  lowS?: boolean; // Canonical signature requirement
  endo?: EndomorphismOpts; // GLV endomorphism for faster scalar multiplication
}

interface WeierstrassPoint<T> {
  x: T;
  y: T;
  z: T; // Projective coordinate
  
  add(other: WeierstrassPoint<T>): WeierstrassPoint<T>;
  subtract(other: WeierstrassPoint<T>): WeierstrassPoint<T>;
  multiply(scalar: bigint): WeierstrassPoint<T>;
  multiplyUnsafe(scalar: bigint): WeierstrassPoint<T>;
  negate(): WeierstrassPoint<T>;
  double(): WeierstrassPoint<T>;
  
  toAffine(): AffinePoint<T>;
  toRawBytes(isCompressed?: boolean): Uint8Array;
  toHex(isCompressed?: boolean): string;
  
  equals(other: WeierstrassPoint<T>): boolean;
  assertValidity(): void;
}

interface ECDSA {
  sign(message: Hex, privateKey: PrivKey, opts?: ECDSASignOpts): ECDSASignature;
  verify(signature: ECDSASignature, message: Hex, publicKey: Hex, opts?: ECDSAVerifyOpts): boolean;
  getPublicKey(privateKey: PrivKey, isCompressed?: boolean): Uint8Array;
}

interface ECDH {
  getSharedSecret(privateKeyA: PrivKey, publicKeyB: Hex, isCompressed?: boolean): Uint8Array;
}

interface ECDSASignature {
  r: bigint;
  s: bigint;
  recovery?: number;
  
  toCompactRawBytes(): Uint8Array;
  toDERRawBytes(): Uint8Array;
  toCompactHex(): string;
  toDERHex(): string;
  
  normalizeS(): ECDSASignature;
  recoverPublicKey(message: Hex): WeierstrassPoint<bigint>;
}

Edwards Curves

Abstract implementation for twisted Edwards curves (ax² + y² = 1 + dx²y²) with EdDSA signatures.

import { twistedEdwards, edwards, eddsa } from "@noble/curves/abstract/edwards";

/**
 * Creates a twisted Edwards curve implementation from curve parameters
 * @param c - Curve configuration including field, curve parameters, and hash function
 * @returns Complete curve implementation with signing, verification, and point operations
 */
function twistedEdwards(c: CurveTypeWithLength): CurveFn;

/**
 * Creates Edwards curve point operations
 * @param params - Edwards curve parameters (a, d, etc.)
 * @param extraOpts - Additional options like hash function and precomputation
 * @returns Edwards point constructor
 */
function edwards(params: EdwardsOpts, extraOpts?: EdwardsExtraOpts): EdwardsPointCons;

/**
 * Creates EdDSA signature implementation for Edwards curves
 * @param Point - Edwards point constructor
 * @param cHash - Hash function for EdDSA
 * @param eddsaOpts - EdDSA-specific options
 * @returns EdDSA interface with sign, verify, and key operations
 */
function eddsa(
  Point: EdwardsPointCons,
  cHash: FHash,
  eddsaOpts?: EdDSAOpts
): EdDSA;

Edwards Types

interface CurveTypeWithLength {
  p: bigint; // Base field modulus
  n: bigint; // Curve order
  a: bigint; // Curve parameter a
  d: bigint; // Curve parameter d
  Gx: bigint; // Generator point x coordinate
  Gy: bigint; // Generator point y coordinate
  h?: bigint; // Cofactor
  hash: CHash; // Hash function for signatures
  nByteLength?: number; // Byte length of scalar field
  nBitLength?: number; // Bit length of scalar field
}

interface EdwardsPoint {
  x: bigint;
  y: bigint;
  z: bigint;
  t: bigint; // Extended coordinate t = xy/z
  
  add(other: EdwardsPoint): EdwardsPoint;
  subtract(other: EdwardsPoint): EdwardsPoint; 
  multiply(scalar: bigint): EdwardsPoint;
  multiplyUnsafe(scalar: bigint): EdwardsPoint;
  negate(): EdwardsPoint;
  double(): EdwardsPoint;
  
  toAffine(): AffinePoint<bigint>;
  toRawBytes(): Uint8Array;
  toHex(): string;
  
  equals(other: EdwardsPoint): boolean;
  assertValidity(): void;
}

interface EdDSA {
  sign(message: Hex, privateKey: PrivKey, context?: Hex): Uint8Array;
  verify(signature: Hex, message: Hex, publicKey: Hex, context?: Hex): boolean;
  getPublicKey(privateKey: PrivKey): Uint8Array;
}

interface EdwardsOpts {
  p: bigint; // Base field modulus
  a: bigint; // Curve parameter a
  d: bigint; // Curve parameter d  
  n: bigint; // Curve order
  Gx: bigint; // Generator x coordinate
  Gy: bigint; // Generator y coordinate
  h?: bigint; // Cofactor
  adjustScalarBytes?: (bytes: Uint8Array) => Uint8Array; // Scalar clamping function
}

Modular Arithmetic

Field arithmetic operations and finite field implementations.

import { 
  Field, mod, pow, pow2, invert, tonelliShanks, FpSqrt,
  FpPow, FpInvertBatch, FpDiv, hashToPrivateScalar, mapHashToField
} from "@noble/curves/abstract/modular";

/**
 * Creates a finite field implementation
 * @param ORDER - Field modulus (prime number)
 * @param opts - Field options including sqrt implementation
 * @returns Field implementation with arithmetic operations
 */
function Field(
  ORDER: bigint,
  opts?: {
    sqrt?: (n: bigint) => bigint;
    isLE?: boolean;
  }
): IField<bigint>;

/**
 * Modular reduction: a mod b
 * @param a - Number to reduce
 * @param b - Modulus
 * @returns a mod b, always positive
 */
function mod(a: bigint, b: bigint): bigint;

/**
 * Modular exponentiation: num^power mod modulo
 * @param num - Base
 * @param power - Exponent  
 * @param modulo - Modulus
 * @returns num^power mod modulo
 */
function pow(num: bigint, power: bigint, modulo: bigint): bigint;

/**
 * Optimized modular exponentiation with precomputed powers
 * @param x - Base
 * @param power - Exponent
 * @param modulo - Modulus
 * @returns x^power mod modulo
 */
function pow2(x: bigint, power: bigint, modulo: bigint): bigint;

/**
 * Modular multiplicative inverse using extended Euclidean algorithm
 * @param number - Number to invert
 * @param modulo - Modulus (must be prime)
 * @returns number^(-1) mod modulo
 */
function invert(number: bigint, modulo: bigint): bigint;

/**
 * Creates Tonelli-Shanks square root implementation
 * @param P - Prime modulus
 * @returns Function to compute square roots in field
 */
function tonelliShanks(P: bigint): <T>(Fp: IField<T>, n: T) => T;

/**
 * Creates square root implementation for finite fields
 * @param P - Prime modulus
 * @returns Square root function
 */
function FpSqrt(P: bigint): <T>(Fp: IField<T>, n: T) => T;

/**
 * Batch modular inversion using Montgomery's trick
 * @param Fp - Field implementation
 * @param nums - Array of field elements to invert
 * @param passZero - Whether to pass zero elements unchanged
 * @returns Array of inverted elements
 */
function FpInvertBatch<T>(Fp: IField<T>, nums: T[], passZero?: boolean): T[];

/**
 * Hash arbitrary data to private scalar
 * @param hash - Hash bytes
 * @param groupOrder - Curve order
 * @param isLE - Whether hash is little-endian
 * @returns Private scalar in range [1, groupOrder-1]
 */
function hashToPrivateScalar(
  hash: Uint8Array,
  groupOrder: bigint,
  isLE?: boolean
): bigint;

/**
 * Map hash output to field element
 * @param key - Hash bytes
 * @param fieldOrder - Field modulus
 * @param isLE - Whether to use little-endian interpretation
 * @returns Field element
 */
function mapHashToField(key: Uint8Array, fieldOrder: bigint, isLE?: boolean): Uint8Array;

Modular Types

interface IField<T> {
  ORDER: bigint; // Field modulus
  ZERO: T; // Additive identity
  ONE: T; // Multiplicative identity
  BYTES: number; // Byte length of field elements
  BITS: number; // Bit length of field elements
  MASK: bigint; // Bit mask for field elements
  
  // Arithmetic operations
  create(num: T): T;
  add(a: T, b: T): T;
  sub(a: T, b: T): T; 
  mul(a: T, b: T): T;
  div(a: T, b: T): T;
  pow(a: T, b: bigint): T;
  inv(a: T): T;
  neg(a: T): T;
  sqr(a: T): T;
  sqrt(a: T): T;
  
  // Comparison and validation
  eql(a: T, b: T): boolean;
  isZero(a: T): boolean;
  isOne(a: T): boolean;
  isValid(a: T): boolean;
  
  // Serialization
  toBytes(a: T): Uint8Array;
  fromBytes(bytes: Uint8Array): T;
}

interface NLength {
  nByteLength: number;
  nBitLength: number;
}

Hash-to-Curve

Standardized methods for hashing arbitrary data to elliptic curve points.

import { 
  createHasher, expand_message_xmd, expand_message_xof, 
  hash_to_field, isogenyMap 
} from "@noble/curves/abstract/hash-to-curve";

/**
 * Creates hash-to-curve hasher following RFC 9380
 * @param Point - Curve point constructor
 * @param mapToCurve - Map-to-curve function
 * @param opts - Hash-to-curve options including DST and hash function
 * @returns Hash-to-curve hasher with hashToCurve and encodeToCurve methods
 */
function createHasher<T>(
  Point: H2CPointConstructor<T>,
  mapToCurve: MapToCurve<T>,
  opts: {
    DST: string; // Domain separation tag
    encodeDST?: string; // Encode domain separation tag
    p: bigint; // Field modulus
    m: number; // Field extension degree
    k: number; // Security parameter
    expand?: string; // Expand function ('xmd' or 'xof')
    hash: CHash; // Hash function
  }
): H2CHasher<T>;

/**
 * Expand message using XMD (eXpand Message Domain)
 * @param msg - Message to expand
 * @param DST - Domain separation tag
 * @param lenInBytes - Target length in bytes
 * @param H - Hash function
 * @returns Expanded message
 */
function expand_message_xmd(
  msg: Uint8Array,
  DST: Uint8Array,
  lenInBytes: number,
  H: CHash
): Uint8Array;

/**
 * Expand message using XOF (eXtendable Output Function)
 * @param msg - Message to expand
 * @param DST - Domain separation tag
 * @param lenInBytes - Target length in bytes
 * @param k - Security parameter
 * @param H - XOF function
 * @returns Expanded message
 */
function expand_message_xof(
  msg: Uint8Array,
  DST: Uint8Array,
  lenInBytes: number,
  k: number,
  H: any
): Uint8Array;

/**
 * Hash message to field elements
 * @param msg - Message bytes
 * @param count - Number of field elements to produce
 * @param options - Hash-to-field options
 * @returns Array of field element arrays
 */
function hash_to_field(
  msg: Uint8Array,
  count: number,
  options: {
    DST: string;
    p: bigint;
    m: number;
    k: number;
    expand?: string;
    hash: CHash;
  }
): bigint[][];

/**
 * Creates isogeny map for hash-to-curve
 * @param field - Base field
 * @param map - Isogeny rational map coefficients [xNum, xDen, yNum, yDen]
 * @returns Isogeny mapping function
 */
function isogenyMap<T, F extends IField<T>>(
  field: F,
  map: [T[], T[], T[], T[]]
): (x: T, y: T) => { x: T; y: T };

Hash-to-Curve Types

interface H2CHasher<T> {
  hashToCurve(msg: Uint8Array, options?: { DST?: string }): H2CPoint<T>;
  encodeToCurve(msg: Uint8Array, options?: { DST?: string }): H2CPoint<T>;
}

interface H2CPoint<T> {
  toAffine(): AffinePoint<T>;
  add(other: H2CPoint<T>): H2CPoint<T>;
  multiply(scalar: bigint): H2CPoint<T>;
  equals(other: H2CPoint<T>): boolean;
}

type MapToCurve<T> = (scalar: bigint[]) => AffinePoint<T>;
type H2CMethod<T> = (msg: Uint8Array, options?: { DST?: string }) => H2CPoint<T>;

interface AffinePoint<T> {
  x: T;
  y: T;
}

Additional Abstract Modules

BLS Signatures

import { bls } from "@noble/curves/abstract/bls";

/**
 * Creates BLS signature implementation for pairing-friendly curves
 * @param CURVE - BLS curve configuration with G1, G2, GT, and pairing
 * @returns BLS signature interface with aggregation support
 */
function bls<T>(CURVE: BLSOpts<T>): BLSCurveFn;

interface BLSCurveFn {
  sign(message: Hex, privateKey: PrivKey): Uint8Array;
  verify(signature: Hex, message: Hex, publicKey: Hex): boolean;
  aggregatePublicKeys(publicKeys: Hex[]): Uint8Array;
  aggregateSignatures(signatures: Hex[]): Uint8Array;
  verifyBatch(signature: Hex, messages: Hex[], publicKeys: Hex[]): boolean;
  getPublicKey(privateKey: PrivKey): Uint8Array;
}

Montgomery Curves

import { montgomery } from "@noble/curves/abstract/montgomery";

/**
 * Creates Montgomery curve implementation for key exchange
 * @param opts - Montgomery curve parameters
 * @returns Montgomery curve with key exchange operations
 */
function montgomery(opts: MontgomeryOpts): MontgomeryCurveFn;

interface MontgomeryCurveFn {
  getPublicKey(privateKey: PrivKey): Uint8Array;
  getSharedSecret(privateKey: PrivKey, publicKey: Hex): Uint8Array;
  utils: {
    randomPrivateKey(): Uint8Array;
  };
}

Tower Fields

Extension field operations for pairing-friendly curves, enabling efficient computation over Fp2, Fp6, and Fp12.

import { tower12 } from "@noble/curves/abstract/tower";

/**
 * Creates tower field operations for BLS-style pairing curves
 * @param opts - Tower field configuration including base field and extension parameters
 * @returns Field operations for Fp2, Fp6, and Fp12 extensions
 */
function tower12(opts: Tower12Opts): {
  Fp2: Fp2Bls;
  Fp6: Fp6Bls; 
  Fp12: Fp12Bls;
  psiFrobenius(x: Fp2): Fp2;
};

type Fp2 = { c0: bigint; c1: bigint };
type Fp6 = { c0: Fp2; c1: Fp2; c2: Fp2 };
type Fp12 = { c0: Fp6; c1: Fp6 };

Poseidon Hash

Algebraic hash function designed for zero-knowledge proof systems with efficient circuit representation.

import { poseidon, poseidonSponge } from "@noble/curves/abstract/poseidon";

/**
 * Creates Poseidon hash function
 * @param opts - Poseidon configuration including field size, rounds, and constants
 * @returns Poseidon hash function instance
 */
function poseidon(opts: PoseidonOpts): PoseidonFn;

/**
 * Creates Poseidon sponge construction for variable-length input
 * @param opts - Sponge configuration parameters
 * @returns Factory function for Poseidon sponge instances
 */
function poseidonSponge(opts: PoseidonSpongeOpts): () => PoseidonSponge;

interface PoseidonFn {
  (inputs: bigint[]): bigint;
  m: number;
  roundConstants: bigint[][];
}

Fast Fourier Transform

Polynomial operations and number-theoretic transforms for efficient computation in cryptographic protocols, including FFT/NTT, polynomial arithmetic, and roots of unity generation.

import { FFT, poly, rootsOfUnity } from "@noble/curves/abstract/fft";

/**
 * Creates FFT/NTT operations for polynomial arithmetic
 * @param roots - Roots of unity for the transformation
 * @param opts - FFT configuration options including field operations
 * @returns FFT transformation methods for direct and inverse transforms
 */
function FFT<T>(roots: RootsOfUnity, opts: FFTOpts<T, bigint>): FFTMethods<T>;

/**
 * Creates comprehensive polynomial operations over a field
 * @param field - Field operations for polynomial coefficients
 * @param roots - Roots of unity for FFT-based operations
 * @param create - Function to create polynomial instances
 * @param fft - Optional pre-computed FFT methods
 * @param length - Default polynomial length
 * @returns Complete polynomial arithmetic suite
 */
function poly<T, P extends Polynomial<T>>(
  field: IField<T>,
  roots: RootsOfUnity,
  create?: CreatePolyFn<P, T>,
  fft?: FFTMethods<T>,
  length?: number
): PolyFn<P, T>;

/**
 * Generates roots of unity for FFT operations
 * @param field - Field operations (must have primitive root)
 * @param generator - Optional primitive root generator
 * @returns Cached roots of unity and bit-reversal permutation utilities
 */
function rootsOfUnity(field: IField<bigint>, generator?: bigint): RootsOfUnity;

// Core FFT interfaces
interface FFTMethods<T> {
  /** Forward FFT: time domain to frequency domain */
  direct<P extends Polynomial<T>>(values: P, brpInput?: boolean, brpOutput?: boolean): P;
  /** Inverse FFT: frequency domain to time domain */
  inverse<P extends Polynomial<T>>(values: P, brpInput?: boolean, brpOutput?: boolean): P;
}

interface RootsOfUnity {
  /** Get roots of unity for given bit size */
  roots(bits: number): bigint[];
  /** Get bit-reversal permutation indices */
  brp(bits: number): bigint[];
  /** Get inverse roots of unity */
  inverse(bits: number): bigint[];
  /** Get primitive root for given bit size */
  omega(bits: number): bigint;
  /** Clear cached values */
  clear(): void;
}

// Polynomial operations
interface PolyFn<P extends Polynomial<T>, T> {
  /** Create zero polynomial */
  ZERO: P;
  /** Create polynomial from coefficients */
  fromCoeffs(coeffs: T[]): P;
  /** Create polynomial from evaluations */
  fromEvals(evals: T[]): P;
  
  /** Add two polynomials */
  add(a: P, b: P): P;
  /** Subtract two polynomials */
  sub(a: P, b: P): P;
  /** Multiply two polynomials (FFT-accelerated) */
  mul(a: P, b: P): P;
  /** Multiply polynomial by scalar */
  scale(a: P, scalar: T): P;
  /** Compute polynomial division with quotient and remainder */
  divmod(a: P, b: P): { quotient: P; remainder: P };
  
  /** Evaluate polynomial at point */
  eval(poly: P, point: T): T;
  /** Multi-point evaluation */
  evalMany(poly: P, points: T[]): T[];
  /** Polynomial interpolation from points */
  interpolate(points: Array<{ x: T; y: T }>): P;
  
  /** Convert between coefficient and evaluation representations */
  toCoeffs(poly: P): T[];
  toEvals(poly: P): T[];
  
  /** FFT-based operations */
  fft: FFTMethods<T>;
}

// Configuration types
interface FFTOpts<T, F> {
  /** Field for polynomial coefficients */
  field: IField<F>;
  /** Function to create polynomial from array */
  create: CreatePolyFn<Polynomial<T>, T>;
  /** Optional custom multiplication for performance */
  mul?: (a: T, b: F) => T;
  /** Optional custom addition for performance */
  add?: (a: T, b: T) => T;
  /** Optional custom zero element */
  zero?: () => T;
}

interface Polynomial<T> extends MutableArrayLike<T> {
  [index: number]: T;
  length: number;
  slice(start?: number, end?: number): this;
}

interface MutableArrayLike<T> {
  [index: number]: T;
  length: number;
}

type CreatePolyFn<P, T> = (values: T[]) => P;

FFT Usage Examples:

import { FFT, poly, rootsOfUnity } from "@noble/curves/abstract/fft";
import { Field } from "@noble/curves/abstract/modular";

// Create field for polynomial coefficients  
const Fp = Field(2n ** 255n - 19n); // Ed25519 field

// Generate roots of unity for FFT
const roots = rootsOfUnity(Fp);

// Create FFT operations
const fft = FFT(roots, {
  field: Fp,
  create: (values) => new Uint8Array(values.map(v => Number(v))),
});

// Create polynomial operations with FFT acceleration
const polynomial = poly(Fp, roots, (coeffs) => new BigUint64Array(coeffs));

// Polynomial arithmetic
const p1 = polynomial.fromCoeffs([1n, 2n, 3n]); // 3x² + 2x + 1
const p2 = polynomial.fromCoeffs([4n, 5n]);     // 5x + 4

const sum = polynomial.add(p1, p2);       // 3x² + 7x + 5
const product = polynomial.mul(p1, p2);   // FFT-accelerated multiplication

// Evaluation and interpolation
const result = polynomial.eval(p1, 10n);  // Evaluate at x = 10
const points = [
  { x: 1n, y: 6n },
  { x: 2n, y: 17n },
  { x: 3n, y: 34n }
];
const interpolated = polynomial.interpolate(points);

Use Cases:

  • Zero-Knowledge Proofs: Polynomial commitments and proof systems (PLONK, STARK)
  • Error Correction: Reed-Solomon codes and polynomial-based error correction
  • Cryptographic Protocols: Polynomial secret sharing, threshold cryptography
  • Signal Processing: Convolution, correlation, and digital signal processing
  • Homomorphic Encryption: Polynomial arithmetic for encrypted computation
  • Multivariate Cryptography: Polynomial system solving and Gröbner bases

Oblivious Pseudorandom Functions (OPRF)

RFC 9497 implementation of Oblivious Pseudorandom Functions supporting OPRF, VOPRF, and POPRF modes for privacy-preserving protocols.

import { createORPF } from "@noble/curves/abstract/oprf";

/**
 * Creates OPRF implementation for a specific curve and hash function
 * @param opts - OPRF configuration including curve, hash, and domain separation
 * @returns Complete OPRF suite with three protocol variants
 */
function createORPF<P extends CurvePoint<any, P>>(opts: OPRFOpts<P>): OPRF;

/**
 * OPRF suite providing three protocol variants
 */
interface OPRF {
  readonly name: string; // Ciphersuite identifier
  
  // Base OPRF mode (mode 0x00) - simple, non-verifiable
  readonly oprf: {
    generateKeyPair(): OPRFKeys;
    deriveKeyPair(seed: Bytes, keyInfo: Bytes): OPRFKeys;
    blind(input: Bytes, rng?: RNG): OPRFBlind;
    blindEvaluate(secretKey: ScalarBytes, blinded: PointBytes): PointBytes;
    finalize(input: Bytes, blind: ScalarBytes, evaluated: PointBytes): Bytes;
  };
  
  // Verifiable OPRF mode (mode 0x01) - includes proofs
  readonly voprf: {
    generateKeyPair(): OPRFKeys;
    deriveKeyPair(seed: Bytes, keyInfo: Bytes): OPRFKeys;
    blind(input: Bytes, rng?: RNG): OPRFBlind;
    blindEvaluate(secretKey: ScalarBytes, publicKey: PointBytes, blinded: PointBytes, rng?: RNG): OPRFBlindEval;
    blindEvaluateBatch(secretKey: ScalarBytes, publicKey: PointBytes, blinded: PointBytes[], rng?: RNG): OPRFBlindEvalBatch;
    finalize(input: Bytes, blind: ScalarBytes, evaluated: PointBytes, blinded: PointBytes, publicKey: PointBytes, proof: Bytes): Bytes;
    finalizeBatch(items: OPRFFinalizeItem[], publicKey: PointBytes, proof: Bytes): Bytes[];
  };
  
  // Partially Oblivious PRF mode (mode 0x02) - includes domain separation
  readonly poprf: (info: Bytes) => {
    generateKeyPair(): OPRFKeys;
    deriveKeyPair(seed: Bytes, keyInfo: Bytes): OPRFKeys;
    blind(input: Bytes, publicKey: PointBytes, rng?: RNG): OPRFBlind & { tweakedKey: PointBytes };
    blindEvaluate(secretKey: ScalarBytes, blinded: PointBytes, rng?: RNG): OPRFBlindEval;
    blindEvaluateBatch(secretKey: ScalarBytes, blinded: PointBytes[], rng: RNG): OPRFBlindEvalBatch;
    finalize(input: Bytes, blind: ScalarBytes, evaluated: PointBytes, blinded: PointBytes, proof: Bytes, tweakedKey: PointBytes): Bytes;
    finalizeBatch(items: OPRFFinalizeItem[], proof: Bytes, tweakedKey: PointBytes): Bytes[];
  };
}

// OPRF configuration
interface OPRFOpts<P extends CurvePoint<any, P>> {
  name: string; // Ciphersuite name
  Point: CurvePointCons<P>; // Curve point constructor
  hash: (msg: Bytes) => Bytes; // Hash function
  hashToScalar: (msg: Uint8Array, options: htfBasicOpts) => bigint; // Hash-to-scalar
  hashToGroup: ((msg: Uint8Array, options: htfBasicOpts) => P) | H2CMethod<P>; // Hash-to-curve
}

// OPRF data types
interface OPRFKeys {
  secretKey: ScalarBytes;
  publicKey: PointBytes;
}

interface OPRFBlind {
  blind: Uint8Array; // Secret blinding scalar
  blinded: Uint8Array; // Blinded group element to send to server
}

interface OPRFBlindEval {
  evaluated: PointBytes; // Server's evaluation result
  proof: Bytes; // DLEQ proof of correct evaluation
}

interface OPRFBlindEvalBatch {
  evaluated: PointBytes[]; // Batch evaluation results
  proof: Bytes; // Single proof for entire batch
}

interface OPRFFinalizeItem {
  input: Bytes;
  blind: ScalarBytes;
  evaluated: PointBytes;
  blinded: PointBytes;
}

type PointBytes = Uint8Array;
type ScalarBytes = Uint8Array;
type Bytes = Uint8Array;
type RNG = typeof randomBytes;

OPRF Protocol Flow:

import { createORPF } from "@noble/curves/abstract/oprf";
import { ristretto255 } from "@noble/curves/ed25519"; 
import { sha512 } from "@noble/hashes/sha512";

// Create OPRF suite for Ristretto255 + SHA-512
const oprf = createORPF({
  name: "ristretto255-SHA512",
  Point: ristretto255.Point,
  hash: sha512,
  hashToScalar: ristretto255.hashToScalar,
  hashToGroup: ristretto255.hashToCurve
});

// Server: Generate key pair
const serverKeys = oprf.voprf.generateKeyPair();

// Client: Blind input
const input = new TextEncoder().encode("secret-input");
const { blind, blinded } = oprf.voprf.blind(input);

// Server: Evaluate blinded input with proof
const { evaluated, proof } = oprf.voprf.blindEvaluate(
  serverKeys.secretKey,
  serverKeys.publicKey, 
  blinded
);

// Client: Finalize to get OPRF output
const output = oprf.voprf.finalize(
  input,
  blind,
  evaluated,
  blinded,
  serverKeys.publicKey,
  proof
);

Use Cases:

  • Password-Authenticated Key Exchange (PAKE): Secure password login without revealing passwords
  • Private Set Intersection (PSI): Compute set intersections while preserving privacy
  • Anonymous Credentials: Issue unlinkable credentials for Privacy Pass systems
  • Private Information Retrieval (PIR): Query databases without revealing accessed items
  • Encrypted Search: Enable keyword search over encrypted data with private queries
  • Spam Prevention: Issue anonymous tokens for rate-limiting and abuse prevention

Base Curve Abstractions

Core abstractions and interfaces for elliptic curve implementations, providing foundational types and multi-scalar multiplication.

import { Group, GroupCons, CurvePoint, pippenger } from "@noble/curves/abstract/curve";

// Base group interface for algebraic structures
interface Group<T extends Group<T>> {
  double(): T;
  negate(): T;
  add(other: T): T;
  subtract(other: T): T;
  equals(other: T): boolean;
  multiply(scalar: bigint): T;
}

// Group constructor interface
interface GroupCons<T extends Group<T>> {
  ZERO: T;
  BASE: T;
  fromBytes(bytes: Uint8Array): T;
  fromHex(hex: string): T;
}

// Curve point interface extending Group
interface CurvePoint<U, T extends CurvePoint<U, T> = CurvePoint<U, any>> extends Group<T> {
  readonly Fp: IField<U>;
  readonly Fn: IField<bigint>;
  x: U;
  y: U;
  is0(): boolean;
  toBytes(isCompressed?: boolean): Uint8Array;
  toHex(isCompressed?: boolean): string;
  toRawBytes(isCompressed?: boolean): Uint8Array;
  assertValidity(): void;
}

/**
 * Multi-scalar multiplication using Pippenger's algorithm
 * @param Point - Group constructor
 * @param Fn - Scalar field
 * @param points - Array of points to multiply
 * @param scalars - Array of scalars for multiplication
 * @returns Result of sum(points[i] * scalars[i])
 */
function pippenger<T extends Group<T>>(
  Point: GroupCons<T>,
  Fn: IField<bigint>,
  points: T[],
  scalars: bigint[]
): T;

docs

abstract-primitives.md

curves.md

index.md

utilities.md

webcrypto.md

tile.json