diff --git a/constantine/lowlevel_bigints.nim b/constantine/lowlevel_bigints.nim index 50e58eaa..07cea40c 100644 --- a/constantine/lowlevel_bigints.nim +++ b/constantine/lowlevel_bigints.nim @@ -8,7 +8,8 @@ import ./platforms/abstractions, - ./math/io/io_bigints + ./math/io/io_bigints, + ./math/arithmetic/bigints # ############################################################ # @@ -32,7 +33,7 @@ export abstractions.SecretWord, abstractions.BigInt -# BigInt +# BigInt serialization # ------------------------------------------------------------ func unmarshalBE*(dst: var BigInt, src: openarray[byte]): bool = @@ -44,3 +45,26 @@ func marshalBE*(dst: var openarray[byte], src: BigInt): bool = ## Return true on success ## Return false if destination is too small compared to source return dst.marshal(src, bigEndian) + +# BigInt +# ------------------------------------------------------------ + +export bigints.setZero +export bigints.setOne + +export bigints.`<` +export bigints.`<=` +export bigints.isOdd +export bigints.isEven + +export bigints.add +export bigints.cadd +export bigints.sub +export bigints.csub + +export bigints.reduce +export bigints.reduce_vartime +export bigints.invmod +export bigints.invmod_vartime + +export bigints.bit0 diff --git a/constantine/lowlevel_fields.nim b/constantine/lowlevel_fields.nim index 14dc1c6a..b20554ec 100644 --- a/constantine/lowlevel_fields.nim +++ b/constantine/lowlevel_fields.nim @@ -34,7 +34,11 @@ export abstractions.SecretWord, abstractions.BigInt, algebras.Algebra, - algebras.getBigInt + algebras.getBigInt, + algebras.bits, + algebras.baseFieldModulus, + algebras.scalarFieldModulus + # Scalar field Fr and Prime Field Fp # ------------------------------------------------------------ @@ -42,7 +46,11 @@ export export algebras.Fp, algebras.Fr, - algebras.FF + algebras.FF, + + # Workaround generic sandwich + algebras.matchingBigInt, + algebras.matchingOrderBigInt func unmarshalBE*(dst: var FF, src: openarray[byte]): bool = ## Return true on success @@ -112,6 +120,8 @@ export arithmetic.sqrt_if_square export arithmetic.invsqrt_if_square export arithmetic.sqrt_ratio_if_square +export arithmetic.pow +export arithmetic.pow_vartime # Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers # tend to generate useless memory moves or have difficulties to minimize stack allocation @@ -122,3 +132,6 @@ export arithmetic.sqrt_ratio_if_square export arithmetic.`+` export arithmetic.`-` export arithmetic.`*` +export arithmetic.`^` +export arithmetic.`~^` +export arithmetic.toBig diff --git a/constantine/lowlevel_pairing_curves.nim b/constantine/lowlevel_pairing_curves.nim index 19c53ff2..47458191 100644 --- a/constantine/lowlevel_pairing_curves.nim +++ b/constantine/lowlevel_pairing_curves.nim @@ -14,6 +14,7 @@ import ./math/pairings/[ cyclotomic_subgroups, lines_eval, + miller_accumulators, pairings_generic, gt_exponentiations, gt_exponentiations_vartime] @@ -51,6 +52,13 @@ export lines_eval.line_add export lines_eval.mul_by_line export lines_eval.mul_by_2_lines +export miller_accumulators.MillerAccumulator +export miller_accumulators.init +export miller_accumulators.update +export miller_accumulators.handover +export miller_accumulators.merge +export miller_accumulators.finish + export cyclotomic_subgroups.finalExpEasy export cyclotomic_subgroups.cyclotomic_inv export cyclotomic_subgroups.cyclotomic_square diff --git a/constantine/math/arithmetic/bigints.nim b/constantine/math/arithmetic/bigints.nim index 458559fd..3c07bc5c 100644 --- a/constantine/math/arithmetic/bigints.nim +++ b/constantine/math/arithmetic/bigints.nim @@ -520,7 +520,7 @@ func invmod*[bits](r: var BigInt[bits], a, M: BigInt[bits]) = {.push inline.} -func reduce_vartime*[aBits, mBits](r: var BigInt[mBits], a: BigInt[aBits], M: BigInt[mBits]): bool = +func reduce_vartime*[aBits, mBits](r: var BigInt[mBits], a: BigInt[aBits], M: BigInt[mBits]): bool {.discardable.} = ## Reduce `a` modulo `M` and store the result in `r` ## Return false if M == 0 return reduce_vartime(r.limbs, a.limbs, M.limbs) diff --git a/constantine/math/arithmetic/finite_fields.nim b/constantine/math/arithmetic/finite_fields.nim index 25dab2f6..692baf0d 100644 --- a/constantine/math/arithmetic/finite_fields.nim +++ b/constantine/math/arithmetic/finite_fields.nim @@ -529,6 +529,23 @@ func pow*(a: var FF, exponent: openarray[byte]) = FF.getSpareBits() ) +func pow*(a: var FF, exponent: FF) = + ## Exponentiation modulo p + ## ``a``: a field element to be exponentiated + ## ``exponent``: a finite field element + const windowSize = 5 # TODO: find best window size for each curves + a.pow(exponent.toBig()) + +func pow*(r: var FF, a: FF, exponent: BigInt or openArray[byte] or FF) = + ## Exponentiation modulo p + ## ``a``: a field element to be exponentiated + ## ``exponent``: a finite field element or big integer + r = a + a.pow(exponent) + +# Vartime exponentiation +# ------------------------------------------------------------------- + func pow_vartime*(a: var FF, exponent: BigInt) = ## Exponentiation modulo p ## ``a``: a field element to be exponentiated @@ -567,6 +584,23 @@ func pow_vartime*(a: var FF, exponent: openarray[byte]) = FF.getSpareBits() ) +func pow_vartime*(a: var FF, exponent: FF) = + ## Exponentiation modulo p + ## ``a``: a field element to be exponentiated + ## ``exponent``: a finite field element + const windowSize = 5 # TODO: find best window size for each curves + a.pow_vartime(exponent.toBig()) + +func pow_vartime*(r: var FF, a: FF, exponent: BigInt or openArray[byte] or FF) = + ## Exponentiation modulo p + ## ``a``: a field element to be exponentiated + ## ``exponent``: a finite field element or big integer + r = a + a.pow_vartime(exponent) + +# Small vartime exponentiation +# ------------------------------------------------------------------- + func pow_squareMultiply_vartime(a: var FF, exponent: SomeUnsignedInt) {.tags:[VarTime], meter.} = ## **Variable-time** Exponentiation ## @@ -905,7 +939,7 @@ func `+`*(a, b: FF): FF {.noInit, inline.} = result.sum(a, b) func `-`*(a, b: FF): FF {.noInit, inline.} = - ## Finite Field addition + ## Finite Field substraction ## ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers ## tend to generate useless memory moves or have difficulties to minimize stack allocation @@ -914,10 +948,28 @@ func `-`*(a, b: FF): FF {.noInit, inline.} = result.diff(a, b) func `*`*(a, b: FF): FF {.noInit, inline.} = - ## Finite Field substraction + ## Finite Field multiplication ## ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers ## tend to generate useless memory moves or have difficulties to minimize stack allocation ## and our types might be large (Fp12 ...) ## See: https://github.com/mratsim/constantine/issues/145 result.prod(a, b) + +func `^`*(a: FF, b: FF or BigInt or openArray[byte]): FF {.noInit, inline.} = + ## Finite Field exponentiation + ## + ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers + ## tend to generate useless memory moves or have difficulties to minimize stack allocation + ## and our types might be large (Fp12 ...) + ## See: https://github.com/mratsim/constantine/issues/145 + result.pow(a, b) + +func `~^`*(a: FF, b: FF or BigInt or openArray[byte]): FF {.noInit, inline.} = + ## Finite Field vartime exponentiation + ## + ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers + ## tend to generate useless memory moves or have difficulties to minimize stack allocation + ## and our types might be large (Fp12 ...) + ## See: https://github.com/mratsim/constantine/issues/145 + result.pow_vartime(a, b) diff --git a/constantine/math/elliptic/ec_scalar_mul.nim b/constantine/math/elliptic/ec_scalar_mul.nim index 76acedae..e2a4f40f 100644 --- a/constantine/math/elliptic/ec_scalar_mul.nim +++ b/constantine/math/elliptic/ec_scalar_mul.nim @@ -278,7 +278,10 @@ func scalarMulEndo*[scalBits; EC]( ## Requires: ## - Cofactor to be cleared ## - 0 <= scalar < curve order - static: doAssert scalBits <= EC.getScalarField().bits(), "Do not use endomorphism to multiply beyond the curve order" + static: doAssert scalBits <= EC.getScalarField().bits(), block: + "Do not use endomorphism to multiply beyond the curve order:\n" & + " scalar: " & $scalBits & "-bit\n" & + " order: " & $EC.getScalarField().bits() & "-bit\n" # 1. Compute endomorphisms const M = when P.F is Fp: 2 @@ -368,7 +371,11 @@ func scalarMulGLV_m2w2*[scalBits; EC](P0: var EC, scalar: BigInt[scalBits]) {.me ## Requires: ## - Cofactor to be cleared ## - 0 <= scalar < curve order - static: doAssert: scalBits <= EC.getScalarField().bits() + static: doAssert scalBits <= EC.getScalarField().bits(), block: + "Do not use endomorphism to multiply beyond the curve order:\n" & + " scalar: " & $scalBits & "-bit\n" & + " order: " & $EC.getScalarField().bits() & "-bit\n" + const G = when EC isnot EC_ShortW_Aff|EC_ShortW_Jac|EC_ShortW_Prj: G1 else: EC.G diff --git a/constantine/math/pairings/gt_exponentiations.nim b/constantine/math/pairings/gt_exponentiations.nim index 3c1f9b2c..3b66eaff 100644 --- a/constantine/math/pairings/gt_exponentiations.nim +++ b/constantine/math/pairings/gt_exponentiations.nim @@ -53,7 +53,10 @@ func gtExpEndo*[Gt: ExtensionField, scalBits: static int]( ## Requires: ## - Cofactor to be cleared ## - 0 <= scalar < curve order - static: doAssert scalBits <= Fr[Gt.Name].bits(), "Do not use endomorphism to multiply beyond the curve order" + static: doAssert scalBits <= Fr[Gt.Name].bits(), block: + "Do not use endomorphism to multiply beyond the curve order:\n" & + " scalar: " & $scalBits & "-bit\n" & + " order: " & $Fr[Gt.Name].bits() & "-bit\n" # 1. Compute endomorphisms const M = when Gt is Fp6: 2 diff --git a/constantine/named/properties_curves.nim b/constantine/named/properties_curves.nim index 30c303f6..e73c88ff 100644 --- a/constantine/named/properties_curves.nim +++ b/constantine/named/properties_curves.nim @@ -34,9 +34,9 @@ template getBigInt*(Name: static Algebra, kind: static FieldKind): untyped = # # and `ptr UncheckedArray[BigInt[Fr[EC.F.Name].bits]]` gets undeclared field: 'Name' when kind == kBaseField: - BigInt[Fp[Name].bits()] + Name.baseFieldModulus().typeof() else: - BigInt[Fr[Name].bits()] + Name.scalarFieldModulus().typeof() template getField*(Name: static Algebra, kind: static FieldKind): untyped = when kind == kBaseField: diff --git a/constantine/platforms/allocs.nim b/constantine/platforms/allocs.nim index 18913aa5..3e2cb97f 100644 --- a/constantine/platforms/allocs.nim +++ b/constantine/platforms/allocs.nim @@ -80,7 +80,8 @@ template allocStackUnchecked*(T: typedesc, size: int): ptr T = cast[ptr T](alloca(size)) template allocStackArray*(T: typedesc, len: SomeInteger): ptr UncheckedArray[T] = - cast[ptr UncheckedArray[T]](alloca(sizeof(T) * cast[int](len))) + {.warning[CastSizes]:off.}: + cast[ptr UncheckedArray[T]](alloca(sizeof(T) * cast[int](len))) # Heap allocation # ---------------------------------------------------------------------------------- @@ -93,7 +94,8 @@ proc allocHeapUnchecked*(T: typedesc, size: int): ptr T {.inline.} = cast[type result](malloc(size)) proc allocHeapArray*(T: typedesc, len: SomeInteger): ptr UncheckedArray[T] {.inline.} = - cast[type result](malloc(sizeof(T) * cast[int](len))) + {.warning[CastSizes]:off.}: + cast[type result](malloc(sizeof(T) * cast[int](len))) proc freeHeap*(p: pointer) {.inline.} = free(p) @@ -131,4 +133,4 @@ proc allocHeapUncheckedAlignedPtr*(T: typedesc[ptr], size: int, alignment: stati allocHeapUncheckedAligned(typeof(default(T)[]), size, alignment) proc freeHeapAligned*(p: pointer) {.inline.} = - aligned_free(p) \ No newline at end of file + aligned_free(p)