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\
|
||||
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\
|
||||
Augusto Jun Devegili and Colm Ó hÉigeartaigh and Michael Scott and Ricardo Dahab, 2006\
|
||||
https://eprint.iacr.org/2006/471
|
||||
|
|
|
@ -29,67 +29,6 @@ import
|
|||
# sum(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
|
||||
|
@ -142,6 +81,12 @@ func double*(r: var CubicExtAddGroup, a: CubicExtAddGroup) =
|
|||
r.c1.double(a.c1)
|
||||
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) =
|
||||
## Sum ``a`` and ``b`` into r
|
||||
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.c1.diff(a.c1, b.c1)
|
||||
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]
|
||||
|
||||
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
|
||||
# (c0, c1)² => (c0 + 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