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:



107
108
109
110
111
112
113
114
115
116
# File 'lib/bsv/primitives/curve.rb', line 107

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 (constant-time).

Uses the Montgomery ladder by default, matching OpenSSL convention. Safe for both secret and public scalars. For explicit variable-time multiplication of public scalars, use multiply_generator_vt.

Parameters:

  • scalar_bn (OpenSSL::BN)

    the scalar multiplier

Returns:



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

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).

Alias for multiply_generator — retained for backward compatibility and expressiveness.

Parameters:

  • scalar_bn (OpenSSL::BN)

    the secret scalar multiplier

Returns:



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

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

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

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

Faster than multiply_generator but leaks timing information about the scalar. Use only for public scalars (e.g. signature verification).

Parameters:

  • scalar_bn (OpenSSL::BN)

    the public scalar multiplier

Returns:



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

def multiply_generator_vt(scalar_bn)
  G.mul_vt(scalar_bn)
end

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

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

Uses the Montgomery ladder by default, matching OpenSSL convention. Safe for both secret and public scalars. For explicit variable-time multiplication of public scalars, use multiply_point_vt.

Parameters:

Returns:



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

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).

Alias for multiply_point — retained for backward compatibility and expressiveness.

Parameters:

Returns:



83
84
85
# File 'lib/bsv/primitives/curve.rb', line 83

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

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

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

Faster than multiply_point but leaks timing information about the scalar. Use only for public scalars (e.g. signature verification).

Parameters:

Returns:



95
96
97
# File 'lib/bsv/primitives/curve.rb', line 95

def multiply_point_vt(point, scalar_bn)
  point.mul_vt(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:



132
133
134
# File 'lib/bsv/primitives/curve.rb', line 132

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



122
123
124
125
126
# File 'lib/bsv/primitives/curve.rb', line 122

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