bls12-381 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/bls/point.rb CHANGED
@@ -1,9 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'bigdecimal'
4
+ require 'h2c'
4
5
 
5
6
  module BLS
6
7
 
8
+ # Point serialization flags
9
+ POINT_COMPRESSION_FLAG = 0x80
10
+ POINT_INFINITY_FLAG = 0x40
11
+ POINT_Y_FLAG = 0x20
12
+
13
+ autoload :PointG1, "bls/point/g1"
14
+ autoload :PointG2, "bls/point/g2"
15
+
7
16
  class PointError < StandardError; end
8
17
 
9
18
  # Abstract Point class that consist of projective coordinates.
@@ -224,240 +233,8 @@ module BLS
224
233
  end
225
234
  end
226
235
 
227
- class PointG1 < ProjectivePoint
228
-
229
- BASE = PointG1.new(Fq.new(Curve::G_X), Fq.new(Curve::G_Y), Fq::ONE)
230
- ZERO = PointG1.new(Fq::ONE, Fq::ONE, Fq::ZERO)
231
- MAX_BITS = Fq::MAX_BITS
232
-
233
- # Parse PointG1 from form hex.
234
- # @param [String] hex hex value of PointG1.
235
- # @return [PointG1]
236
- # @raise [BLS::PointError] Occurs when hex length does not match, or point does not on G1.
237
- def self.from_hex(hex)
238
- bytes = [hex].pack('H*')
239
- point = case bytes.bytesize
240
- when 48
241
- compressed_value = hex.to_i(16)
242
- b_flag = BLS.mod(compressed_value, POW_2_383) / POW_2_382
243
- return ZERO if b_flag == 1
244
-
245
- x = BLS.mod(compressed_value, POW_2_381)
246
- full_y = BLS.mod(x**3 + Fq.new(Curve::B).value, Curve::P)
247
- y = BLS.pow_mod(full_y, (Curve::P + 1) / 4, Curve::P)
248
- 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?
249
-
250
- a_flag = BLS.mod(compressed_value, POW_2_382) / POW_2_381
251
- y = Curve::P - y unless ((y * 2) / Curve::P) == a_flag
252
- PointG1.new(Fq.new(x), Fq.new(y), Fq::ONE)
253
- when 96
254
- return ZERO unless (bytes[0].unpack1('H*').to_i(16) & (1 << 6)).zero?
255
-
256
- x = bytes[0...PUBLIC_KEY_LENGTH].unpack1('H*').to_i(16)
257
- y = bytes[PUBLIC_KEY_LENGTH..-1].unpack1('H*').to_i(16)
258
- PointG1.new(Fq.new(x), Fq.new(y), Fq::ONE)
259
- else
260
- raise PointError, 'Invalid point G1, expected 48 or 96 bytes.'
261
- end
262
- point.validate!
263
- point
264
- end
265
-
266
- def to_hex(compressed: false)
267
- if compressed
268
- if self == PointG1::ZERO
269
- hex = POW_2_383 + POW_2_382
270
- else
271
- x, y = to_affine
272
- flag = (y.value * 2) / Curve::P
273
- hex = x.value + flag * POW_2_381 + POW_2_383
274
- end
275
- BLS.num_to_hex(hex, PUBLIC_KEY_LENGTH)
276
- else
277
- if self == PointG1::ZERO
278
- (1 << 6).to_s(16) + '00' * (2 * PUBLIC_KEY_LENGTH - 1)
279
- else
280
- x, y = to_affine
281
- BLS.num_to_hex(x.value, PUBLIC_KEY_LENGTH) + BLS.num_to_hex(y.value, PUBLIC_KEY_LENGTH)
282
- end
283
- end
284
- end
285
-
286
- # Parse Point from private key.
287
- # @param [String|Integer] private_key a private key with hex or number.
288
- # @return [PointG1] G1Point corresponding to private keys.
289
- # @raise [BLS::Error] Occur when the private key is zero.
290
- def self.from_private_key(private_key)
291
- BASE * BLS.normalize_priv_key(private_key)
292
- end
293
-
294
- # Validate this point whether on curve over Fq.
295
- # @raise [PointError] Occur when this point not on curve over Fq.
296
- def validate!
297
- b = Fq.new(Curve::B)
298
- return if zero?
299
-
300
- left = y.pow(2) * z - x.pow(3)
301
- right = b * z.pow(3)
302
- raise PointError, 'Invalid point: not on curve over Fq' unless left == right
303
- end
304
-
305
- # Sparse multiplication against precomputed coefficients.
306
- # @param [PointG2] p
307
- def miller_loop(p)
308
- BLS.miller_loop(p.pairing_precomputes, to_affine)
309
- end
310
- end
311
-
312
- class PointG2 < ProjectivePoint
313
-
314
- attr_accessor :precomputes
315
-
316
- MAX_BITS = Fq2::MAX_BITS
317
- BASE = PointG2.new(Fq2.new(Curve::G2_X), Fq2.new(Curve::G2_Y), Fq2::ONE)
318
- ZERO = PointG2.new(Fq2::ONE, Fq2::ONE, Fq2::ZERO)
319
-
320
- # Parse PointG1 from form hex.
321
- # @param [String] hex hex value of PointG2. Currently, only uncompressed formats(196 bytes) are supported.
322
- # @return [BLS::PointG2] PointG2 object.
323
- # @raise [BLS::PointError]
324
- def self.from_hex(hex)
325
- bytes = [hex].pack('H*')
326
- point = case bytes.bytesize
327
- when 96
328
- raise PointError, 'Compressed format not supported yet.'
329
- when 192
330
- return ZERO unless (bytes[0].unpack1('H*').to_i(16) & (1 << 6)).zero?
331
-
332
- x1 = bytes[0...PUBLIC_KEY_LENGTH].unpack1('H*').to_i(16)
333
- x0 = bytes[PUBLIC_KEY_LENGTH...(2 * PUBLIC_KEY_LENGTH)].unpack1('H*').to_i(16)
334
- y1 = bytes[(2 * PUBLIC_KEY_LENGTH)...(3 * PUBLIC_KEY_LENGTH)].unpack1('H*').to_i(16)
335
- y0 = bytes[(3 * PUBLIC_KEY_LENGTH)..-1].unpack1('H*').to_i(16)
336
- PointG2.new(Fq2.new([x0, x1]), Fq2.new([y0, y1]), Fq2::ONE)
337
- else
338
- raise PointError, 'Invalid uncompressed point G2, expected 192 bytes.'
339
- end
340
- point.validate!
341
- point
342
- end
343
-
344
- # Parse Point from private key.
345
- # @param [String|Integer] private_key a private key with hex or number.
346
- # @return [PointG1] G1Point corresponding to private keys.
347
- # @raise [BLS::Error] Occur when the private key is zero.
348
- def self.from_private_key(private_key)
349
- BASE * BLS.normalize_priv_key(private_key)
350
- end
351
-
352
- # Convert hash to PointG2
353
- # @param [String] message a hash with hex format.
354
- # @return [BLS::PointG2] point.
355
- # @raise [BLS::PointError]
356
- def self.hash_to_curve(message)
357
- raise PointError, 'expected hex string' unless message[/^[a-fA-F0-9]*$/]
358
-
359
- u = BLS.hash_to_field(message, 2)
360
- q0 = PointG2.new(*BLS.isogeny_map_g2(*BLS.map_to_curve_sswu_g2(u[0])))
361
- q1 = PointG2.new(*BLS.isogeny_map_g2(*BLS.map_to_curve_sswu_g2(u[1])))
362
- r = q0 + q1
363
- BLS.clear_cofactor_g2(r)
364
- end
365
-
366
- def to_hex(compressed: false)
367
- raise ArgumentError, 'Not supported' if compressed
368
-
369
- if self == PointG2::ZERO
370
- (1 << 6).to_s(16) + '00' * (4 * PUBLIC_KEY_LENGTH - 1)
371
- else
372
- validate!
373
- x, y = to_affine.map(&:values)
374
- BLS.num_to_hex(x[1], PUBLIC_KEY_LENGTH) +
375
- BLS.num_to_hex(x[0], PUBLIC_KEY_LENGTH) +
376
- BLS.num_to_hex(y[1], PUBLIC_KEY_LENGTH) +
377
- BLS.num_to_hex(y[0], PUBLIC_KEY_LENGTH)
378
- end
379
- end
380
-
381
- # Convert to signature with hex format.
382
- # @return [String] signature with hex format.
383
- def to_signature
384
- if self == PointG2::ZERO
385
- sum = POW_2_383 + POW_2_382
386
- return BLS.num_to_hex(sum, PUBLIC_KEY_LENGTH) + BLS.num_to_hex(0, PUBLIC_KEY_LENGTH)
387
- end
388
- validate!
389
- x, y = to_affine.map(&:values)
390
- tmp = y[1] > 0 ? y[1] * 2 : y[0] * 2
391
- aflag1 = tmp / Curve::P
392
- z1 = x[1] + aflag1 * POW_2_381 + POW_2_383
393
- z2 = x[0]
394
- BLS.num_to_hex(z1, PUBLIC_KEY_LENGTH) + BLS.num_to_hex(z2, PUBLIC_KEY_LENGTH)
395
- end
396
-
397
- def validate!
398
- b = Fq2.new(Curve::B2)
399
- return if zero?
400
-
401
- left = y.pow(2) * z - x.pow(3)
402
- right = b * z.pow(3)
403
- raise PointError, 'Invalid point: not on curve over Fq2' unless left == right
404
- end
405
-
406
- def clear_pairing_precomputes
407
- self.precomputes = nil
408
- end
409
-
410
- def pairing_precomputes
411
- return precomputes if precomputes
412
-
413
- self.precomputes = calc_pairing_precomputes(*to_affine)
414
- precomputes
415
- end
416
-
417
- private
418
-
419
- def calc_pairing_precomputes(x, y)
420
- q_x, q_y, q_z = [x, y, Fq2::ONE]
421
- r_x, r_y, r_z = [q_x, q_y, q_z]
422
- ell_coeff = []
423
- i = BLS_X_LEN - 2
424
- while i >= 0
425
- t0 = r_y.square
426
- t1 = r_z.square
427
- t2 = t1.multiply(3).multiply_by_b
428
- t3 = t2 * 3
429
- t4 = (r_y + r_z).square - t1 - t0
430
- ell_coeff << [t2 - t0, r_x.square * 3, t4.negate]
431
- r_x = (t0 - t3) * r_x * r_y / 2
432
- r_y = ((t0 + t3) / 2).square - t2.square * 3
433
- r_z = t0 * t4
434
- unless BLS.bit_get(Curve::X, i).zero?
435
- t0 = r_y - q_y * r_z
436
- t1 = r_x - q_x * r_z
437
- ell_coeff << [t0 * q_x - t1 * q_y, t0.negate, t1]
438
- t2 = t1.square
439
- t3 = t2 * t1
440
- t4 = t2 * r_x
441
- t5 = t3 - t4 * 2 + t0.square * r_z
442
- r_x = t1 * t5
443
- r_y = (t4 - t5) * t0 - t3 * r_y
444
- r_z *= t3
445
- end
446
- i -= 1
447
- end
448
- ell_coeff
449
- end
450
- end
451
-
452
236
  module_function
