Implement squaring for 𝔽p6 = 𝔽p2[∛(1+𝑖)]
This commit is contained in:
parent
bde619155b
commit
03898b2292
|
@ -63,6 +63,10 @@ From Ben Edgington, https://hackmd.io/@benjaminion/bls12-381
|
||||||
Daniel V. Bailey and Christof Paar, 1998\
|
Daniel V. Bailey and Christof Paar, 1998\
|
||||||
https://www.emsec.ruhr-uni-bochum.de/media/crypto/veroeffentlichungen/2015/03/26/crypto98rc9.pdf
|
https://www.emsec.ruhr-uni-bochum.de/media/crypto/veroeffentlichungen/2015/03/26/crypto98rc9.pdf
|
||||||
|
|
||||||
|
- Asymmetric Squaring Formulae\
|
||||||
|
Jaewook Chung and M. Anwar Hasan\
|
||||||
|
http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf
|
||||||
|
|
||||||
- Multiplication and Squaring on Pairing-Friendly Fields\
|
- Multiplication and Squaring on Pairing-Friendly Fields\
|
||||||
Augusto Jun Devegili and Colm Ó hÉigeartaigh and Michael Scott and Ricardo Dahab, 2006\
|
Augusto Jun Devegili and Colm Ó hÉigeartaigh and Michael Scott and Ricardo Dahab, 2006\
|
||||||
https://eprint.iacr.org/2006/471
|
https://eprint.iacr.org/2006/471
|
||||||
|
|
|
@ -29,67 +29,6 @@ import
|
||||||
# sum(mR, a, b)
|
# sum(mR, a, b)
|
||||||
# diff(mR, a, b)
|
# diff(mR, a, b)
|
||||||
|
|
||||||
# ############################################################
|
|
||||||
#
|
|
||||||
# Quadratic Extension fields
|
|
||||||
#
|
|
||||||
# ############################################################
|
|
||||||
|
|
||||||
type
|
|
||||||
QuadExtAddGroup* = concept x
|
|
||||||
## Quadratic extension fields - Abelian Additive Group concept
|
|
||||||
type BaseField = auto
|
|
||||||
x.c0 is BaseField
|
|
||||||
x.c1 is BaseField
|
|
||||||
|
|
||||||
func `==`*(a, b: QuadExtAddGroup): CTBool[Word] =
|
|
||||||
## Constant-time equality check
|
|
||||||
(a.c0 == b.c0) and (a.c1 == b.c1)
|
|
||||||
|
|
||||||
func setZero*(a: var QuadExtAddGroup) =
|
|
||||||
## Set ``a`` to zero in the extension field
|
|
||||||
## Coordinates 0 + 0 𝛼
|
|
||||||
## with 𝛼 the solution of f(x) = x² - µ = 0
|
|
||||||
a.c0.setZero()
|
|
||||||
a.c1.setZero()
|
|
||||||
|
|
||||||
func setOne*(a: var QuadExtAddGroup) =
|
|
||||||
## Set ``a`` to one in the extension field
|
|
||||||
## Coordinates 1 + 0 𝛼
|
|
||||||
## with 𝛼 the solution of f(x) = x² - µ = 0
|
|
||||||
a.c0.setOne()
|
|
||||||
a.c1.setZero()
|
|
||||||
|
|
||||||
func `+=`*(a: var QuadExtAddGroup, b: QuadExtAddGroup) =
|
|
||||||
## Addition in the extension field
|
|
||||||
a.c0 += b.c0
|
|
||||||
a.c1 += b.c1
|
|
||||||
|
|
||||||
func `-=`*(a: var QuadExtAddGroup, b: QuadExtAddGroup) =
|
|
||||||
## Substraction in the extension field
|
|
||||||
a.c0 -= b.c0
|
|
||||||
a.c1 -= b.c1
|
|
||||||
|
|
||||||
func double*(r: var QuadExtAddGroup, a: QuadExtAddGroup) =
|
|
||||||
## Double in the extension field
|
|
||||||
r.c0.double(a.c0)
|
|
||||||
r.c1.double(a.c1)
|
|
||||||
|
|
||||||
func sum*(r: var QuadExtAddGroup, a, b: QuadExtAddGroup) =
|
|
||||||
## Sum ``a`` and ``b`` into r
|
|
||||||
r.c0.sum(a.c0, b.c0)
|
|
||||||
r.c1.sum(a.c1, b.c1)
|
|
||||||
|
|
||||||
func diff*(r: var QuadExtAddGroup, a, b: QuadExtAddGroup) =
|
|
||||||
## Difference of ``a`` by `b`` into r
|
|
||||||
r.c0.diff(a.c0, b.c0)
|
|
||||||
r.c1.diff(a.c1, b.c1)
|
|
||||||
|
|
||||||
func neg*(r: var QuadExtAddGroup, a: QuadExtAddGroup) =
|
|
||||||
## Negate ``a`` into ``r``
|
|
||||||
r.c0.neg(a.c0)
|
|
||||||
r.c1.neg(a.c1)
|
|
||||||
|
|
||||||
# ############################################################
|
# ############################################################
|
||||||
#
|
#
|
||||||
# Cubic Extension fields
|
# Cubic Extension fields
|
||||||
|
@ -142,6 +81,12 @@ func double*(r: var CubicExtAddGroup, a: CubicExtAddGroup) =
|
||||||
r.c1.double(a.c1)
|
r.c1.double(a.c1)
|
||||||
r.c2.double(a.c2)
|
r.c2.double(a.c2)
|
||||||
|
|
||||||
|
func double*(a: var CubicExtAddGroup) =
|
||||||
|
## Double in the extension field
|
||||||
|
double(a.c0)
|
||||||
|
double(a.c1)
|
||||||
|
double(a.c2)
|
||||||
|
|
||||||
func sum*(r: var CubicExtAddGroup, a, b: CubicExtAddGroup) =
|
func sum*(r: var CubicExtAddGroup, a, b: CubicExtAddGroup) =
|
||||||
## Sum ``a`` and ``b`` into r
|
## Sum ``a`` and ``b`` into r
|
||||||
r.c0.sum(a.c0, b.c0)
|
r.c0.sum(a.c0, b.c0)
|
||||||
|
@ -153,3 +98,70 @@ func diff*(r: var CubicExtAddGroup, a, b: CubicExtAddGroup) =
|
||||||
r.c0.diff(a.c0, b.c0)
|
r.c0.diff(a.c0, b.c0)
|
||||||
r.c1.diff(a.c1, b.c1)
|
r.c1.diff(a.c1, b.c1)
|
||||||
r.c2.diff(a.c2, b.c2)
|
r.c2.diff(a.c2, b.c2)
|
||||||
|
|
||||||
|
# ############################################################
|
||||||
|
#
|
||||||
|
# Quadratic Extension fields
|
||||||
|
#
|
||||||
|
# ############################################################
|
||||||
|
|
||||||
|
type
|
||||||
|
QuadExtAddGroup* = concept x
|
||||||
|
## Quadratic extension fields - Abelian Additive Group concept
|
||||||
|
not(x is CubicExtAddGroup)
|
||||||
|
type BaseField = auto
|
||||||
|
x.c0 is BaseField
|
||||||
|
x.c1 is BaseField
|
||||||
|
|
||||||
|
func `==`*(a, b: QuadExtAddGroup): CTBool[Word] =
|
||||||
|
## Constant-time equality check
|
||||||
|
(a.c0 == b.c0) and (a.c1 == b.c1)
|
||||||
|
|
||||||
|
func setZero*(a: var QuadExtAddGroup) =
|
||||||
|
## Set ``a`` to zero in the extension field
|
||||||
|
## Coordinates 0 + 0 𝛼
|
||||||
|
## with 𝛼 the solution of f(x) = x² - µ = 0
|
||||||
|
a.c0.setZero()
|
||||||
|
a.c1.setZero()
|
||||||
|
|
||||||
|
func setOne*(a: var QuadExtAddGroup) =
|
||||||
|
## Set ``a`` to one in the extension field
|
||||||
|
## Coordinates 1 + 0 𝛼
|
||||||
|
## with 𝛼 the solution of f(x) = x² - µ = 0
|
||||||
|
a.c0.setOne()
|
||||||
|
a.c1.setZero()
|
||||||
|
|
||||||
|
func `+=`*(a: var QuadExtAddGroup, b: QuadExtAddGroup) =
|
||||||
|
## Addition in the extension field
|
||||||
|
a.c0 += b.c0
|
||||||
|
a.c1 += b.c1
|
||||||
|
|
||||||
|
func `-=`*(a: var QuadExtAddGroup, b: QuadExtAddGroup) =
|
||||||
|
## Substraction in the extension field
|
||||||
|
a.c0 -= b.c0
|
||||||
|
a.c1 -= b.c1
|
||||||
|
|
||||||
|
func double*(r: var QuadExtAddGroup, a: QuadExtAddGroup) =
|
||||||
|
## Double in the extension field
|
||||||
|
r.c0.double(a.c0)
|
||||||
|
r.c1.double(a.c1)
|
||||||
|
|
||||||
|
func double*(a: var QuadExtAddGroup) =
|
||||||
|
## Double in the extension field
|
||||||
|
double(a.c0)
|
||||||
|
double(a.c1)
|
||||||
|
|
||||||
|
func sum*(r: var QuadExtAddGroup, a, b: QuadExtAddGroup) =
|
||||||
|
## Sum ``a`` and ``b`` into r
|
||||||
|
r.c0.sum(a.c0, b.c0)
|
||||||
|
r.c1.sum(a.c1, b.c1)
|
||||||
|
|
||||||
|
func diff*(r: var QuadExtAddGroup, a, b: QuadExtAddGroup) =
|
||||||
|
## Difference of ``a`` by `b`` into r
|
||||||
|
r.c0.diff(a.c0, b.c0)
|
||||||
|
r.c1.diff(a.c1, b.c1)
|
||||||
|
|
||||||
|
func neg*(r: var QuadExtAddGroup, a: QuadExtAddGroup) =
|
||||||
|
## Negate ``a`` into ``r``
|
||||||
|
r.c0.neg(a.c0)
|
||||||
|
r.c1.neg(a.c1)
|
||||||
|
|
|
@ -61,7 +61,7 @@ type
|
||||||
c0*, c1*: Fp[C]
|
c0*, c1*: Fp[C]
|
||||||
|
|
||||||
func square*(r: var Fp2, a: Fp2) =
|
func square*(r: var Fp2, a: Fp2) =
|
||||||
## Return a^2 in 𝔽p2 = 𝔽p[𝑖] in ``r``
|
## Return a² in 𝔽p2 = 𝔽p[𝑖] in ``r``
|
||||||
## ``r`` is initialized/overwritten
|
## ``r`` is initialized/overwritten
|
||||||
# (c0, c1)² => (c0 + c1𝑖)²
|
# (c0, c1)² => (c0 + c1𝑖)²
|
||||||
# => c0² + 2 c0 c1𝑖 + (c1𝑖)²
|
# => c0² + 2 c0 c1𝑖 + (c1𝑖)²
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
# Constantine
|
||||||
|
# Copyright (c) 2018-2019 Status Research & Development GmbH
|
||||||
|
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
|
||||||
|
# Licensed and distributed under either of
|
||||||
|
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
|
||||||
|
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
|
||||||
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
|
# ############################################################
|
||||||
|
#
|
||||||
|
# Cubic Extension field over base field 𝔽p2
|
||||||
|
# 𝔽p6 = 𝔽p2[∛(1 + 𝑖)]
|
||||||
|
#
|
||||||
|
# ############################################################
|
||||||
|
|
||||||
|
# This implements a quadratic extension field over 𝔽p2 = 𝔽p[𝑖]
|
||||||
|
# the base field 𝔽p:
|
||||||
|
# 𝔽p6 = 𝔽p2[∛(1 + 𝑖)]
|
||||||
|
# with element A of coordinates (a0, a1) represented
|
||||||
|
# by a0 + a1 ξ + a2 ξ²
|
||||||
|
#
|
||||||
|
# The irreducible polynomial chosen is
|
||||||
|
# x³ - ξ with ξ = 𝑖+1
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Consequently, for this file Fp2 to be valid
|
||||||
|
# 𝑖+1 MUST not be a square in 𝔽p2
|
||||||
|
|
||||||
|
import
|
||||||
|
../arithmetic,
|
||||||
|
../config/curves,
|
||||||
|
./abelian_groups,
|
||||||
|
./fp2_complex
|
||||||
|
|
||||||
|
type
|
||||||
|
Fp6*[C: static Curve] = object
|
||||||
|
## Element of the extension field
|
||||||
|
## 𝔽p6 = 𝔽p2[∛(1 + 𝑖)]
|
||||||
|
##
|
||||||
|
## with coordinates (c0, c1, c2) such as
|
||||||
|
## c0 + c1 ξ + c2 ξ²
|
||||||
|
##
|
||||||
|
## This requires 1 + 𝑖 to not be a cube in 𝔽p2
|
||||||
|
c0*, c1*, c2*: Fp2[C]
|
||||||
|
|
||||||
|
Xi = object
|
||||||
|
## ξ (Xi) the cubic non-residue
|
||||||
|
|
||||||
|
func `*`(_: typedesc[Xi], a: Fp2): Fp2 =
|
||||||
|
## Multiply an element of 𝔽p2 by 𝔽p6 cubic non-residue 1 + 𝑖
|
||||||
|
## (c0 + c1 𝑖) (1 + 𝑖) => c0 + (c0 + c1)𝑖 + c1 𝑖²
|
||||||
|
## => c0 - c1 + (c0 + c1) 𝑖
|
||||||
|
result.c0 = a.c0 - a.c1
|
||||||
|
result.c1 = a.c0 + a.c1
|
||||||
|
|
||||||
|
template `*`(a: Fp2, _: typedesc[Xi]): Fp2 =
|
||||||
|
Xi * a
|
||||||
|
|
||||||
|
func square*[C](r: var Fp6[C], a: Fp6[C]) =
|
||||||
|
## Return a²
|
||||||
|
##
|
||||||
|
# Algorithm is Chung-Hasan Squaring SQR3
|
||||||
|
# http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf
|
||||||
|
var v2{.noInit.}, v3{.noInit.}, v4{.noInit.}, v5{.noInit.}: Fp2[C]
|
||||||
|
|
||||||
|
v4.prod(a.c0, a.c1)
|
||||||
|
v4.double()
|
||||||
|
v5.square(a.c2)
|
||||||
|
r.c1 = Xi * v5
|
||||||
|
r.c1 += v4
|
||||||
|
v2.diff(v4, v5)
|
||||||
|
v3.square(a.c0)
|
||||||
|
v4.diff(a.c0, a.c1)
|
||||||
|
v4 += a.c2
|
||||||
|
v5.prod(a.c1, a.c2)
|
||||||
|
v5.double()
|
||||||
|
v4.square(v4)
|
||||||
|
r.c0 = Xi * v5
|
||||||
|
r.c0 += v3
|
||||||
|
r.c2.sum(v2, v4)
|
||||||
|
r.c2 += v5
|
||||||
|
r.c2 -= v3
|
|
@ -0,0 +1,133 @@
|
||||||
|
# Constantine
|
||||||
|
# Copyright (c) 2018-2019 Status Research & Development GmbH
|
||||||
|
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
|
||||||
|
# Licensed and distributed under either of
|
||||||
|
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
|
||||||
|
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
|
||||||
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
|
import
|
||||||
|
# Standard library
|
||||||
|
unittest, times, random,
|
||||||
|
# Internals
|
||||||
|
../constantine/tower_field_extensions/[abelian_groups, fp6_1_plus_i],
|
||||||
|
../constantine/config/[common, curves],
|
||||||
|
../constantine/arithmetic,
|
||||||
|
# Test utilities
|
||||||
|
../helpers/prng
|
||||||
|
|
||||||
|
const Iters = 128
|
||||||
|
|
||||||
|
var rng: RngState
|
||||||
|
let seed = uint32(getTime().toUnix() and (1'i64 shl 32 - 1)) # unixTime mod 2^32
|
||||||
|
rng.seed(seed)
|
||||||
|
echo "test_fp6 xoshiro512** seed: ", seed
|
||||||
|
|
||||||
|
# Import: wrap in field element tests in small procedures
|
||||||
|
# otherwise they will become globals,
|
||||||
|
# and will create binary size issues.
|
||||||
|
# Also due to Nim stack scanning,
|
||||||
|
# having too many elements on the stack (a couple kB)
|
||||||
|
# will significantly slow down testing (100x is possible)
|
||||||
|
|
||||||
|
suite "𝔽p6 = 𝔽p2[∛(1+𝑖)] (irreducible polynomial x³ - (1+𝑖))":
|
||||||
|
test "Squaring 1 returns 1":
|
||||||
|
template test(C: static Curve) =
|
||||||
|
block:
|
||||||
|
proc testInstance() =
|
||||||
|
let One = block:
|
||||||
|
var O{.noInit.}: Fp6[C]
|
||||||
|
O.setOne()
|
||||||
|
O
|
||||||
|
block:
|
||||||
|
var r{.noinit.}: Fp6[C]
|
||||||
|
r.square(One)
|
||||||
|
check: bool(r == One)
|
||||||
|
# block:
|
||||||
|
# var r{.noinit.}: Fp6[C]
|
||||||
|
# r.prod(One, One)
|
||||||
|
# check: bool(r == One)
|
||||||
|
|
||||||
|
testInstance()
|
||||||
|
|
||||||
|
test(BN254)
|
||||||
|
test(BLS12_381)
|
||||||
|
|
||||||
|
test "Squaring 2 returns 4":
|
||||||
|
template test(C: static Curve) =
|
||||||
|
block:
|
||||||
|
proc testInstance() =
|
||||||
|
let One = block:
|
||||||
|
var O{.noInit.}: Fp6[C]
|
||||||
|
O.setOne()
|
||||||
|
O
|
||||||
|
|
||||||
|
var Two: Fp6[C]
|
||||||
|
Two.double(One)
|
||||||
|
|
||||||
|
var Four: Fp6[C]
|
||||||
|
Four.double(Two)
|
||||||
|
|
||||||
|
var r: Fp6[C]
|
||||||
|
r.square(Two)
|
||||||
|
|
||||||
|
check: bool(r == Four)
|
||||||
|
|
||||||
|
testInstance()
|
||||||
|
|
||||||
|
test(BN254)
|
||||||
|
test(BLS12_381)
|
||||||
|
|
||||||
|
test "Squaring 3 returns 9":
|
||||||
|
template test(C: static Curve) =
|
||||||
|
block:
|
||||||
|
proc testInstance() =
|
||||||
|
let One = block:
|
||||||
|
var O{.noInit.}: Fp6[C]
|
||||||
|
O.setOne()
|
||||||
|
O
|
||||||
|
|
||||||
|
var Three: Fp6[C]
|
||||||
|
for _ in 0 ..< 3:
|
||||||
|
Three += One
|
||||||
|
|
||||||
|
var Nine: Fp6[C]
|
||||||
|
for _ in 0 ..< 9:
|
||||||
|
Nine += One
|
||||||
|
|
||||||
|
var u: Fp6[C]
|
||||||
|
u.square(Three)
|
||||||
|
|
||||||
|
check: bool(u == Nine)
|
||||||
|
|
||||||
|
testInstance()
|
||||||
|
|
||||||
|
test(BN254)
|
||||||
|
test(BLS12_381)
|
||||||
|
|
||||||
|
test "Squaring -3 returns 9":
|
||||||
|
template test(C: static Curve) =
|
||||||
|
block:
|
||||||
|
proc testInstance() =
|
||||||
|
let One = block:
|
||||||
|
var O{.noInit.}: Fp6[C]
|
||||||
|
O.setOne()
|
||||||
|
O
|
||||||
|
|
||||||
|
var MinusThree: Fp6[C]
|
||||||
|
for _ in 0 ..< 3:
|
||||||
|
MinusThree -= One
|
||||||
|
|
||||||
|
var Nine: Fp6[C]
|
||||||
|
for _ in 0 ..< 9:
|
||||||
|
Nine += One
|
||||||
|
|
||||||
|
var u: Fp6[C]
|
||||||
|
u.square(MinusThree)
|
||||||
|
|
||||||
|
check: bool(u == Nine)
|
||||||
|
|
||||||
|
testInstance()
|
||||||
|
|
||||||
|
test(BN254)
|
||||||
|
test(BLS12_381)
|
Loading…
Reference in New Issue