Module Secp256k1

Pure Ruby secp256k1 elliptic curve implementation.

Provides field arithmetic, point operations with Jacobian coordinates, and windowed-NAF scalar multiplication. Ported from the BSV TypeScript SDK reference implementation.

All field operations work on plain Ruby Integer values (arbitrary precision, C-backed in MRI). No external gems required.

Constants

GX

Generator point x-coordinate.

GY

Generator point y-coordinate.

HALF_N

Half the curve order, used for low-S normalisation (BIP-62).

JP_INFINITY

Not documented.

MASK_256

256-bit mask for fast reduction.

N

The curve order (number of points on the curve).

P

The secp256k1 field prime: p = 2^256 - 2^32 - 977

P_PLUS1_DIV4

(P + 1) / 4 — used for modular square root since P ≡ 3 (mod 4).

VERSION

Not documented.

WNAF_CACHE_MAX

Maximum number of entries kept in the wNAF precomputation cache. Bounds memory usage for long-running processes (e.g. servers).

WNAF_TABLE_CACHE

Cache for precomputed wNAF tables, keyed by “window:x:y”. FIFO eviction: the oldest inserted entry is dropped when the cap is reached (Hash preserves insertion order; we delete the first key). Bounded at WNAF_CACHE_MAX entries; keyed only on the public base point — no secret-scalar exposure.

Public Class Methods

allow_pure_ruby_ct!()

Explicitly allow constant-time operations in pure-Ruby mode. Call this only after evaluating the risks documented in docs/risks.md.

bytes_to_int(bytes)

Convert a big-endian binary string to an Integer.

  • @param bytes [String] binary string (ASCII-8BIT)
  • @return [Integer]

fadd(a, b)

Modular addition in the field.

finv(a)

Modular multiplicative inverse in the field (Fermat’s little theorem).

  • @param a [Integer] value to invert (must be non-zero mod P)
  • @raise [ArgumentError] if a is zero mod P
  • @return [Integer] a^(P-2) mod P

fmul(a, b)

Modular multiplication in the field.

fneg(a)

Modular negation in the field.

Canonicalises the operand so the result matches the C wrapper for any non-negative 256-bit input — see {#fsub} for the negative-input note.

fred(x)

Fast reduction modulo the secp256k1 prime.

Exploits the structure P = 2^256 - 2^32 - 977 to avoid generic modular division. Two folding passes plus a conditional subtraction.

  • @param x [Integer] non-negative integer
  • @return [Integer] x mod P, in range [0, P)

fsqr(a)

Modular squaring in the field.

fsqrt(a)

Modular square root in the field.

Uses the identity sqrt(a) = a^((P+1)/4) mod P, valid because P ≡ 3 (mod 4). Returns nil if a is not a quadratic residue.

  • @param a [Integer]
  • @return [Integer, nil] the square root, or nil if none exists

fsub(a, b)

Modular subtraction in the field.

Canonicalises both operands so the result matches the C wrapper for any non-negative 256-bit input — load-bearing for the dfuzz differential, where pure-Ruby serves as the oracle. The dfuzz harness only feeds non-negative inputs (xorshift output, plus structured P-band vectors), so the differential never observes the negative case.

Note: pure-Ruby accepts negative inputs (Ruby % canonicalises them); the C wrapper rejects negatives via rb_to_uint256. Backend parity holds for all >= 0 inputs; intentional divergence on negatives.

int_to_bytes(n, length = 32)

Convert an Integer to a fixed-length big-endian binary string.

  • @param n [Integer] the integer to convert
  • @param length [Integer] desired byte length (default 32)
  • @raise [ArgumentError]
  • @return [String] binary string (ASCII-8BIT)

jp_add(p, q)

Add two Jacobian points.

  • @param p [Array] first Jacobian point
  • @param q [Array] second Jacobian point
  • @return [Array] resulting Jacobian point

jp_double(p)

Double a Jacobian point.

Formula from hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html (a=0 for secp256k1).

  • @param p [Array(Integer, Integer, Integer)] Jacobian point [X, Y, Z]
  • @return [Array(Integer, Integer, Integer)]

jp_neg(p)

Negate a Jacobian point.

jp_to_affine(jp)

Convert a Jacobian point to affine coordinates.

  • @param jp [Array(Integer, Integer, Integer)]
  • @return [Array(Integer, Integer)] affine [x, y], or nil for infinity

native?()

Whether the native C extension is loaded and active.

  • @return [Boolean]

pure_ruby_ct_allowed?()

  • @api private
  • @return [Boolean]

scalar_add(a, b)

Scalar addition mod N.

scalar_inv(a)

Scalar multiplicative inverse (Fermat).

  • @raise [ArgumentError] if a is zero mod N

scalar_mod(a)

Reduce modulo the curve order.

scalar_mul(a, b)

Scalar multiplication mod N.


This site uses Just the Docs, a documentation theme for Jekyll.