453
237
 
454
- def clear_cofactor_g2(p)
455
- t1 = p.multiply_unsafe(Curve::X).negate
456
- t2 = p.from_affine_tuple(BLS.psi(*p.to_affine))
457
- p2 = p.from_affine_tuple(BLS.psi2(*p.double.to_affine))
458
- p2 - t2 + (t1 + t2).multiply_unsafe(Curve::X).negate - t1 - p
459
- end
460
-
461
238
  def norm_p1(point)
462
239
  point.is_a?(PointG1) ? point : PointG1.from_hex(point)
463
240
  end
@@ -466,52 +243,12 @@ module BLS
466
243
  point.is_a?(PointG2) ? point : PointG2.from_hex(point)
467
244
  end
468
245
 
469
- def norm_p2h(point)
470
- point.is_a?(PointG2) ? point : PointG2.hash_to_curve(point)
246
+ def norm_p1h(point)
247
+ point.is_a?(PointG1) ? point : PointG1.hash_to_curve(point)
471
248
  end
472
249
 
473
- # Convert hash to Field.
474
- # @param [String] message hash value with hex format.
475
- # @return [Array[Integer]] byte array.
476
- def hash_to_field(message, degree, random_oracle: true)
477
- count = random_oracle ? 2 : 1
478
- l = 64
479
- len_in_bytes = count * degree * l
480
- pseudo_random_bytes = BLS.expand_message_xmd(message, len_in_bytes)
481
- u = Array.new(count)
482
- count.times do |i|
483
- e = Array.new(degree)
484
- degree.times do |j|
485
- elm_offset = l * (j + i * degree)
486
- tv = pseudo_random_bytes[elm_offset...(elm_offset + l)]
487
- e[j] = BLS.mod(BLS.os2ip(tv), Curve::P)
488
- end
489
- u[i] = e
490
- end
491
- u
250
+ def norm_p2h(point)
251
+ point.is_a?(PointG2) ? point : PointG2.hash_to_curve(point)
492
252
  end
