Class: BLS::PointG1

Inherits:
ProjectivePoint show all
Defined in:
lib/bls/point/g1.rb

Constant Summary collapse

DST_BASIC =
'BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_NUL_'
KEY_SIZE_COMPRESSED =
48
KEY_SIZE_UNCOMPRESSED =
96
BASE =
PointG1.new(Fp.new(Curve::G_X), Fp.new(Curve::G_Y), Fp::ONE)
ZERO =
PointG1.new(Fp::ONE, Fp::ONE, Fp::ZERO)
MAX_BITS =
Fp::MAX_BITS

Instance Attribute Summary

Attributes inherited from ProjectivePoint

#m_precomputes, #x, #y, #z

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from ProjectivePoint

#==, #add, #calc_multiply_precomputes, #clear_multiply_precomputes, #double, #from_affine_tuple, #gen_invert_batch, #initialize, #max_bits, #multiply, #multiply_unsafe, #negate, #new_point, #normalize_z, #precomputes_window, #subtract, #to_affine, #to_affine_batch, #zero, #zero?

Constructor Details

This class inherits a constructor from BLS::ProjectivePoint

Class Method Details

.from_hex(hex) ⇒ PointG1

Parse PointG1 from form hex.

Parameters:

  • hex (String)

    hex value of PointG1.

Returns:

Raises:

  • (BLS::PointError)

    Occurs when hex length does not match, or point does not on G1.



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/bls/point/g1.rb', line 17

def self.from_hex(hex)
  bytes = [hex].pack('H*')
  point = case bytes.bytesize
          when KEY_SIZE_COMPRESSED
            compressed_value = hex.to_i(16)
            b_flag = BLS.mod(compressed_value, POW_2_383) / POW_2_382
            return ZERO if b_flag == 1

            x = BLS.mod(compressed_value, POW_2_381)
            full_y = BLS.mod(x**3 + Fp.new(Curve::B).value, Curve::P)
            y = BLS.pow_mod(full_y, (Curve::P + 1) / 4, Curve::P)
            raise PointError, 'The given point is not on G1: y**2 = x**3 + b.' unless (BLS.pow_mod(y, 2, Curve::P) - full_y).zero?

            a_flag = BLS.mod(compressed_value, POW_2_382) / POW_2_381
            y = Curve::P - y unless ((y * 2) / Curve::P) == a_flag
            PointG1.new(Fp.new(x), Fp.new(y), Fp::ONE)
          when KEY_SIZE_UNCOMPRESSED
            return ZERO unless (bytes[0].unpack1('H*').to_i(16) & (1 << 6)).zero?

            x = bytes[0...PUBLIC_KEY_LENGTH].unpack1('H*').to_i(16)
            y = bytes[PUBLIC_KEY_LENGTH..-1].unpack1('H*').to_i(16)
            PointG1.new(Fp.new(x), Fp.new(y), Fp::ONE)
          else
            raise PointError, 'Invalid point G1, expected 48 or 96 bytes.'
          end
  point.validate!
  point
end

.from_private_key(private_key) ⇒ PointG1

Parse Point from private key.

Parameters:

  • private_key (String|Integer)

    a private key with hex or number.

Returns:

  • (PointG1)

    G1Point corresponding to private keys.

Raises:

  • (BLS::Error)

    Occur when the private key is zero.



70
71
72
# File 'lib/bls/point/g1.rb', line 70

def self.from_private_key(private_key)
  BASE * BLS.normalize_priv_key(private_key)
end

.hash_to_curve(message) ⇒ BLS::PointG1

Convert hash to PointG1

Parameters:

  • message (String)

    a hash with hex format.

Returns:

Raises:



78
79
80
81
82
83
84
85
# File 'lib/bls/point/g1.rb', line 78

def self.hash_to_curve(message)
  raise PointError, 'expected hex string' unless message[/^[a-fA-F0-9]*$/]

  h2c = ::H2C.get(::H2C::Suite::BLS12381G1_XMDSHA256_SWU_RO_, PointG1::DST_BASIC)
  p = h2c.digest([message].pack('H*'))

  PointG1.new(Fp.new(p.x), Fp.new(p.y), Fp::ONE)
end

Instance Method Details

#miller_loop(p) ⇒ Object

Sparse multiplication against precomputed coefficients.

Parameters:



100
101
102
# File 'lib/bls/point/g1.rb', line 100

def miller_loop(p)
  BLS.miller_loop(p.pairing_precomputes, to_affine)
end

#to_hex(compressed: false) ⇒ Object



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/bls/point/g1.rb', line 46

def to_hex(compressed: false)
  if compressed
    if self == PointG1::ZERO
      hex = POW_2_383 + POW_2_382
    else
      x, y = to_affine
      flag = (y.value * 2) / Curve::P
      hex = x.value + flag * POW_2_381 + POW_2_383
    end
    BLS.num_to_hex(hex, PUBLIC_KEY_LENGTH)
  else
    if self == PointG1::ZERO
      (1 << 6).to_s(16) + '00' * (2 * PUBLIC_KEY_LENGTH - 1)
    else
      x, y = to_affine
      BLS.num_to_hex(x.value, PUBLIC_KEY_LENGTH) + BLS.num_to_hex(y.value, PUBLIC_KEY_LENGTH)
    end
  end
end

#validate!Object

Validate this point whether on curve over Fp.

Raises:

  • (PointError)

    Occur when this point not on curve over Fp.



89
90
91
92
93
94
95
96
# File 'lib/bls/point/g1.rb', line 89

def validate!
  b = Fp.new(Curve::B)
  return if zero?

  left = y.pow(2) * z - x.pow(3)
  right = b * z.pow(3)
  raise PointError, 'Invalid point: not on curve over Fp' unless left == right
end