bls12-381 0.2.2 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +5 -3
- data/bls12-381.gemspec +1 -1
- data/lib/bls/field.rb +163 -136
- data/lib/bls/h2c.rb +114 -0
- data/lib/bls/math.rb +4 -61
- data/lib/bls/pairing.rb +1 -1
- data/lib/bls/point/g1.rb +105 -0
- data/lib/bls/point/g2.rb +188 -0
- data/lib/bls/point.rb +13 -276
- data/lib/bls/version.rb +1 -1
- data/lib/bls.rb +89 -36
- metadata +19 -2
data/lib/bls/field.rb
CHANGED
@@ -13,10 +13,6 @@ module BLS
|
|
13
13
|
self.class.new(-value)
|
14
14
|
end
|
15
15
|
|
16
|
-
def ==(other)
|
17
|
-
value == other.value
|
18
|
-
end
|
19
|
-
|
20
16
|
def invert
|
21
17
|
x0 = 1
|
22
18
|
x1 = 0
|
@@ -75,23 +71,31 @@ module BLS
|
|
75
71
|
end
|
76
72
|
|
77
73
|
# Finite field over q.
|
78
|
-
class
|
74
|
+
class Fp
|
79
75
|
include Field
|
80
76
|
|
81
77
|
ORDER = BLS::Curve::P
|
82
78
|
MAX_BITS = Curve::P.bit_length
|
79
|
+
BYTES_LEN = (MAX_BITS / 8.0).ceil
|
83
80
|
|
84
81
|
attr_reader :value
|
85
82
|
|
86
83
|
def initialize(value)
|
87
|
-
raise ArgumentError, '
|
84
|
+
raise ArgumentError, 'value must be Integer.' unless value.is_a?(Integer)
|
88
85
|
|
89
86
|
@value = BLS.mod(value, ORDER)
|
90
87
|
end
|
91
88
|
|
92
|
-
ZERO =
|
93
|
-
ONE =
|
89
|
+
ZERO = Fp.new(0)
|
90
|
+
ONE = Fp.new(1)
|
94
91
|
|
92
|
+
def to_bytes
|
93
|
+
[to_hex].pack('H*')
|
94
|
+
end
|
95
|
+
|
96
|
+
def to_hex
|
97
|
+
value.to_s(16).rjust(2 * BYTES_LEN, '0')
|
98
|
+
end
|
95
99
|
end
|
96
100
|
|
97
101
|
# Finite field over r.
|
@@ -103,7 +107,7 @@ module BLS
|
|
103
107
|
attr_reader :value
|
104
108
|
|
105
109
|
def initialize(value)
|
106
|
-
raise ArgumentError, '
|
110
|
+
raise ArgumentError, 'value must be Integer.' unless value.is_a?(Integer)
|
107
111
|
|
108
112
|
@value = BLS.mod(value, ORDER)
|
109
113
|
end
|
@@ -111,10 +115,6 @@ module BLS
|
|
111
115
|
ZERO = Fr.new(0)
|
112
116
|
ONE = Fr.new(1)
|
113
117
|
|
114
|
-
def legendre
|
115
|
-
pow((order - 1) / 2)
|
116
|
-
end
|
117
|
-
|
118
118
|
end
|
119
119
|
|
120
120
|
# Module for a field over polynomial.
|
@@ -140,7 +140,7 @@ module BLS
|
|
140
140
|
alias - subtract
|
141
141
|
|
142
142
|
def div(other)
|
143
|
-
inv = other.is_a?(Integer) ?
|
143
|
+
inv = other.is_a?(Integer) ? Fp.new(other).invert.value : other.invert
|
144
144
|
multiply(inv)
|
145
145
|
end
|
146
146
|
alias / div
|
@@ -168,14 +168,26 @@ module BLS
|
|
168
168
|
def conjugate
|
169
169
|
self.class.new([coeffs[0], coeffs[1].negate])
|
170
170
|
end
|
171
|
+
|
172
|
+
# Convert to byte string.
|
173
|
+
# @return [String]
|
174
|
+
def to_bytes
|
175
|
+
[to_hex].pack('H*')
|
176
|
+
end
|
177
|
+
|
178
|
+
# Convert to hex string.
|
179
|
+
# @return [String]
|
180
|
+
def to_hex
|
181
|
+
coeffs.map(&:to_hex).join
|
182
|
+
end
|
171
183
|
end
|
172
184
|
|
173
185
|
# Finite extension field over irreducible polynomial.
|
174
|
-
#
|
175
|
-
class
|
186
|
+
# Fp(u) / (u^2 - β) where β = -1
|
187
|
+
class Fp2
|
176
188
|
include FQP
|
177
189
|
|
178
|
-
# For
|
190
|
+
# For Fp2 roots of unity.
|
179
191
|
RV1 = 0x6af0e0437ff400b6831e36d6bd17ffe48395dabc2d3435e77f76e17009241c5ee67992f72ec05f4c81084fbede3cc09
|
180
192
|
EV1 = 0x699be3b8c6870965e5bf892ad5d2cc7b0e85a117402dfd83b7f4a947e02d978498255a2aaec0ac627b5afbdf1bf1c90
|
181
193
|
EV2 = 0x8157cd83046453f5dd0972b6e3949e4288020b5b8a9cc99ca07e27089a2ce2436d965026adad3ef7baba37f2183e9b5
|
@@ -191,36 +203,36 @@ module BLS
|
|
191
203
|
def initialize(coeffs)
|
192
204
|
raise ArgumentError, 'Expected array with 2 elements' unless coeffs.size == 2
|
193
205
|
|
194
|
-
@coeffs = coeffs.map { |c| c.is_a?(Integer) ?
|
206
|
+
@coeffs = coeffs.map { |c| c.is_a?(Integer) ? Fp.new(c) : c }
|
195
207
|
end
|
196
208
|
|
197
|
-
ROOT =
|
198
|
-
ZERO =
|
199
|
-
ONE =
|
209
|
+
ROOT = Fp.new(-1)
|
210
|
+
ZERO = Fp2.new([0, 0])
|
211
|
+
ONE = Fp2.new([1, 0])
|
200
212
|
|
201
|
-
# Eighth roots of unity, used for computing square roots in
|
213
|
+
# Eighth roots of unity, used for computing square roots in Fp2.
|
202
214
|
ROOTS_OF_UNITY = [
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
215
|
+
Fp2.new([1, 0]),
|
216
|
+
Fp2.new([RV1, -RV1]),
|
217
|
+
Fp2.new([0, 1]),
|
218
|
+
Fp2.new([RV1, RV1]),
|
219
|
+
Fp2.new([-1, 0]),
|
220
|
+
Fp2.new([-RV1, RV1]),
|
221
|
+
Fp2.new([0, -1]),
|
222
|
+
Fp2.new([-RV1, -RV1])
|
211
223
|
].freeze
|
212
224
|
|
213
225
|
# eta values, used for computing sqrt(g(X1(t)))
|
214
226
|
ETAS = [
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
227
|
+
Fp2.new([EV1, EV2]),
|
228
|
+
Fp2.new([-EV2, EV1]),
|
229
|
+
Fp2.new([EV3, EV4]),
|
230
|
+
Fp2.new([-EV4, EV3])
|
219
231
|
].freeze
|
220
232
|
|
221
233
|
FROBENIUS_COEFFICIENTS = [
|
222
|
-
|
223
|
-
|
234
|
+
Fp.new(0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001),
|
235
|
+
Fp.new(0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaaa)
|
224
236
|
].freeze
|
225
237
|
|
226
238
|
def values
|
@@ -233,47 +245,62 @@ module BLS
|
|
233
245
|
a = c0 + c1
|
234
246
|
b = c0 - c1
|
235
247
|
c = c0 + c0
|
236
|
-
|
248
|
+
Fp2.new([a * b, c * c1])
|
249
|
+
end
|
250
|
+
|
251
|
+
def sqrt
|
252
|
+
candidate = pow((Fp2::ORDER + 8) / 16)
|
253
|
+
check = candidate.square / self
|
254
|
+
r = ROOTS_OF_UNITY
|
255
|
+
divisor = [r[0], r[2], r[4], r[6]].find { |x| x == check }
|
256
|
+
return nil unless divisor
|
257
|
+
root = r[r.index(divisor) / 2]
|
258
|
+
raise Error, 'Invalid root' unless root
|
259
|
+
x1 = candidate / root
|
260
|
+
x2 = x1.negate
|
261
|
+
re1, im1 = x1.coeffs
|
262
|
+
re2, im2 = x2.coeffs
|
263
|
+
im1.value > im2.value || (im1 == im2 && re1.value > re2.value) ? x1 : x2
|
237
264
|
end
|
238
265
|
|
239
266
|
def multiply(other)
|
240
|
-
return
|
267
|
+
return Fp2.new(coeffs.map { |c| c * other }) if other.is_a?(Integer)
|
241
268
|
|
242
269
|
c0, c1 = coeffs
|
243
270
|
r0, r1 = other.coeffs
|
244
271
|
t1 = c0 * r0
|
245
272
|
t2 = c1 * r1
|
246
|
-
|
273
|
+
Fp2.new([t1 - t2, ((c0 + c1) * (r0 + r1)) - (t1 + t2)])
|
247
274
|
end
|
248
275
|
alias * multiply
|
249
276
|
|
250
277
|
def invert
|
251
278
|
a, b = values
|
252
|
-
factor =
|
253
|
-
|
279
|
+
factor = Fp.new(a * a + b * b).invert
|
280
|
+
Fp2.new([factor * a, factor * -b])
|
254
281
|
end
|
255
282
|
|
256
283
|
# Raises to q**i -th power
|
257
284
|
def frobenius_map(power)
|
258
|
-
|
285
|
+
Fp2.new([coeffs[0], coeffs[1] * Fp2::FROBENIUS_COEFFICIENTS[power % 2]])
|
259
286
|
end
|
260
287
|
|
261
288
|
def mul_by_non_residue
|
262
289
|
c0, c1 = coeffs
|
263
|
-
|
290
|
+
Fp2.new([c0 - c1, c0 + c1])
|
264
291
|
end
|
265
292
|
|
266
293
|
def multiply_by_b
|
267
294
|
c0, c1 = coeffs
|
268
295
|
t0 = c0 * 4
|
269
296
|
t1 = c1 * 4
|
270
|
-
|
297
|
+
Fp2.new([t0 - t1, t0 + t1])
|
271
298
|
end
|
272
299
|
end
|
273
300
|
|
274
301
|
# Finite extension field over irreducible polynomial.
|
275
|
-
#
|
276
|
-
class
|
302
|
+
# Fp2(v) / (v^3 - ξ) where ξ = u + 1
|
303
|
+
class Fp6
|
277
304
|
include FQP
|
278
305
|
|
279
306
|
attr_reader :coeffs
|
@@ -285,61 +312,61 @@ module BLS
|
|
285
312
|
end
|
286
313
|
|
287
314
|
def self.from_tuple(t)
|
288
|
-
|
315
|
+
Fp6.new([Fp2.new(t[0...2]), Fp2.new(t[2...4]), Fp2.new(t[4...6])])
|
289
316
|
end
|
290
317
|
|
291
|
-
ZERO =
|
292
|
-
ONE =
|
318
|
+
ZERO = Fp6.new([Fp2::ZERO, Fp2::ZERO, Fp2::ZERO])
|
319
|
+
ONE = Fp6.new([Fp2::ONE, Fp2::ZERO, Fp2::ZERO])
|
293
320
|
|
294
321
|
FROBENIUS_COEFFICIENTS_1 = [
|
295
|
-
|
322
|
+
Fp2.new([
|
296
323
|
0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,
|
297
324
|
0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
298
325
|
]),
|
299
|
-
|
326
|
+
Fp2.new([
|
300
327
|
0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,
|
301
328
|
0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaac
|
302
329
|
]),
|
303
|
-
|
330
|
+
Fp2.new([
|
304
331
|
0x00000000000000005f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffe,
|
305
332
|
0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,
|
306
333
|
]),
|
307
|
-
|
334
|
+
Fp2.new([
|
308
335
|
0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,
|
309
336
|
0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
|
310
337
|
]),
|
311
|
-
|
338
|
+
Fp2.new([
|
312
339
|
0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaac,
|
313
340
|
0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
314
341
|
]),
|
315
|
-
|
342
|
+
Fp2.new([
|
316
343
|
0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,
|
317
344
|
0x00000000000000005f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffe
|
318
345
|
])
|
319
346
|
].freeze
|
320
347
|
|
321
348
|
FROBENIUS_COEFFICIENTS_2 = [
|
322
|
-
|
349
|
+
Fp2.new([
|
323
350
|
0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,
|
324
351
|
0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
325
352
|
]),
|
326
|
-
|
353
|
+
Fp2.new([
|
327
354
|
0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaad,
|
328
355
|
0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
329
356
|
]),
|
330
|
-
|
357
|
+
Fp2.new([
|
331
358
|
0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaac,
|
332
359
|
0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
333
360
|
]),
|
334
|
-
|
361
|
+
Fp2.new([
|
335
362
|
0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaaa,
|
336
363
|
0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
337
364
|
]),
|
338
|
-
|
365
|
+
Fp2.new([
|
339
366
|
0x00000000000000005f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffe,
|
340
367
|
0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
341
368
|
]),
|
342
|
-
|
369
|
+
Fp2.new([
|
343
370
|
0x00000000000000005f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffeffff,
|
344
371
|
0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
345
372
|
])
|
@@ -347,11 +374,11 @@ module BLS
|
|
347
374
|
|
348
375
|
# Multiply by quadratic non-residue v.
|
349
376
|
def mul_by_non_residue
|
350
|
-
|
377
|
+
Fp6.new([coeffs[2].mul_by_non_residue, coeffs[0], coeffs[1]])
|
351
378
|
end
|
352
379
|
|
353
380
|
def multiply(other)
|
354
|
-
return
|
381
|
+
return Fp6.new([coeffs[0] * other, coeffs[1] * other, coeffs[2] * other]) if other.is_a?(Integer)
|
355
382
|
|
356
383
|
c0, c1, c2 = coeffs
|
357
384
|
r0, r1, r2 = other.coeffs
|
@@ -359,7 +386,7 @@ module BLS
|
|
359
386
|
t1 = c1 * r1
|
360
387
|
t2 = c2 * r2
|
361
388
|
|
362
|
-
|
389
|
+
Fp6.new([
|
363
390
|
t0 + ((c1 + c2) * (r1 + r2) - (t1 + t2)).mul_by_non_residue,
|
364
391
|
(c0 + c1) * (r0 + r1) - (t0 + t1) + t2.mul_by_non_residue,
|
365
392
|
t1 + ((c0 + c2) * (r0 + r2) - (t0 + t2))
|
@@ -369,7 +396,7 @@ module BLS
|
|
369
396
|
|
370
397
|
# Sparse multiplication.
|
371
398
|
def multiply_by_1(b1)
|
372
|
-
|
399
|
+
Fp6.new([coeffs[2].multiply(b1).mul_by_non_residue, coeffs[0] * b1, coeffs[1] * b1])
|
373
400
|
end
|
374
401
|
|
375
402
|
# Sparse multiplication.
|
@@ -377,11 +404,11 @@ module BLS
|
|
377
404
|
c0, c1, c2 = coeffs
|
378
405
|
t0 = c0 * b0
|
379
406
|
t1 = c1 * b1
|
380
|
-
|
407
|
+
Fp6.new([((c1 + c2) * b1 - t1).mul_by_non_residue + t0, (b0 + b1) * (c0 + c1) - t0 - t1, (c0 + c2) * b0 - t0 + t1])
|
381
408
|
end
|
382
409
|
|
383
|
-
def
|
384
|
-
|
410
|
+
def multiply_by_fp2(other)
|
411
|
+
Fp6.new(coeffs.map { |c| c * other })
|
385
412
|
end
|
386
413
|
|
387
414
|
def square
|
@@ -390,7 +417,7 @@ module BLS
|
|
390
417
|
t1 = c0 * c1 * 2
|
391
418
|
t3 = c1 * c2 * 2
|
392
419
|
t4 = c2.square
|
393
|
-
|
420
|
+
Fp6.new([t3.mul_by_non_residue + t0, t4.mul_by_non_residue + t1, t1 + (c0 - c1 + c2).square + t3 - t0 - t4])
|
394
421
|
end
|
395
422
|
|
396
423
|
def invert
|
@@ -399,21 +426,21 @@ module BLS
|
|
399
426
|
t1 = c2.square.mul_by_non_residue - (c0 * c1)
|
400
427
|
t2 = c1.square - c0 * c2
|
401
428
|
t4 = ((c2 * t1 + c1 * t2).mul_by_non_residue + c0 * t0).invert
|
402
|
-
|
429
|
+
Fp6.new([t4 * t0, t4 * t1, t4 * t2])
|
403
430
|
end
|
404
431
|
|
405
432
|
def frobenius_map(power)
|
406
|
-
|
433
|
+
Fp6.new([
|
407
434
|
coeffs[0].frobenius_map(power),
|
408
|
-
coeffs[1].frobenius_map(power) *
|
409
|
-
coeffs[2].frobenius_map(power) *
|
435
|
+
coeffs[1].frobenius_map(power) * Fp6::FROBENIUS_COEFFICIENTS_1[power % 6],
|
436
|
+
coeffs[2].frobenius_map(power) * Fp6::FROBENIUS_COEFFICIENTS_2[power % 6]
|
410
437
|
])
|
411
438
|
end
|
412
439
|
end
|
413
440
|
|
414
441
|
# Finite extension field over irreducible polynomial.
|
415
|
-
#
|
416
|
-
class
|
442
|
+
# Fp6(w) / (w2 - γ) where γ = v
|
443
|
+
class Fp12
|
417
444
|
include FQP
|
418
445
|
|
419
446
|
attr_reader :coeffs
|
@@ -425,71 +452,71 @@ module BLS
|
|
425
452
|
end
|
426
453
|
|
427
454
|
def self.from_tuple(t)
|
428
|
-
|
455
|
+
Fp12.new([Fp6.from_tuple(t[0...6]), Fp6.from_tuple(t[6...12])])
|
429
456
|
end
|
430
457
|
|
431
|
-
ZERO =
|
432
|
-
ONE =
|
458
|
+
ZERO = Fp12.new([Fp6::ZERO, Fp6::ZERO])
|
459
|
+
ONE = Fp12.new([Fp6::ONE, Fp6::ZERO])
|
433
460
|
|
434
461
|
FROBENIUS_COEFFICIENTS = [
|
435
|
-
|
462
|
+
Fp2.new([
|
436
463
|
0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,
|
437
464
|
0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
438
465
|
]),
|
439
|
-
|
466
|
+
Fp2.new([
|
440
467
|
0x1904d3bf02bb0667c231beb4202c0d1f0fd603fd3cbd5f4f7b2443d784bab9c4f67ea53d63e7813d8d0775ed92235fb8,
|
441
468
|
0x00fc3e2b36c4e03288e9e902231f9fb854a14787b6c7b36fec0c8ec971f63c5f282d5ac14d6c7ec22cf78a126ddc4af3
|
442
469
|
]),
|
443
|
-
|
470
|
+
Fp2.new([
|
444
471
|
0x00000000000000005f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffeffff,
|
445
472
|
0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
446
473
|
]),
|
447
|
-
|
474
|
+
Fp2.new([
|
448
475
|
0x135203e60180a68ee2e9c448d77a2cd91c3dedd930b1cf60ef396489f61eb45e304466cf3e67fa0af1ee7b04121bdea2,
|
449
476
|
0x06af0e0437ff400b6831e36d6bd17ffe48395dabc2d3435e77f76e17009241c5ee67992f72ec05f4c81084fbede3cc09
|
450
477
|
]),
|
451
|
-
|
478
|
+
Fp2.new([
|
452
479
|
0x00000000000000005f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffe,
|
453
480
|
0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
454
481
|
]),
|
455
|
-
|
482
|
+
Fp2.new([
|
456
483
|
0x144e4211384586c16bd3ad4afa99cc9170df3560e77982d0db45f3536814f0bd5871c1908bd478cd1ee605167ff82995,
|
457
484
|
0x05b2cfd9013a5fd8df47fa6b48b1e045f39816240c0b8fee8beadf4d8e9c0566c63a3e6e257f87329b18fae980078116
|
458
485
|
]),
|
459
|
-
|
486
|
+
Fp2.new([
|
460
487
|
0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaaa,
|
461
488
|
0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
462
489
|
]),
|
463
|
-
|
490
|
+
Fp2.new([
|
464
491
|
0x00fc3e2b36c4e03288e9e902231f9fb854a14787b6c7b36fec0c8ec971f63c5f282d5ac14d6c7ec22cf78a126ddc4af3,
|
465
492
|
0x1904d3bf02bb0667c231beb4202c0d1f0fd603fd3cbd5f4f7b2443d784bab9c4f67ea53d63e7813d8d0775ed92235fb8
|
466
493
|
]),
|
467
|
-
|
494
|
+
Fp2.new([
|
468
495
|
0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaac,
|
469
496
|
0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
470
497
|
]),
|
471
|
-
|
498
|
+
Fp2.new([
|
472
499
|
0x06af0e0437ff400b6831e36d6bd17ffe48395dabc2d3435e77f76e17009241c5ee67992f72ec05f4c81084fbede3cc09,
|
473
500
|
0x135203e60180a68ee2e9c448d77a2cd91c3dedd930b1cf60ef396489f61eb45e304466cf3e67fa0af1ee7b04121bdea2
|
474
501
|
]),
|
475
|
-
|
502
|
+
Fp2.new([
|
476
503
|
0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaad,
|
477
504
|
0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
478
505
|
]),
|
479
|
-
|
506
|
+
Fp2.new([
|
480
507
|
0x05b2cfd9013a5fd8df47fa6b48b1e045f39816240c0b8fee8beadf4d8e9c0566c63a3e6e257f87329b18fae980078116,
|
481
508
|
0x144e4211384586c16bd3ad4afa99cc9170df3560e77982d0db45f3536814f0bd5871c1908bd478cd1ee605167ff82995
|
482
509
|
])
|
483
510
|
].freeze
|
484
511
|
|
485
512
|
def multiply(other)
|
486
|
-
return
|
513
|
+
return Fp12.new([coeffs[0] * other, coeffs[1] * other]) if other.is_a?(Integer)
|
487
514
|
|
488
515
|
c0, c1 = coeffs
|
489
516
|
r0, r1 = other.coeffs
|
490
517
|
t1 = c0 * r0
|
491
518
|
t2 = c1 * r1
|
492
|
-
|
519
|
+
Fp12.new([t1 + t2.mul_by_non_residue, (c0 + c1) * (r0 + r1) - (t1 + t2)])
|
493
520
|
end
|
494
521
|
alias * multiply
|
495
522
|
|
@@ -497,35 +524,35 @@ module BLS
|
|
497
524
|
c0, c1 = coeffs
|
498
525
|
t0 = c0.multiply_by_01(o0, o1)
|
499
526
|
t1 = c1.multiply_by_1(o4)
|
500
|
-
|
527
|
+
Fp12.new([t1.mul_by_non_residue + t0, (c1 + c0).multiply_by_01(o0, o1 + o4) - t0 - t1])
|
501
528
|
end
|
502
529
|
|
503
|
-
def
|
504
|
-
|
530
|
+
def multiply_by_fp2(other)
|
531
|
+
Fp12.new(coeffs.map{ |c| c.multiply_by_fp2(other) })
|
505
532
|
end
|
506
533
|
|
507
534
|
def square
|
508
535
|
c0, c1 = coeffs
|
509
536
|
ab = c0 * c1
|
510
|
-
|
537
|
+
Fp12.new([(c1.mul_by_non_residue + c0) * (c0 + c1) - ab - ab.mul_by_non_residue, ab + ab])
|
511
538
|
end
|
512
539
|
|
513
540
|
def invert
|
514
541
|
c0, c1 = coeffs
|
515
542
|
t = (c0.square - c1.square.mul_by_non_residue).invert
|
516
|
-
|
543
|
+
Fp12.new([c0 * t, (c1 * t).negate])
|
517
544
|
end
|
518
545
|
|
519
546
|
def frobenius_map(power)
|
520
547
|
c0, c1 = coeffs
|
521
548
|
r0 = c0.frobenius_map(power)
|
522
549
|
c1_0, c1_1, c1_2 = c1.frobenius_map(power).coeffs
|
523
|
-
|
550
|
+
Fp12.new([
|
524
551
|
r0,
|
525
|
-
|
526
|
-
c1_0 *
|
527
|
-
c1_1 *
|
528
|
-
c1_2 *
|
552
|
+
Fp6.new([
|
553
|
+
c1_0 * Fp12::FROBENIUS_COEFFICIENTS[power % 12],
|
554
|
+
c1_1 * Fp12::FROBENIUS_COEFFICIENTS[power % 12],
|
555
|
+
c1_2 * Fp12::FROBENIUS_COEFFICIENTS[power % 12]])])
|
529
556
|
end
|
530
557
|
|
531
558
|
def final_exponentiate
|
@@ -544,17 +571,17 @@ module BLS
|
|
544
571
|
c0, c1 = coeffs
|
545
572
|
c0c0, c0c1, c0c2 = c0.coeffs
|
546
573
|
c1c0, c1c1, c1c2 = c1.coeffs
|
547
|
-
t3, t4 =
|
548
|
-
t5, t6 =
|
549
|
-
t7, t8 =
|
574
|
+
t3, t4 = fp4_square(c0c0, c1c1)
|
575
|
+
t5, t6 = fp4_square(c1c0, c0c2)
|
576
|
+
t7, t8 = fp4_square(c0c1, c1c2)
|
550
577
|
t9 = t8.mul_by_non_residue
|
551
|
-
|
552
|
-
|
553
|
-
|
578
|
+
Fp12.new([
|
579
|
+
Fp6.new([(t3 - c0c0) * 2 + t3, (t5 - c0c1) * 2 + t5, (t7 - c0c2) * 2 + t7]),
|
580
|
+
Fp6.new([(t9 + c1c0) * 2 + t9, (t4 + c1c1) * 2 + t4, (t6 + c1c2) * 2 + t6])])
|
554
581
|
end
|
555
582
|
|
556
583
|
def cyclotomic_exp(n)
|
557
|
-
z =
|
584
|
+
z = Fp12::ONE
|
558
585
|
i = BLS_X_LEN - 1
|
559
586
|
while i >= 0
|
560
587
|
z = z.cyclotomic_square
|
@@ -566,10 +593,10 @@ module BLS
|
|
566
593
|
|
567
594
|
private
|
568
595
|
|
569
|
-
# @param [
|
570
|
-
# @param [
|
596
|
+
# @param [Fp2] a
|
597
|
+
# @param [Fp2] b
|
571
598
|
# @return [Array]
|
572
|
-
def
|
599
|
+
def fp4_square(a, b)
|
573
600
|
a2 = a.square
|
574
601
|
b2 = b.square
|
575
602
|
[b2.mul_by_non_residue + a2, (a + b).square - a2 - b2]
|
@@ -577,10 +604,10 @@ module BLS
|
|
577
604
|
|
578
605
|
end
|
579
606
|
|
580
|
-
UT_ROOT = BLS::
|
581
|
-
WSQ = BLS::
|
607
|
+
UT_ROOT = BLS::Fp6.new([BLS::Fp2::ZERO, BLS::Fp2::ONE, BLS::Fp2::ZERO])
|
608
|
+
WSQ = BLS::Fp12.new([UT_ROOT, BLS::Fp6::ZERO])
|
582
609
|
WSQ_INV = WSQ.invert
|
583
|
-
WCU = BLS::
|
610
|
+
WCU = BLS::Fp12.new([BLS::Fp6::ZERO, UT_ROOT])
|
584
611
|
WCU_INV = WCU.invert
|
585
612
|
# 1 / F2(2)^((p - 1) / 3) in GF(p^2)
|
586
613
|
PSI2_C1 = 0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaac
|
@@ -589,54 +616,54 @@ module BLS
|
|
589
616
|
P_MINUS_9_DIV_16 = (Curve::P**2 - 9) / 16
|
590
617
|
|
591
618
|
XNUM = [
|
592
|
-
|
619
|
+
Fp2.new([
|
593
620
|
0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97d6,
|
594
621
|
0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97d6]),
|
595
|
-
|
622
|
+
Fp2.new([
|
596
623
|
0x0,
|
597
624
|
0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71a]),
|
598
|
-
|
625
|
+
Fp2.new([
|
599
626
|
0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71e,
|
600
627
|
0x8ab05f8bdd54cde190937e76bc3e447cc27c3d6fbd7063fcd104635a790520c0a395554e5c6aaaa9354ffffffffe38d]),
|
601
|
-
|
628
|
+
Fp2.new([
|
602
629
|
0x171d6541fa38ccfaed6dea691f5fb614cb14b4e7f4e810aa22d6108f142b85757098e38d0f671c7188e2aaaaaaaa5ed1,
|
603
630
|
0x0])
|
604
631
|
].freeze
|
605
632
|
XDEN = [
|
606
|
-
|
633
|
+
Fp2.new([
|
607
634
|
0x0,
|
608
635
|
0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa63]),
|
609
|
-
|
636
|
+
Fp2.new([
|
610
637
|
0xc,
|
611
638
|
0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa9f]),
|
612
|
-
|
613
|
-
|
639
|
+
Fp2::ONE,
|
640
|
+
Fp2::ZERO
|
614
641
|
].freeze
|
615
642
|
YNUM = [
|
616
|
-
|
643
|
+
Fp2.new([
|
617
644
|
0x1530477c7ab4113b59a4c18b076d11930f7da5d4a07f649bf54439d87d27e500fc8c25ebf8c92f6812cfc71c71c6d706,
|
618
645
|
0x1530477c7ab4113b59a4c18b076d11930f7da5d4a07f649bf54439d87d27e500fc8c25ebf8c92f6812cfc71c71c6d706]),
|
619
|
-
|
646
|
+
Fp2.new([
|
620
647
|
0x0,
|
621
648
|
0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97be]),
|
622
|
-
|
649
|
+
Fp2.new([
|
623
650
|
0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71c,
|
624
651
|
0x8ab05f8bdd54cde190937e76bc3e447cc27c3d6fbd7063fcd104635a790520c0a395554e5c6aaaa9354ffffffffe38f]),
|
625
|
-
|
652
|
+
Fp2.new([
|
626
653
|
0x124c9ad43b6cf79bfbf7043de3811ad0761b0f37a1e26286b0e977c69aa274524e79097a56dc4bd9e1b371c71c718b10,
|
627
654
|
0x0])
|
628
655
|
].freeze
|
629
656
|
YDEN = [
|
630
|
-
|
657
|
+
Fp2.new([
|
631
658
|
0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa8fb,
|
632
659
|
0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa8fb]),
|
633
|
-
|
660
|
+
Fp2.new([
|
634
661
|
0x0,
|
635
662
|
0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa9d3]),
|
636
|
-
|
663
|
+
Fp2.new([
|
637
664
|
0x12,
|
638
665
|
0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa99]),
|
639
|
-
|
666
|
+
Fp2.new([0x1, 0x0])
|
640
667
|
].freeze
|
641
668
|
|
642
669
|
ISOGENY_COEFFICIENTS = [XNUM, XDEN, YNUM, YDEN]
|
@@ -644,8 +671,8 @@ module BLS
|
|
644
671
|
module_function
|
645
672
|
|
646
673
|
def psi(x, y)
|
647
|
-
x2 = WSQ_INV.
|
648
|
-
y2 = WCU_INV.
|
674
|
+
x2 = WSQ_INV.multiply_by_fp2(x).frobenius_map(1).multiply(WSQ).coeffs[0].coeffs[0]
|
675
|
+
y2 = WCU_INV.multiply_by_fp2(y).frobenius_map(1).multiply(WCU).coeffs[0].coeffs[0]
|
649
676
|
[x2, y2]
|
650
677
|
end
|
651
678
|
|
@@ -654,7 +681,7 @@ module BLS
|
|
654
681
|
end
|
655
682
|
|
656
683
|
def miller_loop(ell, g1)
|
657
|
-
f12 =
|
684
|
+
f12 = Fp12::ONE
|
658
685
|
p_x, p_y = g1
|
659
686
|
i = BLS_X_LEN - 2
|
660
687
|
j = 0
|
@@ -681,13 +708,13 @@ module BLS
|
|
681
708
|
sign_0 || (zero_0 && sign_1)
|
682
709
|
end
|
683
710
|
|
684
|
-
def
|
711
|
+
def sqrt_div_fp2(u, v)
|
685
712
|
uv7 = u * v**7
|
686
713
|
uv15 = uv7 * v**8
|
687
714
|
gamma = uv15**P_MINUS_9_DIV_16 * uv7
|
688
715
|
success = false
|
689
716
|
result = gamma
|
690
|
-
positive_roots_of_unity =
|
717
|
+
positive_roots_of_unity = Fp2::ROOTS_OF_UNITY[0...4]
|
691
718
|
positive_roots_of_unity.each do |root|
|
692
719
|
candidate = root * gamma
|
693
720
|
if (candidate**2 * v - u).zero? && !success
|