crypto_bigint_syncless/traits.rs
1//! Traits provided by this crate
2
3pub use num_traits::{
4 ConstOne, ConstZero, WrappingAdd, WrappingMul, WrappingNeg, WrappingShl, WrappingShr,
5 WrappingSub,
6};
7
8use crate::{Limb, NonZero, Odd, Reciprocal, modular::Retrieve};
9use core::{
10 fmt::{self, Debug},
11 ops::{
12 Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div,
13 DivAssign, Mul, MulAssign, Neg, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub,
14 SubAssign,
15 },
16};
17use subtle::{
18 Choice, ConditionallySelectable, ConstantTimeEq, ConstantTimeGreater, ConstantTimeLess,
19 CtOption,
20};
21
22#[cfg(feature = "rand_core")]
23use rand_core::{RngCore, TryRngCore};
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 + AsRef<[Limb]>
88 + BitAnd<Output = Self>
89 + for<'a> BitAnd<&'a Self, Output = Self>
90 + BitAndAssign
91 + for<'a> BitAndAssign<&'a Self>
92 + BitOr<Output = Self>
93 + for<'a> BitOr<&'a Self, Output = Self>
94 + BitOrAssign
95 + for<'a> BitOrAssign<&'a Self>
96 + BitXor<Output = Self>
97 + for<'a> BitXor<&'a Self, Output = Self>
98 + BitXorAssign
99 + for<'a> BitXorAssign<&'a Self>
100 + CheckedAdd
101 + CheckedSub
102 + CheckedMul
103 + CheckedDiv
104 + Clone
105 + ConstantTimeEq
106 + ConstantTimeGreater
107 + ConstantTimeLess
108 + ConstantTimeSelect
109 + Debug
110 + Default
111 + DivAssign<NonZero<Self>>
112 + for<'a> DivAssign<&'a NonZero<Self>>
113 + Eq
114 + fmt::LowerHex
115 + fmt::UpperHex
116 + fmt::Binary
117 + Mul<Output = Self>
118 + for<'a> Mul<&'a Self, Output = Self>
119 + MulAssign<Self>
120 + for<'a> MulAssign<&'a Self>
121 + Not<Output = Self>
122 + One
123 + Ord
124 + Rem<NonZero<Self>, Output = Self>
125 + for<'a> Rem<&'a NonZero<Self>, Output = Self>
126 + RemAssign<NonZero<Self>>
127 + for<'a> RemAssign<&'a NonZero<Self>>
128 + Send
129 + Sized
130 + Shl<u32, Output = Self>
131 + ShlAssign<u32>
132 + ShlVartime
133 + Shr<u32, Output = Self>
134 + ShrAssign<u32>
135 + ShrVartime
136 + Sub<Output = Self>
137 + for<'a> Sub<&'a Self, Output = Self>
138 + SubAssign<Self>
139 + for<'a> SubAssign<&'a Self>
140 + Sync
141 + WrappingAdd
142 + WrappingSub
143 + WrappingMul
144 + WrappingNeg
145 + WrappingShl
146 + WrappingShr
147 + Zero
148{
149 /// Number of limbs in this integer.
150 fn nlimbs(&self) -> usize;
151
152 /// Is this integer value an odd number?
153 ///
154 /// # Returns
155 ///
156 /// If odd, returns `Choice(1)`. Otherwise, returns `Choice(0)`.
157 fn is_odd(&self) -> Choice {
158 self.as_ref()
159 .first()
160 .map(|limb| limb.is_odd())
161 .unwrap_or_else(|| Choice::from(0))
162 }
163
164 /// Is this integer value an even number?
165 ///
166 /// # Returns
167 ///
168 /// If even, returns `Choice(1)`. Otherwise, returns `Choice(0)`.
169 fn is_even(&self) -> Choice {
170 !self.is_odd()
171 }
172}
173
174/// Signed [`Integer`]s.
175pub trait Signed:
176 Div<NonZero<Self>, Output = CtOption<Self>>
177 + for<'a> Div<&'a NonZero<Self>, Output = CtOption<Self>>
178 + From<i8>
179 + From<i16>
180 + From<i32>
181 + From<i64>
182 + Integer
183{
184 /// Corresponding unsigned integer type.
185 type Unsigned: Unsigned;
186
187 /// The sign and magnitude of this [`Signed`].
188 fn abs_sign(&self) -> (Self::Unsigned, Choice);
189
190 /// The magnitude of this [`Signed`].
191 fn abs(&self) -> Self::Unsigned {
192 self.abs_sign().0
193 }
194
195 /// Whether this [`Signed`] is negative (and non-zero), as a [`Choice`].
196 fn is_negative(&self) -> Choice;
197
198 /// Whether this [`Signed`] is positive (and non-zero), as a [`Choice`].
199 fn is_positive(&self) -> Choice;
200}
201
202/// Unsigned [`Integer`]s.
203pub trait Unsigned:
204 AddMod<Output = Self>
205 + BitOps
206 + Div<NonZero<Self>, Output = Self>
207 + for<'a> Div<&'a NonZero<Self>, Output = Self>
208 + DivRemLimb
209 + From<u8>
210 + From<u16>
211 + From<u32>
212 + From<u64>
213 + From<Limb>
214 + Integer
215 + MulMod<Output = Self>
216 + NegMod<Output = Self>
217 + RemLimb
218 + SquareRoot
219 + SquareMod<Output = Self>
220 + SubMod<Output = Self>
221{
222 /// The corresponding Montgomery representation,
223 /// optimized for the performance of modular operations at the price of a conversion overhead.
224 type Monty: Monty<Integer = Self>;
225
226 /// Returns an integer with the first limb set to `limb`, and the same precision as `other`.
227 fn from_limb_like(limb: Limb, other: &Self) -> Self;
228}
229
230/// Zero values: additive identity element for `Self`.
231pub trait Zero: ConstantTimeEq + Sized {
232 /// Returns the additive identity element of `Self`, `0`.
233 fn zero() -> Self;
234
235 /// Determine if this value is equal to `0`.
236 ///
237 /// # Returns
238 ///
239 /// If zero, returns `Choice(1)`. Otherwise, returns `Choice(0)`.
240 #[inline]
241 fn is_zero(&self) -> Choice {
242 self.ct_eq(&Self::zero())
243 }
244
245 /// Set `self` to its additive identity, i.e. `Self::zero`.
246 #[inline]
247 fn set_zero(&mut self) {
248 *self = Zero::zero();
249 }
250
251 /// Return the value `0` with the same precision as `other`.
252 fn zero_like(other: &Self) -> Self
253 where
254 Self: Clone,
255 {
256 let mut ret = other.clone();
257 ret.set_zero();
258 ret
259 }
260}
261
262/// One values: multiplicative identity element for `Self`.
263pub trait One: ConstantTimeEq + Sized {
264 /// Returns the multiplicative identity element of `Self`, `1`.
265 fn one() -> Self;
266
267 /// Determine if this value is equal to `1`.
268 ///
269 /// # Returns
270 ///
271 /// If one, returns `Choice(1)`. Otherwise, returns `Choice(0)`.
272 #[inline]
273 fn is_one(&self) -> Choice {
274 self.ct_eq(&Self::one())
275 }
276
277 /// Set `self` to its multiplicative identity, i.e. `Self::one`.
278 #[inline]
279 fn set_one(&mut self) {
280 *self = One::one();
281 }
282
283 /// Return the value `0` with the same precision as `other`.
284 fn one_like(other: &Self) -> Self
285 where
286 Self: Clone,
287 {
288 let mut ret = other.clone();
289 ret.set_one();
290 ret
291 }
292}
293
294/// Trait for associating constant values with a type.
295pub trait Constants: ConstZero + ConstOne {
296 /// Maximum value this integer can express.
297 const MAX: Self;
298}
299
300/// Fixed-width [`Integer`]s.
301pub trait FixedInteger: Bounded + ConditionallySelectable + Constants + Copy + Integer {
302 /// The number of limbs used on this platform.
303 const LIMBS: usize;
304}
305
306/// Compute the greatest common divisor of two integers.
307pub trait Gcd<Rhs = Self>: Sized {
308 /// Output type.
309 type Output;
310
311 /// Compute the greatest common divisor of `self` and `rhs`.
312 fn gcd(&self, rhs: &Rhs) -> Self::Output;
313
314 /// Compute the greatest common divisor of `self` and `rhs` in variable time.
315 fn gcd_vartime(&self, rhs: &Rhs) -> Self::Output;
316}
317
318/// Compute the extended greatest common divisor of two integers.
319pub trait Xgcd<Rhs = Self>: Sized {
320 /// Output type.
321 type Output;
322
323 /// Compute the extended greatest common divisor of `self` and `rhs`.
324 fn xgcd(&self, rhs: &Rhs) -> Self::Output;
325
326 /// Compute the extended greatest common divisor of `self` and `rhs` in variable time.
327 fn xgcd_vartime(&self, rhs: &Rhs) -> Self::Output;
328}
329
330/// Random number generation support.
331#[cfg(feature = "rand_core")]
332pub trait Random: Sized {
333 /// Generate a random value.
334 ///
335 /// If `rng` is a CSRNG, the generation is cryptographically secure as well.
336 fn random<R: RngCore + ?Sized>(rng: &mut R) -> Self {
337 let Ok(out) = Self::try_random(rng);
338 out
339 }
340
341 /// Generate a random value.
342 ///
343 /// If `rng` is a CSRNG, the generation is cryptographically secure as well.
344 fn try_random<R: TryRngCore + ?Sized>(rng: &mut R) -> Result<Self, R::Error>;
345}
346
347/// Possible errors of the methods in [`RandomBits`] trait.
348#[cfg(feature = "rand_core")]
349#[derive(Debug)]
350pub enum RandomBitsError<T> {
351 /// An error of the internal RNG library.
352 RandCore(T),
353 /// The requested `bits_precision` does not match the size of the integer
354 /// corresponding to the type (in the cases where this is set in compile time).
355 BitsPrecisionMismatch {
356 /// The requested precision.
357 bits_precision: u32,
358 /// The compile-time size of the integer.
359 integer_bits: u32,
360 },
361 /// The requested `bit_length` is larger than `bits_precision`.
362 BitLengthTooLarge {
363 /// The requested bit length of the random number.
364 bit_length: u32,
365 /// The requested precision.
366 bits_precision: u32,
367 },
368}
369
370#[cfg(feature = "rand_core")]
371impl<T> fmt::Display for RandomBitsError<T>
372where
373 T: fmt::Display,
374{
375 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
376 match self {
377 Self::RandCore(err) => write!(f, "{err}"),
378 Self::BitsPrecisionMismatch {
379 bits_precision,
380 integer_bits,
381 } => write!(
382 f,
383 concat![
384 "The requested `bits_precision` ({}) does not match ",
385 "the size of the integer corresponding to the type ({})"
386 ],
387 bits_precision, integer_bits
388 ),
389 Self::BitLengthTooLarge {
390 bit_length,
391 bits_precision,
392 } => write!(
393 f,
394 "The requested `bit_length` ({bit_length}) is larger than `bits_precision` ({bits_precision}).",
395 ),
396 }
397 }
398}
399
400#[cfg(feature = "rand_core")]
401impl<T> core::error::Error for RandomBitsError<T> where T: Debug + fmt::Display {}
402
403/// Random bits generation support.
404#[cfg(feature = "rand_core")]
405pub trait RandomBits: Sized {
406 /// Generate a random value in range `[0, 2^bit_length)`.
407 ///
408 /// A wrapper for [`RandomBits::try_random_bits`] that panics on error.
409 fn random_bits<R: TryRngCore + ?Sized>(rng: &mut R, bit_length: u32) -> Self {
410 Self::try_random_bits(rng, bit_length).expect("try_random_bits() failed")
411 }
412
413 /// Generate a random value in range `[0, 2^bit_length)`.
414 ///
415 /// This method is variable time wrt `bit_length`.
416 ///
417 /// If `rng` is a CSRNG, the generation is cryptographically secure as well.
418 fn try_random_bits<R: TryRngCore + ?Sized>(
419 rng: &mut R,
420 bit_length: u32,
421 ) -> Result<Self, RandomBitsError<R::Error>>;
422
423 /// Generate a random value in range `[0, 2^bit_length)`,
424 /// returning an integer with the closest available size to `bits_precision`
425 /// (if the implementing type supports runtime sizing).
426 ///
427 /// A wrapper for [`RandomBits::try_random_bits_with_precision`] that panics on error.
428 fn random_bits_with_precision<R: TryRngCore + ?Sized>(
429 rng: &mut R,
430 bit_length: u32,
431 bits_precision: u32,
432 ) -> Self {
433 Self::try_random_bits_with_precision(rng, bit_length, bits_precision)
434 .expect("try_random_bits_with_precision() failed")
435 }
436
437 /// Generate a random value in range `[0, 2^bit_length)`,
438 /// returning an integer with the closest available size to `bits_precision`
439 /// (if the implementing type supports runtime sizing).
440 ///
441 /// This method is variable time wrt `bit_length`.
442 ///
443 /// If `rng` is a CSRNG, the generation is cryptographically secure as well.
444 fn try_random_bits_with_precision<R: TryRngCore + ?Sized>(
445 rng: &mut R,
446 bit_length: u32,
447 bits_precision: u32,
448 ) -> Result<Self, RandomBitsError<R::Error>>;
449}
450
451/// Modular random number generation support.
452#[cfg(feature = "rand_core")]
453pub trait RandomMod: Sized + Zero {
454 /// Generate a random number which is less than a given `modulus`.
455 ///
456 /// This uses rejection sampling.
457 ///
458 /// As a result, it runs in variable time that depends in part on
459 /// `modulus`. If the generator `rng` is cryptographically secure (for
460 /// example, it implements `CryptoRng`), then this is guaranteed not to
461 /// leak anything about the output value aside from it being less than
462 /// `modulus`.
463 fn random_mod<R: RngCore + ?Sized>(rng: &mut R, modulus: &NonZero<Self>) -> Self {
464 let Ok(out) = Self::try_random_mod(rng, modulus);
465 out
466 }
467
468 /// Generate a random number which is less than a given `modulus`.
469 ///
470 /// This uses rejection sampling.
471 ///
472 /// As a result, it runs in variable time that depends in part on
473 /// `modulus`. If the generator `rng` is cryptographically secure (for
474 /// example, it implements `CryptoRng`), then this is guaranteed not to
475 /// leak anything about the output value aside from it being less than
476 /// `modulus`.
477 fn try_random_mod<R: TryRngCore + ?Sized>(
478 rng: &mut R,
479 modulus: &NonZero<Self>,
480 ) -> Result<Self, R::Error>;
481}
482
483/// Compute `self + rhs mod p`.
484pub trait AddMod<Rhs = Self, Mod = NonZero<Self>> {
485 /// Output type.
486 type Output;
487
488 /// Compute `self + rhs mod p`.
489 ///
490 /// Assumes `self` and `rhs` are `< p`.
491 fn add_mod(&self, rhs: &Rhs, p: &Mod) -> Self::Output;
492}
493
494/// Compute `self - rhs mod p`.
495pub trait SubMod<Rhs = Self, Mod = NonZero<Self>> {
496 /// Output type.
497 type Output;
498
499 /// Compute `self - rhs mod p`.
500 ///
501 /// Assumes `self` and `rhs` are `< p`.
502 fn sub_mod(&self, rhs: &Rhs, p: &Mod) -> Self::Output;
503}
504
505/// Compute `-self mod p`.
506pub trait NegMod<Mod = NonZero<Self>> {
507 /// Output type.
508 type Output;
509
510 /// Compute `-self mod p`.
511 #[must_use]
512 fn neg_mod(&self, p: &Mod) -> Self::Output;
513}
514
515/// Compute `self * rhs mod p`.
516pub trait MulMod<Rhs = Self, Mod = NonZero<Self>> {
517 /// Output type.
518 type Output;
519
520 /// Compute `self * rhs mod p`.
521 fn mul_mod(&self, rhs: &Rhs, p: &Mod) -> Self::Output;
522}
523
524/// Compute `self * self mod p`.
525pub trait SquareMod<Mod = NonZero<Self>> {
526 /// Output type.
527 type Output;
528
529 /// Compute `self * self mod p`.
530 fn square_mod(&self, p: &Mod) -> Self::Output;
531}
532
533/// Compute `1 / self mod p`.
534#[deprecated(since = "0.7.0", note = "please use `InvertMod` instead")]
535pub trait InvMod<Rhs = Self>: Sized {
536 /// Output type.
537 type Output;
538
539 /// Compute `1 / self mod p`.
540 fn inv_mod(&self, p: &Rhs) -> CtOption<Self::Output>;
541}
542
543#[allow(deprecated)]
544impl<T, Rhs> InvMod<Rhs> for T
545where
546 T: InvertMod<Rhs>,
547{
548 type Output = <T as InvertMod<Rhs>>::Output;
549
550 fn inv_mod(&self, p: &Rhs) -> CtOption<Self::Output> {
551 self.invert_mod(p)
552 }
553}
554
555/// Compute `1 / self mod p`.
556pub trait InvertMod<Mod = NonZero<Self>>: Sized {
557 /// Output type.
558 type Output;
559
560 /// Compute `1 / self mod p`.
561 fn invert_mod(&self, p: &Mod) -> CtOption<Self::Output>;
562}
563
564/// Checked addition.
565pub trait CheckedAdd<Rhs = Self>: Sized {
566 /// Perform checked addition, returning a [`CtOption`] which `is_some` only if the operation
567 /// did not overflow.
568 fn checked_add(&self, rhs: &Rhs) -> CtOption<Self>;
569}
570
571/// Checked division.
572pub trait CheckedDiv<Rhs = Self>: Sized {
573 /// Perform checked division, returning a [`CtOption`] which `is_some` only if the divisor is
574 /// non-zero.
575 fn checked_div(&self, rhs: &Rhs) -> CtOption<Self>;
576}
577
578/// Checked multiplication.
579pub trait CheckedMul<Rhs = Self>: Sized {
580 /// Perform checked multiplication, returning a [`CtOption`] which `is_some`
581 /// only if the operation did not overflow.
582 fn checked_mul(&self, rhs: &Rhs) -> CtOption<Self>;
583}
584
585/// Checked subtraction.
586pub trait CheckedSub<Rhs = Self>: Sized {
587 /// Perform checked subtraction, returning a [`CtOption`] which `is_some`
588 /// only if the operation did not underflow.
589 fn checked_sub(&self, rhs: &Rhs) -> CtOption<Self>;
590}
591
592/// Concatenate two numbers into a "wide" double-width value, using the `hi` value as the most
593/// significant portion of the resulting value.
594pub trait Concat: ConcatMixed<Self, MixedOutput = Self::Output> {
595 /// Concatenated output: twice the width of `Self`.
596 type Output: Integer;
597
598 /// Concatenate the two halves, with `self` as least significant and `hi` as the most significant.
599 fn concat(&self, hi: &Self) -> Self::Output {
600 self.concat_mixed(hi)
601 }
602}
603
604/// Concatenate two numbers into a "wide" combined-width value, using the `hi` value as the most
605/// significant value.
606pub trait ConcatMixed<Hi: ?Sized = Self> {
607 /// Concatenated output: combination of `Self` and `Hi`.
608 type MixedOutput: Integer;
609
610 /// Concatenate the two values, with `self` as least significant and `hi` as the most
611 /// significant.
612 fn concat_mixed(&self, hi: &Hi) -> Self::MixedOutput;
613}
614
615/// Split a number in half, returning the least significant half followed by the most significant.
616pub trait Split: SplitMixed<Self::Output, Self::Output> {
617 /// Split output: low/high components of the value.
618 type Output;
619
620 /// Split this number in half, returning its low and high components respectively.
621 fn split(&self) -> (Self::Output, Self::Output) {
622 self.split_mixed()
623 }
624}
625
626/// Split a number into parts, returning the least significant part followed by the most
627/// significant.
628pub trait SplitMixed<Lo, Hi> {
629 /// Split this number into parts, returning its low and high components respectively.
630 fn split_mixed(&self) -> (Lo, Hi);
631}
632
633/// Encoding support.
634pub trait Encoding: Sized {
635 /// Byte array representation.
636 type Repr: AsRef<[u8]>
637 + AsMut<[u8]>
638 + Copy
639 + Clone
640 + Sized
641 + for<'a> TryFrom<&'a [u8], Error = core::array::TryFromSliceError>;
642
643 /// Decode from big endian bytes.
644 fn from_be_bytes(bytes: Self::Repr) -> Self;
645
646 /// Decode from little endian bytes.
647 fn from_le_bytes(bytes: Self::Repr) -> Self;
648
649 /// Encode to big endian bytes.
650 fn to_be_bytes(&self) -> Self::Repr;
651
652 /// Encode to little endian bytes.
653 fn to_le_bytes(&self) -> Self::Repr;
654}
655
656/// Possible errors in variable-time integer decoding methods.
657#[derive(Clone, Copy, Debug, Eq, PartialEq)]
658pub enum DecodeError {
659 /// The input value was empty.
660 Empty,
661
662 /// The input was not consistent with the format restrictions.
663 InvalidDigit,
664
665 /// Input size is too small to fit in the given precision.
666 InputSize,
667
668 /// The deserialized number is larger than the given precision.
669 Precision,
670}
671
672impl fmt::Display for DecodeError {
673 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
674 match self {
675 Self::Empty => write!(f, "empty value provided"),
676 Self::InvalidDigit => {
677 write!(f, "invalid digit character")
678 }
679 Self::InputSize => write!(f, "input size is too small to fit in the given precision"),
680 Self::Precision => write!(
681 f,
682 "the deserialized number is larger than the given precision"
683 ),
684 }
685 }
686}
687
688impl core::error::Error for DecodeError {}
689
690/// Support for optimized squaring
691pub trait Square {
692 /// Computes the same as `self * self`, but may be more efficient.
693 fn square(&self) -> Self;
694}
695
696/// Support for optimized squaring in-place
697pub trait SquareAssign {
698 /// Computes the same as `self * self`, but may be more efficient.
699 /// Writes the result in `self`.
700 fn square_assign(&mut self);
701}
702
703/// Support for calucaling square roots.
704pub trait SquareRoot {
705 /// Computes `floor(sqrt(self))`.
706 fn sqrt(&self) -> Self;
707
708 /// Computes `floor(sqrt(self))`, variable time in `self`.
709 fn sqrt_vartime(&self) -> Self;
710}
711
712/// Support for optimized division by a single limb.
713pub trait DivRemLimb: Sized {
714 /// Computes `self / rhs` using a pre-made reciprocal,
715 /// returns the quotient (q) and remainder (r).
716 fn div_rem_limb(&self, rhs: NonZero<Limb>) -> (Self, Limb) {
717 self.div_rem_limb_with_reciprocal(&Reciprocal::new(rhs))
718 }
719
720 /// Computes `self / rhs`, returns the quotient (q) and remainder (r).
721 fn div_rem_limb_with_reciprocal(&self, reciprocal: &Reciprocal) -> (Self, Limb);
722}
723
724/// Support for calculating the remainder of two differently sized integers.
725pub trait RemMixed<Reductor>: Sized {
726 /// Calculate the remainder of `self` by the `reductor`.
727 fn rem_mixed(&self, reductor: &NonZero<Reductor>) -> Reductor;
728}
729
730/// Modular reduction from a larger value `T`.
731///
732/// This can be seen as fixed modular reduction, where the modulus is fixed at compile time
733/// by `Self`.
734///
735/// For modular reduction with a variable modulus, use [`Rem`].
736pub trait Reduce<T>: Sized {
737 /// Reduces `self` modulo `Modulus`.
738 fn reduce(value: &T) -> Self;
739}
740
741/// Division in variable time.
742pub trait DivVartime: Sized {
743 /// Computes `self / rhs` in variable time.
744 fn div_vartime(&self, rhs: &NonZero<Self>) -> Self;
745}
746
747/// Support for optimized division by a single limb.
748pub trait RemLimb: Sized {
749 /// Computes `self % rhs` using a pre-made reciprocal.
750 fn rem_limb(&self, rhs: NonZero<Limb>) -> Limb {
751 self.rem_limb_with_reciprocal(&Reciprocal::new(rhs))
752 }
753
754 /// Computes `self % rhs`.
755 fn rem_limb_with_reciprocal(&self, reciprocal: &Reciprocal) -> Limb;
756}
757
758/// Bit counting and bit operations.
759pub trait BitOps {
760 /// Precision of this integer in bits.
761 fn bits_precision(&self) -> u32;
762
763 /// `floor(log2(self.bits_precision()))`.
764 fn log2_bits(&self) -> u32 {
765 u32::BITS - self.bits_precision().leading_zeros() - 1
766 }
767
768 /// Precision of this integer in bytes.
769 fn bytes_precision(&self) -> usize;
770
771 /// Get the value of the bit at position `index`, as a truthy or falsy `Choice`.
772 /// Returns the falsy value for indices out of range.
773 fn bit(&self, index: u32) -> Choice;
774
775 /// Sets the bit at `index` to 0 or 1 depending on the value of `bit_value`.
776 fn set_bit(&mut self, index: u32, bit_value: Choice);
777
778 /// Calculate the number of bits required to represent a given number.
779 fn bits(&self) -> u32 {
780 self.bits_precision() - self.leading_zeros()
781 }
782
783 /// Calculate the number of trailing zeros in the binary representation of this number.
784 fn trailing_zeros(&self) -> u32;
785
786 /// Calculate the number of trailing ones in the binary representation of this number.
787 fn trailing_ones(&self) -> u32;
788
789 /// Calculate the number of leading zeros in the binary representation of this number.
790 fn leading_zeros(&self) -> u32;
791
792 /// Returns `true` if the bit at position `index` is set, `false` otherwise.
793 ///
794 /// # Remarks
795 /// This operation is variable time with respect to `index` only.
796 fn bit_vartime(&self, index: u32) -> bool;
797
798 /// Calculate the number of bits required to represent a given number in variable-time with
799 /// respect to `self`.
800 fn bits_vartime(&self) -> u32;
801
802 /// Sets the bit at `index` to 0 or 1 depending on the value of `bit_value`,
803 /// variable time in `self`.
804 fn set_bit_vartime(&mut self, index: u32, bit_value: bool);
805
806 /// Calculate the number of leading zeros in the binary representation of this number.
807 fn leading_zeros_vartime(&self) -> u32 {
808 self.bits_precision() - self.bits_vartime()
809 }
810
811 /// Calculate the number of trailing zeros in the binary representation of this number in
812 /// variable-time with respect to `self`.
813 fn trailing_zeros_vartime(&self) -> u32;
814
815 /// Calculate the number of trailing ones in the binary representation of this number,
816 /// variable time in `self`.
817 fn trailing_ones_vartime(&self) -> u32;
818}
819
820/// Constant-time exponentiation.
821pub trait Pow<Exponent> {
822 /// Raises to the `exponent` power.
823 fn pow(&self, exponent: &Exponent) -> Self;
824}
825
826impl<T: PowBoundedExp<Exponent>, Exponent: Bounded> Pow<Exponent> for T {
827 fn pow(&self, exponent: &Exponent) -> Self {
828 self.pow_bounded_exp(exponent, Exponent::BITS)
829 }
830}
831
832/// Constant-time exponentiation with exponent of a bounded bit size.
833pub trait PowBoundedExp<Exponent> {
834 /// Raises to the `exponent` power,
835 /// with `exponent_bits` representing the number of (least significant) bits
836 /// to take into account for the exponent.
837 ///
838 /// NOTE: `exponent_bits` may be leaked in the time pattern.
839 fn pow_bounded_exp(&self, exponent: &Exponent, exponent_bits: u32) -> Self;
840}
841
842/// Performs modular multi-exponentiation using Montgomery's ladder.
843///
844/// See: Straus, E. G. Problems and solutions: Addition chains of vectors. American Mathematical Monthly 71 (1964), 806–808.
845pub trait MultiExponentiate<Exponent, BasesAndExponents>: Pow<Exponent> + Sized
846where
847 BasesAndExponents: AsRef<[(Self, Exponent)]> + ?Sized,
848{
849 /// Calculates `x1 ^ k1 * ... * xn ^ kn`.
850 fn multi_exponentiate(bases_and_exponents: &BasesAndExponents) -> Self;
851}
852
853impl<T, Exponent, BasesAndExponents> MultiExponentiate<Exponent, BasesAndExponents> for T
854where
855 T: MultiExponentiateBoundedExp<Exponent, BasesAndExponents>,
856 Exponent: Bounded,
857 BasesAndExponents: AsRef<[(Self, Exponent)]> + ?Sized,
858{
859 fn multi_exponentiate(bases_and_exponents: &BasesAndExponents) -> Self {
860 Self::multi_exponentiate_bounded_exp(bases_and_exponents, Exponent::BITS)
861 }
862}
863
864/// Performs modular multi-exponentiation using Montgomery's ladder.
865/// `exponent_bits` represents the number of bits to take into account for the exponent.
866///
867/// See: Straus, E. G. Problems and solutions: Addition chains of vectors. American Mathematical Monthly 71 (1964), 806–808.
868///
869/// NOTE: this value is leaked in the time pattern.
870pub trait MultiExponentiateBoundedExp<Exponent, BasesAndExponents>: Pow<Exponent> + Sized
871where
872 BasesAndExponents: AsRef<[(Self, Exponent)]> + ?Sized,
873{
874 /// Calculates `x1 ^ k1 * ... * xn ^ kn`.
875 fn multi_exponentiate_bounded_exp(
876 bases_and_exponents: &BasesAndExponents,
877 exponent_bits: u32,
878 ) -> Self;
879}
880
881/// Constant-time inversion.
882pub trait Invert {
883 /// Output of the inversion.
884 type Output;
885
886 /// Computes the inverse.
887 fn invert(&self) -> Self::Output;
888
889 /// Computes the inverse in variable-time.
890 fn invert_vartime(&self) -> Self::Output {
891 self.invert()
892 }
893}
894
895/// Widening multiply: returns a value with a number of limbs equal to the sum of the inputs.
896#[deprecated(since = "0.7.0", note = "please use `ConcatenatingMul` instead")]
897pub trait WideningMul<Rhs = Self>: Sized {
898 /// Output of the widening multiplication.
899 type Output: Integer;
900
901 /// Perform widening multiplication.
902 fn widening_mul(&self, rhs: Rhs) -> Self::Output;
903}
904
905#[allow(deprecated)]
906impl<T, Rhs> WideningMul<Rhs> for T
907where
908 T: ConcatenatingMul<Rhs>,
909{
910 type Output = <T as ConcatenatingMul<Rhs>>::Output;
911
912 fn widening_mul(&self, rhs: Rhs) -> Self::Output {
913 self.concatenating_mul(rhs)
914 }
915}
916
917/// Widening multiply: returns a value with a number of limbs equal to the sum of the inputs.
918pub trait ConcatenatingMul<Rhs = Self>: Sized {
919 /// Output of the widening multiplication.
920 type Output: Integer;
921
922 /// Perform widening multiplication.
923 fn concatenating_mul(&self, rhs: Rhs) -> Self::Output;
924}
925
926/// Left shifts, variable time in `shift`.
927pub trait ShlVartime: Sized {
928 /// Computes `self << shift`.
929 ///
930 /// Returns `None` if `shift >= self.bits_precision()`.
931 fn overflowing_shl_vartime(&self, shift: u32) -> CtOption<Self>;
932
933 /// Computes `self << shift` in a panic-free manner, masking off bits of `shift`
934 /// which would cause the shift to exceed the type's width.
935 fn wrapping_shl_vartime(&self, shift: u32) -> Self;
936}
937
938/// Right shifts, variable time in `shift`.
939pub trait ShrVartime: Sized {
940 /// Computes `self >> shift`.
941 ///
942 /// Returns `None` if `shift >= self.bits_precision()`.
943 fn overflowing_shr_vartime(&self, shift: u32) -> CtOption<Self>;
944
945 /// Computes `self >> shift` in a panic-free manner, masking off bits of `shift`
946 /// which would cause the shift to exceed the type's width.
947 fn wrapping_shr_vartime(&self, shift: u32) -> Self;
948}
949
950/// Methods for resizing the allocated storage.
951pub trait Resize: Sized {
952 /// The result of the resizing.
953 type Output;
954
955 /// Resizes to the minimum storage that fits `at_least_bits_precision`
956 /// without checking if the bit size of `self` is larger than `at_least_bits_precision`.
957 ///
958 /// Variable-time w.r.t. `at_least_bits_precision`.
959 fn resize_unchecked(self, at_least_bits_precision: u32) -> Self::Output;
960
961 /// Resizes to the minimum storage that fits `at_least_bits_precision`
962 /// returning `None` if the bit size of `self` is larger than `at_least_bits_precision`.
963 ///
964 /// Variable-time w.r.t. `at_least_bits_precision`.
965 fn try_resize(self, at_least_bits_precision: u32) -> Option<Self::Output>;
966
967 /// Resizes to the minimum storage that fits `at_least_bits_precision`
968 /// panicking if the bit size of `self` is larger than `at_least_bits_precision`.
969 ///
970 /// Variable-time w.r.t. `at_least_bits_precision`.
971 fn resize(self, at_least_bits_precision: u32) -> Self::Output {
972 self.try_resize(at_least_bits_precision).unwrap_or_else(|| {
973 panic!("The bit size of `self` is larger than `at_least_bits_precision`")
974 })
975 }
976}
977
978/// A representation of an integer optimized for the performance of modular operations.
979pub trait Monty:
980 'static
981 + Clone
982 + Debug
983 + Eq
984 + Sized
985 + Send
986 + Sync
987 + Add<Output = Self>
988 + for<'a> Add<&'a Self, Output = Self>
989 + AddAssign
990 + for<'a> AddAssign<&'a Self>
991 + Sub<Output = Self>
992 + for<'a> Sub<&'a Self, Output = Self>
993 + SubAssign
994 + for<'a> SubAssign<&'a Self>
995 + Mul<Output = Self>
996 + for<'a> Mul<&'a Self, Output = Self>
997 + MulAssign
998 + for<'a> MulAssign<&'a Self>
999 + Neg<Output = Self>
1000 + PowBoundedExp<Self::Integer>
1001 + Retrieve<Output = Self::Integer>
1002 + Square
1003 + SquareAssign
1004{
1005 /// The original integer type.
1006 type Integer: Unsigned<Monty = Self>;
1007
1008 /// Prepared Montgomery multiplier for tight loops.
1009 type Multiplier<'a>: Debug + Clone + MontyMultiplier<'a, Monty = Self>;
1010
1011 /// The precomputed data needed for this representation.
1012 type Params: 'static + Clone + Debug + Eq + Sized + Send + Sync;
1013
1014 /// Create the precomputed data for Montgomery representation of integers modulo `modulus`,
1015 /// variable time in `modulus`.
1016 fn new_params_vartime(modulus: Odd<Self::Integer>) -> Self::Params;
1017
1018 /// Convert the value into the representation using precomputed data.
1019 fn new(value: Self::Integer, params: Self::Params) -> Self;
1020
1021 /// Returns zero in this representation.
1022 fn zero(params: Self::Params) -> Self;
1023
1024 /// Returns one in this representation.
1025 fn one(params: Self::Params) -> Self;
1026
1027 /// Returns the parameter struct used to initialize this object.
1028 fn params(&self) -> &Self::Params;
1029
1030 /// Access the value in Montgomery form.
1031 fn as_montgomery(&self) -> &Self::Integer;
1032
1033 /// Copy the Montgomery representation from `other` into `self`.
1034 /// NOTE: the parameters remain unchanged.
1035 fn copy_montgomery_from(&mut self, other: &Self);
1036
1037 /// Performs doubling, returning `self + self`.
1038 fn double(&self) -> Self;
1039
1040 /// Performs division by 2, that is returns `x` such that `x + x = self`.
1041 fn div_by_2(&self) -> Self;
1042
1043 /// Performs division by 2 inplace, that is finds `x` such that `x + x = self`
1044 /// and writes it into `self`.
1045 fn div_by_2_assign(&mut self) {
1046 *self = self.div_by_2()
1047 }
1048
1049 /// Calculate the sum of products of pairs `(a, b)` in `products`.
1050 ///
1051 /// This method is variable time only with the value of the modulus.
1052 /// For a modulus with leading zeros, this method is more efficient than a naive sum of products.
1053 ///
1054 /// This method will panic if `products` is empty. All terms must be associated with equivalent
1055 /// Montgomery parameters.
1056 fn lincomb_vartime(products: &[(&Self, &Self)]) -> Self;
1057}
1058
1059/// Prepared Montgomery multiplier for tight loops.
1060///
1061/// Allows one to perform inplace multiplication without allocations
1062/// (important for the `BoxedUint` case).
1063///
1064/// NOTE: You will be operating with Montgomery representations directly,
1065/// make sure they all correspond to the same set of parameters.
1066pub trait MontyMultiplier<'a>: From<&'a <Self::Monty as Monty>::Params> {
1067 /// The associated Montgomery-representation integer.
1068 type Monty: Monty;
1069
1070 /// Performs a Montgomery multiplication, assigning a fully reduced result to `lhs`.
1071 fn mul_assign(&mut self, lhs: &mut Self::Monty, rhs: &Self::Monty);
1072
1073 /// Performs a Montgomery squaring, assigning a fully reduced result to `lhs`.
1074 fn square_assign(&mut self, lhs: &mut Self::Monty);
1075}