crypto_bigint/traits.rs
1//! Traits provided by this crate
2
3mod sealed;
4
5pub use num_traits::{
6 ConstZero, WrappingAdd, WrappingMul, WrappingNeg, WrappingShl, WrappingShr, WrappingSub,
7};
8
9pub(crate) use sealed::PrecomputeInverterWithAdjuster;
10
11use crate::{Limb, NonZero, Odd, Reciprocal};
12use core::fmt::{self, Debug};
13use core::ops::{
14 Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign,
15 Mul, MulAssign, Neg, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign,
16};
17use subtle::{
18 Choice, ConditionallySelectable, ConstantTimeEq, ConstantTimeGreater, ConstantTimeLess,
19 CtOption,
20};
21
22#[cfg(feature = "rand_core")]
23use rand_core::RngCore;
24
25/// Integers whose representation takes a bounded amount of space.
26pub trait Bounded {
27 /// Size of this integer in bits.
28 const BITS: u32;
29
30 /// Size of this integer in bytes.
31 const BYTES: usize;
32}
33
34/// Trait for types which are conditionally selectable in constant time.
35///
36/// Similar to (and blanket impl'd for) `subtle`'s [`ConditionallySelectable`] trait, but without
37/// the `Copy` bound which allows it to be impl'd for heap allocated types such as `BoxedUint`.
38///
39/// It also provides generic implementations of conditional assignment and conditional swaps.
40pub trait ConstantTimeSelect: Clone {
41 /// Select `a` or `b` according to `choice`.
42 ///
43 /// # Returns
44 /// - `a` if `choice == Choice(0)`;
45 /// - `b` if `choice == Choice(1)`.
46 fn ct_select(a: &Self, b: &Self, choice: Choice) -> Self;
47
48 /// Conditionally assign `other` to `self`, according to `choice`.
49 #[inline]
50 fn ct_assign(&mut self, other: &Self, choice: Choice) {
51 *self = Self::ct_select(self, other, choice);
52 }
53
54 /// Conditionally swap `self` and `other` if `choice == 1`; otherwise, reassign both unto themselves.
55 #[inline]
56 fn ct_swap(a: &mut Self, b: &mut Self, choice: Choice) {
57 let t: Self = a.clone();
58 a.ct_assign(b, choice);
59 b.ct_assign(&t, choice);
60 }
61}
62
63impl<T: ConditionallySelectable> ConstantTimeSelect for T {
64 #[inline(always)]
65 fn ct_select(a: &Self, b: &Self, choice: Choice) -> Self {
66 T::conditional_select(a, b, choice)
67 }
68
69 #[inline(always)]
70 fn ct_assign(&mut self, other: &Self, choice: Choice) {
71 self.conditional_assign(other, choice)
72 }
73
74 #[inline(always)]
75 fn ct_swap(a: &mut Self, b: &mut Self, choice: Choice) {
76 T::conditional_swap(a, b, choice)
77 }
78}
79
80/// Integer trait: represents common functionality of integer types provided by this crate.
81pub trait Integer:
82 'static
83 + Add<Output = Self>
84 + for<'a> Add<&'a Self, Output = Self>
85 + AddAssign<Self>
86 + for<'a> AddAssign<&'a Self>
87 + AddMod<Output = Self>
88 + AsRef<[Limb]>
89 + BitAnd<Output = Self>
90 + for<'a> BitAnd<&'a Self, Output = Self>
91 + BitAndAssign
92 + for<'a> BitAndAssign<&'a Self>
93 + BitOr<Output = Self>
94 + for<'a> BitOr<&'a Self, Output = Self>
95 + BitOrAssign
96 + for<'a> BitOrAssign<&'a Self>
97 + BitXor<Output = Self>
98 + for<'a> BitXor<&'a Self, Output = Self>
99 + BitXorAssign
100 + for<'a> BitXorAssign<&'a Self>
101 + BitOps
102 + CheckedAdd
103 + CheckedSub
104 + CheckedMul
105 + CheckedDiv
106 + Clone
107 + ConstantTimeEq
108 + ConstantTimeGreater
109 + ConstantTimeLess
110 + ConstantTimeSelect
111 + Debug
112 + Default
113 + Div<NonZero<Self>, Output = Self>
114 + for<'a> Div<&'a NonZero<Self>, Output = Self>
115 + DivAssign<NonZero<Self>>
116 + for<'a> DivAssign<&'a NonZero<Self>>
117 + DivRemLimb
118 + Eq
119 + From<u8>
120 + From<u16>
121 + From<u32>
122 + From<u64>
123 + From<Limb>
124 + Mul<Output = Self>
125 + for<'a> Mul<&'a Self, Output = Self>
126 + MulAssign<Self>
127 + for<'a> MulAssign<&'a Self>
128 + MulMod<Output = Self>
129 + NegMod<Output = Self>
130 + Not<Output = Self>
131 + Ord
132 + Rem<NonZero<Self>, Output = Self>
133 + for<'a> Rem<&'a NonZero<Self>, Output = Self>
134 + RemAssign<NonZero<Self>>
135 + for<'a> RemAssign<&'a NonZero<Self>>
136 + RemLimb
137 + Send
138 + Sized
139 + Shl<u32, Output = Self>
140 + ShlAssign<u32>
141 + ShlVartime
142 + Shr<u32, Output = Self>
143 + ShrAssign<u32>
144 + ShrVartime
145 + Sub<Output = Self>
146 + for<'a> Sub<&'a Self, Output = Self>
147 + SubAssign<Self>
148 + for<'a> SubAssign<&'a Self>
149 + SubMod<Output = Self>
150 + Sync
151 + SquareRoot
152 + WrappingAdd
153 + WrappingSub
154 + WrappingMul
155 + WrappingNeg
156 + WrappingShl
157 + WrappingShr
158 + Zero
159{
160 /// The corresponding Montgomery representation,
161 /// optimized for the performance of modular operations at the price of a conversion overhead.
162 type Monty: Monty<Integer = Self>;
163
164 /// The value `1`.
165 fn one() -> Self;
166
167 /// The value `1` with the same precision as `other`.
168 fn one_like(other: &Self) -> Self {
169 Self::from_limb_like(Limb::ONE, other)
170 }
171
172 /// Returns an integer with the first limb set to `limb`, and the same precision as `other`.
173 fn from_limb_like(limb: Limb, other: &Self) -> Self;
174
175 /// Number of limbs in this integer.
176 fn nlimbs(&self) -> usize;
177
178 /// Is this integer value an odd number?
179 ///
180 /// # Returns
181 ///
182 /// If odd, returns `Choice(1)`. Otherwise, returns `Choice(0)`.
183 fn is_odd(&self) -> Choice {
184 self.as_ref()
185 .first()
186 .map(|limb| limb.is_odd())
187 .unwrap_or_else(|| Choice::from(0))
188 }
189
190 /// Is this integer value an even number?
191 ///
192 /// # Returns
193 ///
194 /// If even, returns `Choice(1)`. Otherwise, returns `Choice(0)`.
195 fn is_even(&self) -> Choice {
196 !self.is_odd()
197 }
198}
199
200/// Fixed-width integers.
201pub trait FixedInteger: Bounded + ConditionallySelectable + Constants + Copy + Integer {
202 /// The number of limbs used on this platform.
203 const LIMBS: usize;
204}
205
206/// Compute the greatest common divisor of two integers.
207pub trait Gcd<Rhs = Self>: Sized {
208 /// Output type.
209 type Output;
210
211 /// Compute the greatest common divisor of `self` and `rhs`.
212 fn gcd(&self, rhs: &Rhs) -> Self::Output;
213
214 /// Compute the greatest common divisor of `self` and `rhs` in variable time.
215 fn gcd_vartime(&self, rhs: &Rhs) -> Self::Output;
216}
217
218/// Trait impl'd by precomputed modular inverters obtained via the [`PrecomputeInverter`] trait.
219pub trait Inverter {
220 /// Output of an inversion.
221 type Output;
222
223 /// Compute a modular inversion, returning `None` if the result is undefined (i.e. if `value` is
224 /// zero or isn't prime relative to the modulus).
225 fn invert(&self, value: &Self::Output) -> CtOption<Self::Output>;
226
227 /// Compute a modular inversion, returning `None` if the result is undefined (i.e. if `value` is
228 /// zero or isn't prime relative to the modulus).
229 ///
230 /// This version is variable-time with respect to `value`.
231 fn invert_vartime(&self, value: &Self::Output) -> CtOption<Self::Output>;
232}
233
234/// Obtain a precomputed inverter for efficiently computing modular inversions for a given modulus.
235pub trait PrecomputeInverter {
236 /// Inverter type for integers of this size.
237 type Inverter: Inverter<Output = Self::Output> + Sized;
238
239 /// Output produced by the inverter.
240 type Output;
241
242 /// Obtain a precomputed inverter for `&self` as the modulus, using `Self::one()` as an adjusting parameter.
243 ///
244 /// Returns `None` if `self` is even.
245 fn precompute_inverter(&self) -> Self::Inverter;
246}
247
248/// Zero values.
249pub trait Zero: ConstantTimeEq + Sized {
250 /// The value `0`.
251 fn zero() -> Self;
252
253 /// Determine if this value is equal to zero.
254 ///
255 /// # Returns
256 ///
257 /// If zero, returns `Choice(1)`. Otherwise, returns `Choice(0)`.
258 #[inline]
259 fn is_zero(&self) -> Choice {
260 self.ct_eq(&Self::zero())
261 }
262
263 /// Set `self` to its additive identity, i.e. `Self::zero`.
264 #[inline]
265 fn set_zero(&mut self) {
266 *self = Zero::zero();
267 }
268
269 /// Return the value `0` with the same precision as `other`.
270 fn zero_like(other: &Self) -> Self
271 where
272 Self: Clone,
273 {
274 let mut ret = other.clone();
275 ret.set_zero();
276 ret
277 }
278}
279
280impl<T: ConstZero + ConstantTimeEq> Zero for T {
281 #[inline(always)]
282 fn zero() -> T {
283 Self::ZERO
284 }
285}
286
287/// Trait for associating constant values with a type.
288pub trait Constants: ConstZero {
289 /// The value `1`.
290 const ONE: Self;
291
292 /// Maximum value this integer can express.
293 const MAX: Self;
294}
295
296/// Random number generation support.
297#[cfg(feature = "rand_core")]
298pub trait Random: Sized {
299 /// Generate a random value.
300 ///
301 /// If `rng` is a CSRNG, the generation is cryptographically secure as well.
302 fn random(rng: &mut (impl RngCore + ?Sized)) -> Self;
303}
304
305/// Possible errors of the methods in [`RandomBits`] trait.
306#[cfg(feature = "rand_core")]
307#[derive(Debug)]
308pub enum RandomBitsError {
309 /// An error of the internal RNG library.
310 RandCore(rand_core::Error),
311 /// The requested `bits_precision` does not match the size of the integer
312 /// corresponding to the type (in the cases where this is set in compile time).
313 BitsPrecisionMismatch {
314 /// The requested precision.
315 bits_precision: u32,
316 /// The compile-time size of the integer.
317 integer_bits: u32,
318 },
319 /// The requested `bit_length` is larger than `bits_precision`.
320 BitLengthTooLarge {
321 /// The requested bit length of the random number.
322 bit_length: u32,
323 /// The requested precision.
324 bits_precision: u32,
325 },
326}
327
328#[cfg(feature = "rand_core")]
329impl fmt::Display for RandomBitsError {
330 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
331 match self {
332 Self::RandCore(err) => write!(f, "{}", err),
333 Self::BitsPrecisionMismatch {
334 bits_precision,
335 integer_bits,
336 } => write!(
337 f,
338 concat![
339 "The requested `bits_precision` ({}) does not match ",
340 "the size of the integer corresponding to the type ({})"
341 ],
342 bits_precision, integer_bits
343 ),
344 Self::BitLengthTooLarge {
345 bit_length,
346 bits_precision,
347 } => write!(
348 f,
349 "The requested `bit_length` ({}) is larger than `bits_precision` ({}).",
350 bit_length, bits_precision
351 ),
352 }
353 }
354}
355
356#[cfg(feature = "rand_core")]
357impl core::error::Error for RandomBitsError {}
358
359/// Random bits generation support.
360#[cfg(feature = "rand_core")]
361pub trait RandomBits: Sized {
362 /// Generate a random value in range `[0, 2^bit_length)`.
363 ///
364 /// A wrapper for [`RandomBits::try_random_bits`] that panics on error.
365 fn random_bits(rng: &mut (impl RngCore + ?Sized), bit_length: u32) -> Self {
366 Self::try_random_bits(rng, bit_length).expect("try_random_bits() failed")
367 }
368
369 /// Generate a random value in range `[0, 2^bit_length)`.
370 ///
371 /// This method is variable time wrt `bit_length`.
372 ///
373 /// If `rng` is a CSRNG, the generation is cryptographically secure as well.
374 fn try_random_bits(
375 rng: &mut (impl RngCore + ?Sized),
376 bit_length: u32,
377 ) -> Result<Self, RandomBitsError>;
378
379 /// Generate a random value in range `[0, 2^bit_length)`,
380 /// returning an integer with the closest available size to `bits_precision`
381 /// (if the implementing type supports runtime sizing).
382 ///
383 /// A wrapper for [`RandomBits::try_random_bits_with_precision`] that panics on error.
384 fn random_bits_with_precision(
385 rng: &mut (impl RngCore + ?Sized),
386 bit_length: u32,
387 bits_precision: u32,
388 ) -> Self {
389 Self::try_random_bits_with_precision(rng, bit_length, bits_precision)
390 .expect("try_random_bits_with_precision() failed")
391 }
392
393 /// Generate a random value in range `[0, 2^bit_length)`,
394 /// returning an integer with the closest available size to `bits_precision`
395 /// (if the implementing type supports runtime sizing).
396 ///
397 /// This method is variable time wrt `bit_length`.
398 ///
399 /// If `rng` is a CSRNG, the generation is cryptographically secure as well.
400 fn try_random_bits_with_precision(
401 rng: &mut (impl RngCore + ?Sized),
402 bit_length: u32,
403 bits_precision: u32,
404 ) -> Result<Self, RandomBitsError>;
405}
406
407/// Modular random number generation support.
408#[cfg(feature = "rand_core")]
409pub trait RandomMod: Sized + Zero {
410 /// Generate a random number which is less than a given `modulus`.
411 ///
412 /// This uses rejection sampling.
413 ///
414 /// As a result, it runs in variable time that depends in part on
415 /// `modulus`. If the generator `rng` is cryptographically secure (for
416 /// example, it implements `CryptoRng`), then this is guaranteed not to
417 /// leak anything about the output value aside from it being less than
418 /// `modulus`.
419 fn random_mod(rng: &mut (impl RngCore + ?Sized), modulus: &NonZero<Self>) -> Self;
420}
421
422/// Compute `self + rhs mod p`.
423pub trait AddMod<Rhs = Self> {
424 /// Output type.
425 type Output;
426
427 /// Compute `self + rhs mod p`.
428 ///
429 /// Assumes `self` and `rhs` are `< p`.
430 fn add_mod(&self, rhs: &Rhs, p: &Self) -> Self::Output;
431}
432
433/// Compute `self - rhs mod p`.
434pub trait SubMod<Rhs = Self> {
435 /// Output type.
436 type Output;
437
438 /// Compute `self - rhs mod p`.
439 ///
440 /// Assumes `self` and `rhs` are `< p`.
441 fn sub_mod(&self, rhs: &Rhs, p: &Self) -> Self::Output;
442}
443
444/// Compute `-self mod p`.
445pub trait NegMod {
446 /// Output type.
447 type Output;
448
449 /// Compute `-self mod p`.
450 #[must_use]
451 fn neg_mod(&self, p: &Self) -> Self::Output;
452}
453
454/// Compute `self * rhs mod p`.
455pub trait MulMod<Rhs = Self> {
456 /// Output type.
457 type Output;
458
459 /// Compute `self * rhs mod p`.
460 fn mul_mod(&self, rhs: &Rhs, p: &Self) -> Self::Output;
461}
462
463/// Compute `1 / self mod p`.
464pub trait InvMod<Rhs = Self>: Sized {
465 /// Output type.
466 type Output;
467
468 /// Compute `1 / self mod p`.
469 fn inv_mod(&self, p: &Rhs) -> CtOption<Self::Output>;
470}
471
472/// Checked addition.
473pub trait CheckedAdd<Rhs = Self>: Sized {
474 /// Perform checked addition, returning a [`CtOption`] which `is_some` only if the operation
475 /// did not overflow.
476 fn checked_add(&self, rhs: &Rhs) -> CtOption<Self>;
477}
478
479/// Checked division.
480pub trait CheckedDiv<Rhs = Self>: Sized {
481 /// Perform checked division, returning a [`CtOption`] which `is_some` only if the divisor is
482 /// non-zero.
483 fn checked_div(&self, rhs: &Rhs) -> CtOption<Self>;
484}
485
486/// Checked multiplication.
487pub trait CheckedMul<Rhs = Self>: Sized {
488 /// Perform checked multiplication, returning a [`CtOption`] which `is_some`
489 /// only if the operation did not overflow.
490 fn checked_mul(&self, rhs: &Rhs) -> CtOption<Self>;
491}
492
493/// Checked subtraction.
494pub trait CheckedSub<Rhs = Self>: Sized {
495 /// Perform checked subtraction, returning a [`CtOption`] which `is_some`
496 /// only if the operation did not underflow.
497 fn checked_sub(&self, rhs: &Rhs) -> CtOption<Self>;
498}
499
500/// Concatenate two numbers into a "wide" double-width value, using the `hi` value as the most
501/// significant portion of the resulting value.
502pub trait Concat: ConcatMixed<Self, MixedOutput = Self::Output> {
503 /// Concatenated output: twice the width of `Self`.
504 type Output: Integer;
505
506 /// Concatenate the two halves, with `self` as least significant and `hi` as the most significant.
507 fn concat(&self, hi: &Self) -> Self::Output {
508 self.concat_mixed(hi)
509 }
510}
511
512/// Concatenate two numbers into a "wide" combined-width value, using the `hi` value as the most
513/// significant value.
514pub trait ConcatMixed<Hi: ?Sized = Self> {
515 /// Concatenated output: combination of `Self` and `Hi`.
516 type MixedOutput: Integer;
517
518 /// Concatenate the two values, with `self` as least significant and `hi` as the most
519 /// significant.
520 fn concat_mixed(&self, hi: &Hi) -> Self::MixedOutput;
521}
522
523/// Split a number in half, returning the least significant half followed by the most significant.
524pub trait Split: SplitMixed<Self::Output, Self::Output> {
525 /// Split output: low/high components of the value.
526 type Output;
527
528 /// Split this number in half, returning its low and high components respectively.
529 fn split(&self) -> (Self::Output, Self::Output) {
530 self.split_mixed()
531 }
532}
533
534/// Split a number into parts, returning the least significant part followed by the most
535/// significant.
536pub trait SplitMixed<Lo, Hi> {
537 /// Split this number into parts, returning its low and high components respectively.
538 fn split_mixed(&self) -> (Lo, Hi);
539}
540
541/// Encoding support.
542pub trait Encoding: Sized {
543 /// Byte array representation.
544 type Repr: AsRef<[u8]>
545 + AsMut<[u8]>
546 + Copy
547 + Clone
548 + Sized
549 + for<'a> TryFrom<&'a [u8], Error = core::array::TryFromSliceError>;
550
551 /// Decode from big endian bytes.
552 fn from_be_bytes(bytes: Self::Repr) -> Self;
553
554 /// Decode from little endian bytes.
555 fn from_le_bytes(bytes: Self::Repr) -> Self;
556
557 /// Encode to big endian bytes.
558 fn to_be_bytes(&self) -> Self::Repr;
559
560 /// Encode to little endian bytes.
561 fn to_le_bytes(&self) -> Self::Repr;
562}
563
564/// Possible errors in variable-time integer decoding methods.
565#[derive(Clone, Copy, Debug, Eq, PartialEq)]
566pub enum DecodeError {
567 /// The input value was empty.
568 Empty,
569
570 /// The input was not consistent with the format restrictions.
571 InvalidDigit,
572
573 /// Input size is too small to fit in the given precision.
574 InputSize,
575
576 /// The deserialized number is larger than the given precision.
577 Precision,
578}
579
580impl fmt::Display for DecodeError {
581 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
582 match self {
583 Self::Empty => write!(f, "empty value provided"),
584 Self::InvalidDigit => {
585 write!(f, "invalid digit character")
586 }
587 Self::InputSize => write!(f, "input size is too small to fit in the given precision"),
588 Self::Precision => write!(
589 f,
590 "the deserialized number is larger than the given precision"
591 ),
592 }
593 }
594}
595
596impl core::error::Error for DecodeError {}
597
598/// Support for optimized squaring
599pub trait Square {
600 /// Computes the same as `self * self`, but may be more efficient.
601 fn square(&self) -> Self;
602}
603
604/// Support for optimized squaring in-place
605pub trait SquareAssign {
606 /// Computes the same as `self * self`, but may be more efficient.
607 /// Writes the result in `self`.
608 fn square_assign(&mut self);
609}
610
611/// Support for calucaling square roots.
612pub trait SquareRoot {
613 /// Computes `floor(sqrt(self))`.
614 fn sqrt(&self) -> Self;
615
616 /// Computes `floor(sqrt(self))`, variable time in `self`.
617 fn sqrt_vartime(&self) -> Self;
618}
619
620/// Support for optimized division by a single limb.
621pub trait DivRemLimb: Sized {
622 /// Computes `self / rhs` using a pre-made reciprocal,
623 /// returns the quotient (q) and remainder (r).
624 fn div_rem_limb(&self, rhs: NonZero<Limb>) -> (Self, Limb) {
625 self.div_rem_limb_with_reciprocal(&Reciprocal::new(rhs))
626 }
627
628 /// Computes `self / rhs`, returns the quotient (q) and remainder (r).
629 fn div_rem_limb_with_reciprocal(&self, reciprocal: &Reciprocal) -> (Self, Limb);
630}
631
632/// Support for calculating the remainder of two differently sized integers.
633pub trait RemMixed<Reductor>: Sized {
634 /// Calculate the remainder of `self` by the `reductor`.
635 fn rem_mixed(&self, reductor: &NonZero<Reductor>) -> Reductor;
636}
637
638/// Support for optimized division by a single limb.
639pub trait RemLimb: Sized {
640 /// Computes `self % rhs` using a pre-made reciprocal.
641 fn rem_limb(&self, rhs: NonZero<Limb>) -> Limb {
642 self.rem_limb_with_reciprocal(&Reciprocal::new(rhs))
643 }
644
645 /// Computes `self % rhs`.
646 fn rem_limb_with_reciprocal(&self, reciprocal: &Reciprocal) -> Limb;
647}
648
649/// Bit counting and bit operations.
650pub trait BitOps {
651 /// Precision of this integer in bits.
652 fn bits_precision(&self) -> u32;
653
654 /// `floor(log2(self.bits_precision()))`.
655 fn log2_bits(&self) -> u32 {
656 u32::BITS - self.bits_precision().leading_zeros() - 1
657 }
658
659 /// Precision of this integer in bytes.
660 fn bytes_precision(&self) -> usize;
661
662 /// Calculate the number of bits needed to represent this number.
663 fn bit(&self, index: u32) -> Choice;
664
665 /// Sets the bit at `index` to 0 or 1 depending on the value of `bit_value`.
666 fn set_bit(&mut self, index: u32, bit_value: Choice);
667
668 /// Calculate the number of bits required to represent a given number.
669 fn bits(&self) -> u32 {
670 self.bits_precision() - self.leading_zeros()
671 }
672
673 /// Calculate the number of trailing zeros in the binary representation of this number.
674 fn trailing_zeros(&self) -> u32;
675
676 /// Calculate the number of trailing ones in the binary representation of this number.
677 fn trailing_ones(&self) -> u32;
678
679 /// Calculate the number of leading zeros in the binary representation of this number.
680 fn leading_zeros(&self) -> u32;
681
682 /// Returns `true` if the bit at position `index` is set, `false` otherwise.
683 ///
684 /// # Remarks
685 /// This operation is variable time with respect to `index` only.
686 fn bit_vartime(&self, index: u32) -> bool;
687
688 /// Calculate the number of bits required to represent a given number in variable-time with
689 /// respect to `self`.
690 fn bits_vartime(&self) -> u32;
691
692 /// Sets the bit at `index` to 0 or 1 depending on the value of `bit_value`,
693 /// variable time in `self`.
694 fn set_bit_vartime(&mut self, index: u32, bit_value: bool);
695
696 /// Calculate the number of leading zeros in the binary representation of this number.
697 fn leading_zeros_vartime(&self) -> u32 {
698 self.bits_precision() - self.bits_vartime()
699 }
700
701 /// Calculate the number of trailing zeros in the binary representation of this number in
702 /// variable-time with respect to `self`.
703 fn trailing_zeros_vartime(&self) -> u32;
704
705 /// Calculate the number of trailing ones in the binary representation of this number,
706 /// variable time in `self`.
707 fn trailing_ones_vartime(&self) -> u32;
708}
709
710/// Constant-time exponentiation.
711pub trait Pow<Exponent> {
712 /// Raises to the `exponent` power.
713 fn pow(&self, exponent: &Exponent) -> Self;
714}
715
716impl<T: PowBoundedExp<Exponent>, Exponent: Bounded> Pow<Exponent> for T {
717 fn pow(&self, exponent: &Exponent) -> Self {
718 self.pow_bounded_exp(exponent, Exponent::BITS)
719 }
720}
721
722/// Constant-time exponentiation with exponent of a bounded bit size.
723pub trait PowBoundedExp<Exponent> {
724 /// Raises to the `exponent` power,
725 /// with `exponent_bits` representing the number of (least significant) bits
726 /// to take into account for the exponent.
727 ///
728 /// NOTE: `exponent_bits` may be leaked in the time pattern.
729 fn pow_bounded_exp(&self, exponent: &Exponent, exponent_bits: u32) -> Self;
730}
731
732/// Performs modular multi-exponentiation using Montgomery's ladder.
733///
734/// See: Straus, E. G. Problems and solutions: Addition chains of vectors. American Mathematical Monthly 71 (1964), 806–808.
735pub trait MultiExponentiate<Exponent, BasesAndExponents>: Pow<Exponent> + Sized
736where
737 BasesAndExponents: AsRef<[(Self, Exponent)]> + ?Sized,
738{
739 /// Calculates `x1 ^ k1 * ... * xn ^ kn`.
740 fn multi_exponentiate(bases_and_exponents: &BasesAndExponents) -> Self;
741}
742
743impl<T, Exponent, BasesAndExponents> MultiExponentiate<Exponent, BasesAndExponents> for T
744where
745 T: MultiExponentiateBoundedExp<Exponent, BasesAndExponents>,
746 Exponent: Bounded,
747 BasesAndExponents: AsRef<[(Self, Exponent)]> + ?Sized,
748{
749 fn multi_exponentiate(bases_and_exponents: &BasesAndExponents) -> Self {
750 Self::multi_exponentiate_bounded_exp(bases_and_exponents, Exponent::BITS)
751 }
752}
753
754/// Performs modular multi-exponentiation using Montgomery's ladder.
755/// `exponent_bits` represents the number of bits to take into account for the exponent.
756///
757/// See: Straus, E. G. Problems and solutions: Addition chains of vectors. American Mathematical Monthly 71 (1964), 806–808.
758///
759/// NOTE: this value is leaked in the time pattern.
760pub trait MultiExponentiateBoundedExp<Exponent, BasesAndExponents>: Pow<Exponent> + Sized
761where
762 BasesAndExponents: AsRef<[(Self, Exponent)]> + ?Sized,
763{
764 /// Calculates `x1 ^ k1 * ... * xn ^ kn`.
765 fn multi_exponentiate_bounded_exp(
766 bases_and_exponents: &BasesAndExponents,
767 exponent_bits: u32,
768 ) -> Self;
769}
770
771/// Constant-time inversion.
772pub trait Invert: Sized {
773 /// Output of the inversion.
774 type Output;
775
776 /// Computes the inverse.
777 fn invert(&self) -> Self::Output;
778
779 /// Computes the inverse in variable-time.
780 fn invert_vartime(&self) -> Self::Output;
781}
782
783/// Widening multiply: returns a value with a number of limbs equal to the sum of the inputs.
784pub trait WideningMul<Rhs = Self>: Sized {
785 /// Output of the widening multiplication.
786 type Output: Integer;
787
788 /// Perform widening multiplication.
789 fn widening_mul(&self, rhs: Rhs) -> Self::Output;
790}
791
792/// Left shifts, variable time in `shift`.
793pub trait ShlVartime: Sized {
794 /// Computes `self << shift`.
795 ///
796 /// Returns `None` if `shift >= self.bits_precision()`.
797 fn overflowing_shl_vartime(&self, shift: u32) -> CtOption<Self>;
798
799 /// Computes `self << shift` in a panic-free manner, masking off bits of `shift`
800 /// which would cause the shift to exceed the type's width.
801 fn wrapping_shl_vartime(&self, shift: u32) -> Self;
802}
803
804/// Right shifts, variable time in `shift`.
805pub trait ShrVartime: Sized {
806 /// Computes `self >> shift`.
807 ///
808 /// Returns `None` if `shift >= self.bits_precision()`.
809 fn overflowing_shr_vartime(&self, shift: u32) -> CtOption<Self>;
810
811 /// Computes `self >> shift` in a panic-free manner, masking off bits of `shift`
812 /// which would cause the shift to exceed the type's width.
813 fn wrapping_shr_vartime(&self, shift: u32) -> Self;
814}
815
816/// A representation of an integer optimized for the performance of modular operations.
817pub trait Monty:
818 'static
819 + Clone
820 + Debug
821 + Eq
822 + Sized
823 + Send
824 + Sync
825 + Add<Output = Self>
826 + for<'a> Add<&'a Self, Output = Self>
827 + AddAssign
828 + for<'a> AddAssign<&'a Self>
829 + Sub<Output = Self>
830 + for<'a> Sub<&'a Self, Output = Self>
831 + SubAssign
832 + for<'a> SubAssign<&'a Self>
833 + Mul<Output = Self>
834 + for<'a> Mul<&'a Self, Output = Self>
835 + MulAssign
836 + for<'a> MulAssign<&'a Self>
837 + Neg<Output = Self>
838 + PowBoundedExp<Self::Integer>
839 + Square
840 + SquareAssign
841{
842 /// The original integer type.
843 type Integer: Integer<Monty = Self>;
844
845 /// The precomputed data needed for this representation.
846 type Params: 'static + Clone + Debug + Eq + Sized + Send + Sync;
847
848 /// Create the precomputed data for Montgomery representation of integers modulo `modulus`,
849 /// variable time in `modulus`.
850 fn new_params_vartime(modulus: Odd<Self::Integer>) -> Self::Params;
851
852 /// Convert the value into the representation using precomputed data.
853 fn new(value: Self::Integer, params: Self::Params) -> Self;
854
855 /// Returns zero in this representation.
856 fn zero(params: Self::Params) -> Self;
857
858 /// Returns one in this representation.
859 fn one(params: Self::Params) -> Self;
860
861 /// Returns the parameter struct used to initialize this object.
862 fn params(&self) -> &Self::Params;
863
864 /// Access the value in Montgomery form.
865 fn as_montgomery(&self) -> &Self::Integer;
866
867 /// Performs doubling, returning `self + self`.
868 fn double(&self) -> Self;
869
870 /// Performs division by 2, that is returns `x` such that `x + x = self`.
871 fn div_by_2(&self) -> Self;
872
873 /// Calculate the sum of products of pairs `(a, b)` in `products`.
874 ///
875 /// This method is variable time only with the value of the modulus.
876 /// For a modulus with leading zeros, this method is more efficient than a naive sum of products.
877 ///
878 /// This method will panic if `products` is empty. All terms must be associated with equivalent
879 /// Montgomery parameters.
880 fn lincomb_vartime(products: &[(&Self, &Self)]) -> Self;
881}