493
253
 
494
- # @param [String] message hash value with hex format.
495
- # @param [Integer] len_in_bytes length
496
- # @return [Array[Integer]] byte array.
497
- # @raise BLS::Error
498
- def expand_message_xmd(message, len_in_bytes)
499
- b_in_bytes = BigDecimal(SHA256_DIGEST_SIZE)
500
- r_in_bytes = b_in_bytes * 2
501
- ell = (BigDecimal(len_in_bytes) / b_in_bytes).ceil
502
- raise BLS::Error, 'Invalid xmd length' if ell > 255
503
-
504
- dst_prime = DST_LABEL.bytes + BLS.i2osp(DST_LABEL.bytesize, 1)
505
- z_pad = BLS.i2osp(0, r_in_bytes)
506
- l_i_b_str = BLS.i2osp(len_in_bytes, 2)
507
- b = Array.new(ell)
508
- payload = z_pad + [message].pack('H*').bytes + l_i_b_str + BLS.i2osp(0, 1) + dst_prime
509
- b_0 = Digest::SHA256.digest(payload.pack('C*'))
510
- b[0] = Digest::SHA256.digest((b_0.bytes + BLS.i2osp(1, 1) + dst_prime).pack('C*'))
511
- (1..ell).each do |i|
512
- args = BLS.bin_xor(b_0, b[i - 1]).bytes + BLS.i2osp(i + 1, 1) + dst_prime
513
- b[i] = Digest::SHA256.digest(args.pack('C*'))
514
- end
515
- b.map(&:bytes).flatten[0...len_in_bytes]
516
- end
517
254
  end
