ring/arithmetic/bigint/
private_exponent.rs

1// Copyright 2015-2023 Brian Smith.
2//
3// Permission to use, copy, modify, and/or distribute this software for any
4// purpose with or without fee is hereby granted, provided that the above
5// copyright notice and this permission notice appear in all copies.
6//
7// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
8// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
10// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14
15use super::{limb, BoxedLimbs, Limb, LimbMask, Modulus};
16use crate::error;
17use alloc::boxed::Box;
18
19pub struct PrivateExponent {
20    limbs: Box<[Limb]>,
21}
22
23impl PrivateExponent {
24    // `p` is the modulus for which the exponent is in the interval [1, `p` - 1).
25    pub fn from_be_bytes_padded<M>(
26        input: untrusted::Input,
27        p: &Modulus<M>,
28    ) -> Result<Self, error::Unspecified> {
29        let dP = BoxedLimbs::from_be_bytes_padded_less_than(input, p)?;
30
31        // Proof that `dP < p - 1`:
32        //
33        // If `dP < p` then either `dP == p - 1` or `dP < p - 1`. Since `p` is
34        // odd, `p - 1` is even. `d` is odd, and an odd number modulo an even
35        // number is odd. Therefore `dP` must be odd. But then it cannot be
36        // `p - 1` and so we know `dP < p - 1`.
37        //
38        // Further we know `dP != 0` because `dP` is not even.
39        if limb::limbs_are_even_constant_time(&dP) != LimbMask::False {
40            return Err(error::Unspecified);
41        }
42
43        Ok(Self {
44            limbs: dP.into_limbs(),
45        })
46    }
47
48    #[cfg(test)]
49    pub fn from_be_bytes_for_test_only<M>(
50        input: untrusted::Input,
51        p: &Modulus<M>,
52    ) -> Result<Self, error::Unspecified> {
53        // Do exactly what `from_be_bytes_padded` does for any inputs it accepts.
54        if let r @ Ok(_) = Self::from_be_bytes_padded(input, p) {
55            return r;
56        }
57
58        let dP = BoxedLimbs::<M>::positive_minimal_width_from_be_bytes(input)?;
59
60        Ok(Self {
61            limbs: dP.into_limbs(),
62        })
63    }
64
65    #[inline]
66    pub(super) fn limbs(&self) -> &[Limb] {
67        &self.limbs
68    }
69}