Class: BLS::PointG2

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

Constant Summary collapse

DST_BASIC =
'BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_'
KEY_SIZE_COMPRESSED =
96
KEY_SIZE_UNCOMPRESSED =
192
MAX_BITS =
Fp2::MAX_BITS
BASE =
PointG2.new(Fp2.new(Curve::G2_X), Fp2.new(Curve::G2_Y), Fp2::ONE)
ZERO =
PointG2.new(Fp2::ONE, Fp2::ONE, Fp2::ZERO)

Instance Attribute Summary collapse

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

Instance Attribute Details

#precomputesObject

Returns the value of attribute precomputes.



4
5
6
# File 'lib/bls/point/g2.rb', line 4

def precomputes
  @precomputes
end

Class Method Details

.from_hex(hex) ⇒ BLS::PointG2

Parameters:

  • hex (String)

    hex value of PointG2. Currently, only uncompressed formats(196 bytes) are supported.

Returns:

Raises:



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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/bls/point/g2.rb', line 20

def self.from_hex(hex)
  bytes = [hex].pack('H*')
  m_byte = bytes[0].unpack1('C')& 0xe0
  if [0x20, 0x60, 0xe0].include?(m_byte)
    raise PointError, "Invalid encoding flag: #{m_byte.to_s(16)}"
  end

  c_bit = m_byte & POINT_COMPRESSION_FLAG # compression flag
  i_bit = m_byte & POINT_INFINITY_FLAG # infinity flag
  s_bit = m_byte & POINT_Y_FLAG # y coordinate sign flag
  bytes[0] = [bytes[0].unpack1('C') & 0x1f].pack('C') # set flag to 0

  if i_bit == POINT_INFINITY_FLAG && bytes.unpack1('H*').to_i(16) > 0
    raise PointError, 'Invalid point, infinity point should be all 0.'
  end

  point = if bytes.bytesize == KEY_SIZE_COMPRESSED && c_bit == POINT_COMPRESSION_FLAG # compress format
            return ZERO if i_bit == POINT_INFINITY_FLAG
            x1 = bytes[0...PUBLIC_KEY_LENGTH].unpack1('H*').to_i(16)
            x0 = bytes[PUBLIC_KEY_LENGTH...(2 * PUBLIC_KEY_LENGTH)].unpack1('H*').to_i(16)
            x = Fp2.new([x0, x1])
            right = x ** 3 + Fp2.new(Curve::B2)
            y = right.sqrt
            raise PointError, 'Invalid compressed G2 point' unless y
            bit_y = if y.coeffs[1].value == 0
                      (y.coeffs[0].value * 2) / Curve::P
                    else
                      (y.coeffs[1].value * 2) / Curve::P == 1 ? 1 : 0
                    end
            y = s_bit > 0 && bit_y > 0 ? y : y.negate
            PointG2.new(x, y, Fp2::ONE)
          elsif bytes.bytesize == KEY_SIZE_UNCOMPRESSED && c_bit != POINT_COMPRESSION_FLAG # uncompressed format
            return ZERO if i_bit == POINT_INFINITY_FLAG
            x1 = bytes[0...PUBLIC_KEY_LENGTH].unpack1('H*').to_i(16)
            x0 = bytes[PUBLIC_KEY_LENGTH...(2 * PUBLIC_KEY_LENGTH)].unpack1('H*').to_i(16)
            y1 = bytes[(2 * PUBLIC_KEY_LENGTH)...(3 * PUBLIC_KEY_LENGTH)].unpack1('H*').to_i(16)
            y0 = bytes[(3 * PUBLIC_KEY_LENGTH)..-1].unpack1('H*').to_i(16)
            PointG2.new(Fp2.new([x0, x1]), Fp2.new([y0, y1]), Fp2::ONE)
          else
            raise PointError, 'Invalid point G2, expected 96/192 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.



69
70
71
# File 'lib/bls/point/g2.rb', line 69

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

.hash_to_curve(message) ⇒ BLS::PointG2

Convert hash to PointG2

Parameters:

  • message (String)

    a hash with hex format.

Returns:

Raises:



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

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

  u = BLS::H2C::G2.hash_to_field(message)
  q0 = PointG2.new(*BLS::H2C::G2.isogeny_map(*BLS::H2C::G2.map_to_curve_sswu(u[0])))
  q1 = PointG2.new(*BLS::H2C::G2.isogeny_map(*BLS::H2C::G2.map_to_curve_sswu(u[1])))
  r = q0 + q1
  clear_cofactor(r)
end

Instance Method Details

#clear_pairing_precomputesObject



136
137
138
# File 'lib/bls/point/g2.rb', line 136

def clear_pairing_precomputes
  self.precomputes = nil
end

#pairing_precomputesObject



140
141
142
143
144
145
# File 'lib/bls/point/g2.rb', line 140

def pairing_precomputes
  return precomputes if precomputes

  self.precomputes = calc_pairing_precomputes(*to_affine)
  precomputes
end

#to_hex(compressed: false) ⇒ String

Serialize pont as hex value.

Parameters:

  • compressed (Boolean) (defaults to: false)

    whether to compress the point.

Returns:

  • (String)

    hex value of point.



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/bls/point/g2.rb', line 90

def to_hex(compressed: false)
  if compressed
    if zero?
      x1 = POW_2_383 + POW_2_382
      x0= 0
    else
      x, y = to_affine
      flag = if y.coeffs[1].value == 0
               (y.coeffs[0].value * 2) / Curve::P
             else
               ((y.coeffs[1].value * 2) / Curve::P).zero? ? 0 : 1
             end
      x1 = x.coeffs[1].value + flag * POW_2_381 + POW_2_383
      x0 = x.coeffs[0].value
    end
    BLS.num_to_hex(x1, PUBLIC_KEY_LENGTH) + BLS.num_to_hex(x0, PUBLIC_KEY_LENGTH)
  else
    if self == PointG2::ZERO
      (1 << 6).to_s(16) + '00' * (4 * PUBLIC_KEY_LENGTH - 1)
    else
      validate!
      x, y = to_affine.map(&:values)
      BLS.num_to_hex(x[1], PUBLIC_KEY_LENGTH) +
        BLS.num_to_hex(x[0], PUBLIC_KEY_LENGTH) +
        BLS.num_to_hex(y[1], PUBLIC_KEY_LENGTH) +
        BLS.num_to_hex(y[0], PUBLIC_KEY_LENGTH)
    end
  end
end

#to_signatureString

Deprecated.

Use #to_hex instead.

Convert to signature with hex format.

Returns:

  • (String)

    signature with hex format.



123
124
125
# File 'lib/bls/point/g2.rb', line 123

def to_signature
  to_hex(compressed: true)
end

#validate!Object

Raises:



127
128
129
130
131
132
133
134
# File 'lib/bls/point/g2.rb', line 127

def validate!
  b = Fp2.new(Curve::B2)
  return if zero?

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