data/lib/bls/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module BLS
4
- VERSION = '0.2.1'
4
+ VERSION = '0.3.0'
5
5
  end
data/lib/bls.rb CHANGED
@@ -5,6 +5,7 @@ require 'bls/version'
5
5
  require 'bls/math'
6
6
  require 'bls/curve'
7
7
  require 'bls/field'
8
+ require 'bls/h2c'
8
9
  require 'bls/point'
9
10
  require 'bls/pairing'
10
11
 
@@ -19,82 +20,134 @@ module BLS
19
20
  PUBLIC_KEY_LENGTH = 48
20
21
  SHA256_DIGEST_SIZE = 32
21
22
 
22
- DST_LABEL = 'BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_'
23
-
24
23
  module_function
25
24
 
26
25
  # Generate BLS signature: s = pk x H(m)
27
- # @param [String] message Message digest(hash value with hex format) to be signed.
26
+ # @param [String] message Message digest(hex format) to be signed.
28
27
  # @param [Integer|String] private_key The private key used for signing. Integer or String(hex).
28
+ # @param [Symbol] sig_type Signature type, :g1 or :g2.
29
+ # If :g1 is specified, the signature is a point on G1 and the public key is a point on G2.
30
+ # If :g2 is specified, the signature is a point on G2 and the public key is a point on G1.
29
31
  # @return [PointG2] The signature point.
30
- def sign(message, private_key)
31
- msg_point = BLS.norm_p2h(message)
32
+ def sign(message, private_key, sig_type: :g2)
33
+ msg_point = case sig_type
34
+ when :g1
35
+ BLS.norm_p1h(message)
36
+ when :g2
37
+ BLS.norm_p2h(message)
38
+ else
39
+ raise Error, 'sig_type must be :g1 or :g2.'
40
+ end
32
41
  msg_point * BLS.normalize_priv_key(private_key)
33
42
  end
34
43
 
35
44
  # Generate public key from +private_key+.
36
45
  # @param [Integer|String] private_key The private key. Integer or String(hex).
37
- # @return [BLS::PointG1] public key.
38
- def get_public_key(private_key)
39
- PointG1.from_private_key(private_key)
46
+ # @param [Symbol] key_type Public key type, :g1 or :g2.
47
+ # @return [BLS::PointG1|BLS::PointG2] public key.
48
+ def get_public_key(private_key, key_type: :g1)
49
+ case key_type
50
+ when :g1
51
+ PointG1.from_private_key(private_key)
52
+ when :g2
53
+ PointG2.from_private_key(private_key)
54
+ else
55
+ raise Error, 'key_type must be :g1 or :g2.'
56
+ end
40
57
  end
