diff --git a/constantine/bigints.nim b/constantine/bigints.nim index d585bb0..1705292 100644 --- a/constantine/bigints.nim +++ b/constantine/bigints.nim @@ -39,16 +39,16 @@ import ./word_types -type Limb* = Ct[uint64] -const LimbBitSize* = sizeof(Limb) * 8 - 1 +type Word* = Ct[uint64] +const WordBitSize* = sizeof(Word) * 8 - 1 ## Limbs are 63-bit by default func words_required(bits: static int): static int = - (bits + LimbBitSize - 1) div LimbBitSize + (bits + WordBitSize - 1) div WordBitSize type BigInt*[bits: static int] = object - limbs*: array[bits.words_required, Limb] + limbs*: array[bits.words_required, Word] const HighLimb* = (not Ct[uint64](0)) shr 1 ## This represents 0x7F_FF_FF_FF__FF_FF_FF_FF @@ -56,7 +56,7 @@ const HighLimb* = (not Ct[uint64](0)) shr 1 ## This biggest representable number in our limbs. ## i.e. The most significant bit is never set at the end of each function -template `[]`*(a: Bigint, idx: int): Limb = +template `[]`*(a: Bigint, idx: int): Word = a.limbs[idx] # ############################################################ @@ -75,38 +75,38 @@ template `[]`*(a: Bigint, idx: int): Limb = # We don't specialise for the control word, any optimizing compiler # will keep it in registers. -template addImpl[bits](result: CTBool[Limb], a: var BigInt[bits], b: BigInt[bits], ctl: CTBool[Limb]) = +template addImpl[bits](result: CTBool[Word], a: var BigInt[bits], b: BigInt[bits], ctl: CTBool[Word]) = ## Constant-time big integer in-place addition ## Returns if addition carried for i in static(0 ..< a.limbs.len): - let new_a = a.limbs[i] + b.limbs[i] + Limb(result) + let new_a = a.limbs[i] + b.limbs[i] + Word(result) result = new_a.isMsbSet() a[i] = ctl.mux(new_a and HighLimb, a) -func add*[bits](a: var BigInt[bits], b: BigInt[bits], ctl: CTBool[Limb]): CTBool[Limb] = +func add*[bits](a: var BigInt[bits], b: BigInt[bits], ctl: CTBool[Word]): CTBool[Word] = ## Constant-time big integer in-place addition ## Returns the "carry flag" result.addImpl(a, b, ctl) -func add*[bits](a: var BigInt[bits], b: static BigInt[bits], ctl: CTBool[Limb]): CTBool[Limb] = +func add*[bits](a: var BigInt[bits], b: static BigInt[bits], ctl: CTBool[Word]): CTBool[Word] = ## Constant-time big integer in-place addition ## Returns the "carry flag". Specialization for B being a compile-time constant (usually a modulus). result.addImpl(a, b, ctl) -template subImpl[bits](result: CTBool[Limb], a: var BigInt[bits], b: BigInt[bits], ctl: CTBool[Limb]) = +template subImpl[bits](result: CTBool[Word], a: var BigInt[bits], b: BigInt[bits], ctl: CTBool[Word]) = ## Constant-time big integer in-place substraction ## Returns the "borrow flag" for i in static(0 ..< a.limbs.len): - let new_a = a.limbs[i] - b.limbs[i] - Limb(result) + let new_a = a.limbs[i] - b.limbs[i] - Word(result) result = new_a.isMsbSet() a[i] = ctl.mux(new_a and HighLimb, a) -func sub*[bits](a: var BigInt[bits], b: BigInt[bits], ctl: CTBool[Limb]): CTBool[Limb] = +func sub*[bits](a: var BigInt[bits], b: BigInt[bits], ctl: CTBool[Word]): CTBool[Word] = ## Constant-time big integer in-place addition ## Returns the "carry flag" result.subImpl(a, b, ctl) -func sub*[bits](a: var BigInt[bits], b: static BigInt[bits], ctl: CTBool[Limb]): CTBool[Limb] = +func sub*[bits](a: var BigInt[bits], b: static BigInt[bits], ctl: CTBool[Word]): CTBool[Word] = ## Constant-time big integer in-place addition ## Returns the "carry flag". Specialization for B being a compile-time constant (usually a modulus). result.subImpl(a, b, ctl) diff --git a/constantine/field_fp.nim b/constantine/field_fp.nim index a9a79ff..adb596f 100644 --- a/constantine/field_fp.nim +++ b/constantine/field_fp.nim @@ -36,16 +36,16 @@ type # ############################################################ const - True = ctrue(Limb) - False = cfalse(Limb) + True = ctrue(Word) + False = cfalse(Word) -template add(a: var Fp, b: Fp, ctl: CTBool[Limb]): CTBool[Limb] = +template add(a: var Fp, b: Fp, ctl: CTBool[Word]): CTBool[Word] = add(a.value, b.value, ctl) -template sub(a: var Fp, b: Fp, ctl: CTBool[Limb]): CTBool[Limb] = +template sub(a: var Fp, b: Fp, ctl: CTBool[Word]): CTBool[Word] = sub(a.value, b.value, ctl) -template `[]`(a: Fp, idx: int): Limb = +template `[]`(a: Fp, idx: int): Word = a.value.limbs[idx] # ############################################################ @@ -69,39 +69,39 @@ func `+`*(a, b: Fp): Fp = ctl = ctl or not sub(result, Fp.P, False) sub(result, Fp.P, ctl) -template scaleadd_impl(a: var Fp, c: Limb) = +template scaleadd_impl(a: var Fp, c: Word) = ## Scale-accumulate ## - ## With a word W = 2^LimbBitSize and a field Fp + ## With a word W = 2^WordBitSize and a field Fp ## Does a <- a * W + c (mod p) const len = a.value.limbs.len - when Fp.P.bits <= LimbBitSize: + when Fp.P.bits <= WordBitSize: # If the prime fits in a single limb - var q: Limb + var q: Word # (hi, lo) = a * 2^63 + c let hi = a[0] shr 1 # 64 - 63 = 1 - let lo = a[0] shl LimbBitSize or c # Assumes most-significant bit in c is not set + let lo = a[0] shl WordBitSize or c # Assumes most-significant bit in c is not set unsafe_div2n1n(q, a[0], hi, lo, Fp.P.limbs[0]) # (hi, lo) mod P else: ## Multiple limbs let hi = a[^1] # Save the high word to detect carries - const R = Fp.P.bits and LimbBitSize # R = bits mod 64 + const R = Fp.P.bits and WordBitSize # R = bits mod 64 when R == 0: # If the number of bits is a multiple of 64 let a1 = a[^2] # let a0 = a[^1] # - moveMem(a[1], a[0], (len-1) * Limb.sizeof) # we can just shift words + moveMem(a[1], a[0], (len-1) * Word.sizeof) # we can just shift words a[0] = c # and replace the first one by c const p0 = Fp.P[^1] else: # Need to deal with partial word shifts at the edge. - let a1 = ((a[^2] shl (LimbBitSize-R)) or (a[^3] shr R)) and HighLimb - let a0 = ((a[^1] shl (LimbBitSize-R)) or (a[^2] shr R)) and HighLimb - moveMem(a[1], a[0], (len-1) * Limb.sizeof) + let a1 = ((a[^2] shl (WordBitSize-R)) or (a[^3] shr R)) and HighLimb + let a0 = ((a[^1] shl (WordBitSize-R)) or (a[^2] shr R)) and HighLimb + moveMem(a[1], a[0], (len-1) * Word.sizeof) a[0] = c - const p0 = ((Fp.P[^1] shl (LimbBitSize-R)) or (Fp.P[^2] shr R)) and HighLimb + const p0 = ((Fp.P[^1] shl (WordBitSize-R)) or (Fp.P[^2] shr R)) and HighLimb # p0 has its high bit set. (a0, a1)/p0 fits in a limb. # Get a quotient q, at most we will be 2 iterations off @@ -109,8 +109,8 @@ template scaleadd_impl(a: var Fp, c: Limb) = let a_hi = a0 shr 1 # 64 - 63 = 1 - a_lo = (a0 shl LimbBitSize) or a1 - var q, r: Limb + a_lo = (a0 shl WordBitSize) or a1 + var q, r: Word q = unsafe_div2n1n(q, r, a_hi, a_lo, p0) # Estimate quotient q = mux( # If n_hi == divisor a0 == b0, HighLimb, # Quotient == HighLimb (0b0111...1111) @@ -121,26 +121,26 @@ template scaleadd_impl(a: var Fp, c: Limb) = ) # Now substract a*2^63 - q*p - var carry = Limb(0) - var over_p = Limb(1) # Track if quotient than the modulus + var carry = Word(0) + var over_p = Word(1) # Track if quotient than the modulus for i in static(0 ..< Fp.P.limbs.len): - var qp_lo: Limb + var qp_lo: Word block: # q*p - qp_hi: Limb + qp_hi: Word unsafe_extendedPrecMul(qp_hi, qp_lo, q, Fp.P[i]) # q * p assert qp_lo.isMsbSet.not assert carry.isMsbSet.not qp_lo += carry # Add carry from previous limb let qp_carry = qp_lo.isMsbSet - carry = mux(qp_carry, qp_hi + Limb(1), qp_hi) # New carry + carry = mux(qp_carry, qp_hi + Word(1), qp_hi) # New carry qp_lo = qp_lo and HighLimb # Normalize to u63 block: # a*2^63 - q*p a[i] -= qp_lo - carry += Limb(a[i].isMsbSet) # Adjust if borrow + carry += Word(a[i].isMsbSet) # Adjust if borrow a[i] = a[i] and HighLimb # Normalize to u63 over_p = mux( @@ -159,16 +159,16 @@ template scaleadd_impl(a: var Fp, c: Limb) = add(a, Fp.P, neg) sub(a, Fp.P, tooBig) -func scaleadd*(a: var Fp, c: Limb) = +func scaleadd*(a: var Fp, c: Word) = ## Scale-accumulate modulo P ## - ## With a word W = 2^LimbBitSize and a field Fp + ## With a word W = 2^WordBitSize and a field Fp ## Does a <- a * W + c (mod p) scaleadd_impl(a, c) -func scaleadd*(a: var Fp, c: static Limb) = +func scaleadd*(a: var Fp, c: static Word) = ## Scale-accumulate modulo P ## - ## With a word W = 2^LimbBitSize and a field Fp + ## With a word W = 2^WordBitSize and a field Fp ## Does a <- a * W + c (mod p) scaleadd_impl(a, c) diff --git a/constantine/montgomery.nim b/constantine/montgomery.nim index 934bc21..b557db8 100644 --- a/constantine/montgomery.nim +++ b/constantine/montgomery.nim @@ -18,7 +18,7 @@ from bitops import fastLog2 # This will only be used at compile-time # so no constant-time worries (it is constant-time if using the De Bruijn multiplication) -func montyMagic*(M: static BigInt): static Limb = +func montyMagic*(M: static BigInt): static Word = ## Returns the Montgomery domain magic number for the input modulus: ## -1/M[0] mod LimbSize ## M[0] is the least significant limb of M @@ -63,7 +63,7 @@ func montyMagic*(M: static BigInt): static Limb = const M0 = M.limbs[0] - k = fastLog2(LimbBitSize) + k = fastLog2(WordBitSize) result = M0 # Start from an inverse of M0 modulo 2, M0 is odd and it's own inverse for _ in static(0 ..< k):