Module: BSV::Primitives::Curve

Defined in:
lib/bsv/primitives/curve.rb

Overview

Low-level secp256k1 elliptic curve operations.

Backed by the pure Ruby Secp256k1 module via an OpenSSL compatibility shim. The shim preserves the OpenSSL::PKey::EC interface so consumer code is unchanged. All constants and methods operate on the secp256k1 curve.

Constant Summary collapse

GROUP =

The secp256k1 curve group.

OpenSSL::PKey::EC::Group.new('secp256k1')
N =

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

GROUP.order
G =

The generator point (base point).

GROUP.generator
HALF_N =

Half the curve order, used for low-S normalisation.

(N >> 1)

Class Method Summary collapse

Class Method Details

.add_points(point_a, point_b) ⇒ OpenSSL::PKey::EC::Point

Add two curve points together.

Uses Point#add where available (Ruby 3.0+ / OpenSSL 3), falling back to multi-scalar multiplication for Ruby 2.7 compatibility.

Parameters:

Returns:



82
83
84
85
86
87
88
89
90
91
# File 'lib/bsv/primitives/curve.rb', line 82

def add_points(point_a, point_b)
  if point_a.respond_to?(:add)
    point_a.add(point_b)
  else
    # Ruby 2.7 / OpenSSL < 3: use multi-scalar mul
    # point_a.mul(bns, points) = bns[0]*point_a + bns[1]*points[0] + ...
    one = OpenSSL::BN.new('1')
    point_a.mul([one, one], [point_b])
  end
end

.multiply_generator(scalar_bn) ⇒ OpenSSL::PKey::EC::Point

Multiply the generator point by a scalar (variable-time, wNAF).

Suitable for public scalars only (e.g. verify paths). For secret scalars use multiply_generator_ct.

Parameters:

  • scalar_bn (OpenSSL::BN)

    the scalar multiplier

Returns:



35
36
37
# File 'lib/bsv/primitives/curve.rb', line 35

def multiply_generator(scalar_bn)
  G.mul(scalar_bn)
end

.multiply_generator_ct(scalar_bn) ⇒ OpenSSL::PKey::EC::Point

Multiply the generator point by a secret scalar (constant-time).

Uses the Montgomery ladder to avoid timing side-channels on the scalar. Use for key generation and signing.

Parameters:

  • scalar_bn (OpenSSL::BN)

    the secret scalar multiplier

Returns:



46
47
48
# File 'lib/bsv/primitives/curve.rb', line 46

def multiply_generator_ct(scalar_bn)
  G.mul_ct(scalar_bn)
end

.multiply_point(point, scalar_bn) ⇒ OpenSSL::PKey::EC::Point

Multiply an arbitrary curve point by a scalar (variable-time, wNAF).

Suitable for public scalars only. For secret scalars use multiply_point_ct.

Parameters:

Returns:



58
59
60
# File 'lib/bsv/primitives/curve.rb', line 58

def multiply_point(point, scalar_bn)
  point.mul(scalar_bn)
end

.multiply_point_ct(point, scalar_bn) ⇒ OpenSSL::PKey::EC::Point

Multiply an arbitrary curve point by a secret scalar (constant-time).

Uses the Montgomery ladder to avoid timing side-channels on the scalar. Use for ECDH shared-secret derivation.

Parameters:

Returns:



70
71
72
# File 'lib/bsv/primitives/curve.rb', line 70

def multiply_point_ct(point, scalar_bn)
  point.mul_ct(scalar_bn)
end

.point_from_bytes(bytes) ⇒ OpenSSL::PKey::EC::Point

Reconstruct a curve point from its byte representation.

Parameters:

  • bytes (String)

    compressed (33 bytes) or uncompressed (65 bytes) point encoding

Returns:



107
108
109
# File 'lib/bsv/primitives/curve.rb', line 107

def point_from_bytes(bytes)
  OpenSSL::PKey::EC::Point.new(GROUP, OpenSSL::BN.new(bytes, 2))
end

.point_x(point) ⇒ OpenSSL::BN

Extract the x-coordinate from a curve point as a big number.

Parameters:

Returns:

  • (OpenSSL::BN)

    the x-coordinate



97
98
99
100
101
# File 'lib/bsv/primitives/curve.rb', line 97

def point_x(point)
  # Uncompressed octet string: 0x04 || X (32 bytes) || Y (32 bytes)
  # Slicing raw bytes avoids BN#to_s(16) stripping leading zeros.
  OpenSSL::BN.new(point.to_octet_string(:uncompressed)[1, 32], 2)
end