41
58
 
42
- # Verify BLS signature.
43
- # @param [String] signature
59
+ # Verify BLS signature. Verify one of the following:
60
+ # * Public key is a point on G1, signature is a point on G2 or
61
+ # * Public key is a point on G2, signature is a point on G1.
62
+ # @param [BLS::PointG1|BLS::PointG2] signature
44
63
  # @param [String] message Message digest(hash value with hex format) to be verified.
45
- # @param [String|BLS::PointG1] public_key Public key with hex format or PointG1.
64
+ # @param [BLS::PointG2|BLS::PointG1] public_key Public key with hex format or PointG1.
46
65
  # @return [Boolean] verification result.
47
66
  def verify(signature, message, public_key)
48
- p = BLS.norm_p1(public_key)
49
- hm = BLS.norm_p2h(message)
50
- g = PointG1::BASE
51
- s = BLS.norm_p2(signature)
52
- ephm = BLS.pairing(p.negate, hm, with_final_exp: false)
53
- egs = BLS.pairing(g, s, with_final_exp: false)
67
+ unless signature.is_a?(PointG1) && public_key.is_a?(PointG2) ||
68
+ signature.is_a?(PointG2) && public_key.is_a?(PointG1)
69
+ raise BLS::Error, 'Invalid signature or public key. If the public key is PointG1, the signature must be an element of Point::G2 or vice versa.'
70
+ end
71
+ g = public_key.is_a?(PointG1) ? PointG1::BASE : PointG2::BASE
72
+ ephm = if public_key.is_a?(PointG1)
73
+ hm = BLS.norm_p2h(message)
74
+ BLS.pairing(public_key.negate, hm, with_final_exp: false)
75
+ else
76
+ hm = BLS.norm_p1h(message)
77
+ BLS.pairing(hm, public_key.negate, with_final_exp: false)
78
+ end
79
+ egs = if public_key.is_a?(PointG1)
80
+ BLS.pairing(g, signature, with_final_exp: false)
81
+ else
82
+ BLS.pairing(signature, g, with_final_exp: false)
83
+ end
54
84
  exp = (egs * ephm).final_exponentiate
55
- exp == Fq12::ONE
85
+ exp == Fp12::ONE
56
86
  end
57
87
 
58
88
  # Aggregate multiple public keys.
59
- # @param [Array[String]] public_keys the list of public keys.
60
- # @return [BLS::PointG1] aggregated public key.
89
+ # @param [Array[BLS::PointG1]|Array[BLS::PointG2]] public_keys the list of public keys.
90
+ # @return [BLS::PointG1|BLS::PointG2] aggregated public key.
61
91
  def aggregate_public_keys(public_keys)
62
92
  raise BLS::Error, 'Expected non-empty array.' if public_keys.empty?
63
-
64
- public_keys.map { |p| BLS.norm_p1(p) }.inject(PointG1::ZERO) { |sum, p| sum + p }
93
+ g1_flag = public_keys.first.is_a?(PointG1)
94
+ sum = g1_flag ? PointG1::ZERO : PointG2::ZERO
95
+ public_keys.each do |pubkey|
96
+ if g1_flag && !pubkey.is_a?(PointG1) || !g1_flag && !pubkey.is_a?(PointG2)
97
+ raise BLS::Error, 'Point G1 and G2 are mixed.'
98
+ end
99
+ sum += pubkey
100
+ end
101
+ sum
65
102
  end
66
103
 
67
104
  # Aggregate multiple signatures.
68
105
  # e(G, S) = e(G, sum(n)Si) = mul(n)(e(G, Si))
69
- # @param [Array[String|BLS::PointG2]] signatures multiple signatures.
70
- # @return [BLS::PointG2] aggregated signature.
106
+ # @param [Array[BLS::PointG2]|Array[BLS::PointG2]] signatures multiple signatures.
107
+ # @return [BLS::PointG2|BLS::PointG1] aggregated signature.
71
108
  def aggregate_signatures(signatures)
72
109
  raise BLS::Error, 'Expected non-empty array.' if signatures.empty?
73
110
 
74
- signatures.map { |s| BLS.norm_p2(s) }.inject(PointG2::ZERO) { |sum, s| sum + s }
111
+ g2_flag = signatures.first.is_a?(PointG2)
112
+ sum = g2_flag ? PointG2::ZERO : PointG1::ZERO
113
+ signatures.each do |signature|
114
+ if g2_flag && !signature.is_a?(PointG2) || !g2_flag && !signature.is_a?(PointG1)
115
+ raise BLS::Error, 'Signature G1 and G2 are mixed.'
116
+ end
117
+ sum += signature
118
+ end
119
+ sum
75
120
  end
76
121
 
77
122
  # Verify aggregated signature.
78
- # @param [BLS::PointG2] signature aggregated signature.
123
+ # @param [BLS::PointG2|BLS::PointG1] signature aggregated signature(BLS::PointG2 or BLS::PointG1).
79
124
  # @param [Array[String]] messages the list of message.
80
- # @param [Array[String|BLS::PointG1]] public_keys the list of public keys with hex or BLS::PointG1 format.
125
+ # @param [Array[BLS::PointG1]|Array[BLS::PointG2]] public_keys the list of public keys(BLS::PointG1 or BLS::PointG2).
81
126
  # @return [Boolean] verification result.
82
127
  def verify_batch(signature, messages, public_keys)
83
128
  raise BLS::Error, 'Expected non-empty array.' if messages.empty?
84
129
  raise BLS::Error, 'Public keys count should equal msg count.' unless messages.size == public_keys.size
85
130
 
86
- n_message = messages.map { |m| BLS.norm_p2h(m) }
87
- n_public_keys = public_keys.map { |p| BLS.norm_p1(p) }
131
+ sig_g2_flag = signature.is_a?(PointG2)
132
+ public_keys.each do |public_key|
133
+ if sig_g2_flag && !public_key.is_a?(PointG1) || !sig_g2_flag && !public_key.is_a?(PointG2)
134
+ raise BLS::Error, "Public key must be #{sig_g2_flag ? 'PointG1' : 'PointG2'}"
135
+ end
136
+ end
137
+
138
+ n_message = messages.map { |m| sig_g2_flag ? BLS.norm_p2h(m) : BLS.norm_p1h(m)}
88
139
  paired = []
140
+ zero = sig_g2_flag ? PointG1::ZERO : PointG2::ZERO
89
141
  n_message.each do |message|
90
- group_pubkey = n_message.each_with_index.inject(PointG1::ZERO)do|group_pubkey, (sub_message, i)|
91
- sub_message == message ? group_pubkey + n_public_keys[i] : group_pubkey
142
+ group_pubkey = n_message.each_with_index.inject(zero)do|group_pubkey, (sub_message, i)|
143
+ sub_message == message ? group_pubkey + public_keys[i] : group_pubkey
92
144
  end
93
- paired << BLS.pairing(group_pubkey, message, with_final_exp: false)
145
+ paired << (sig_g2_flag ? BLS.pairing(group_pubkey, message, with_final_exp: false) :
146
+ BLS.pairing(message, group_pubkey, with_final_exp: false))
94
147
  end
95
- sig = BLS.norm_p2(signature)
96
- paired << BLS.pairing(PointG1::BASE.negate, sig, with_final_exp: false)
97
- product = paired.inject(Fq12::ONE) { |a, b| a * b }
98
- product.final_exponentiate == Fq12::ONE
148
+ paired << (sig_g2_flag ? BLS.pairing(PointG1::BASE.negate, signature, with_final_exp: false) :
149
+ BLS.pairing(signature, PointG2::BASE.negate, with_final_exp: false))
150
+ product = paired.inject(Fp12::ONE) { |a, b| a * b }
151
+ product.final_exponentiate == Fp12::ONE
99
152
  end
100
153
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bls12-381
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shigeyuki Azuchi
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-01-16 00:00:00.000000000 Z
11
+ date: 2023-07-21 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: h2c
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.2.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.2.0
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: bundler
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -61,9 +75,12 @@ files:
61
75
  - lib/bls.rb
62
76
  - lib/bls/curve.rb
63
77
  - lib/bls/field.rb
78
+ - lib/bls/h2c.rb
64
79
  - lib/bls/math.rb
65
80
  - lib/bls/pairing.rb
66
81
  - lib/bls/point.rb
82
+ - lib/bls/point/g1.rb
83
+ - lib/bls/point/g2.rb
67
84
  - lib/bls/version.rb
68
85
  homepage: https://github.com/azuchi/bls12-381
69
86
  licenses: