Skip to main content

ps_ecc/polynomial/implementations/mul/
byte_slice.rs

1use std::ops::Mul;
2
3use crate::{error::PolynomialMulError, Polynomial};
4
5use super::mul_coefficient_slices;
6
7impl Mul<&[u8]> for &Polynomial {
8    type Output = Result<Polynomial, PolynomialMulError>;
9
10    /// Multiplies a polynomial by a coefficient slice over GF(256).
11    ///
12    /// # Errors
13    ///
14    /// Returns `DegreeOverflow` if the result degree exceeds 254.
15    fn mul(self, rhs: &[u8]) -> Self::Output {
16        let rhs_trimmed = match rhs.iter().rposition(|&c| c != 0) {
17            Some(degree) => &rhs[..=degree],
18            None => &[],
19        };
20
21        mul_coefficient_slices(self.coefficients(), rhs_trimmed)
22    }
23}
24
25impl Mul<&[u8]> for Polynomial {
26    type Output = Result<Self, PolynomialMulError>;
27
28    fn mul(self, rhs: &[u8]) -> Self::Output {
29        (&self).mul(rhs)
30    }
31}
32
33#[cfg(test)]
34#[allow(clippy::expect_used)]
35mod tests {
36    use std::ops::Mul;
37
38    use crate::{error::PolynomialMulError, Polynomial};
39
40    #[test]
41    fn mul_by_slice() {
42        let a = Polynomial::try_from(&[1u8, 2][..]).expect("valid polynomial");
43        let b: &[u8] = &[3, 4];
44
45        let result = a.mul(b).expect("degree fits");
46
47        assert_eq!(result.coefficients(), &[3, 2, 8]);
48    }
49
50    #[test]
51    fn mul_slice_degree_overflow() {
52        let a = Polynomial::try_from(&[1u8][..]).expect("valid polynomial");
53        let mut long_slice = [0u8; 256];
54
55        long_slice[255] = 1; // degree 255, which exceeds MAX_DEGREE
56
57        let result = a.mul(long_slice.as_slice());
58
59        assert_eq!(result, Err(PolynomialMulError::DegreeOverflow));
60    }
61
62    #[test]
63    fn mul_long_slice_with_trailing_zeros() {
64        let a = Polynomial::try_from(&[1u8, 2][..]).expect("valid polynomial");
65        let mut long_slice = [0u8; 300];
66
67        long_slice[0] = 3;
68        long_slice[1] = 4; // effective degree is 1, despite slice length 300
69
70        let result = a.mul(long_slice.as_slice()).expect("degree fits");
71
72        assert_eq!(result.coefficients(), &[3, 2, 8]);
73    }
74
75    #[test]
76    fn mul_slice_matches_polynomial() {
77        let a = Polynomial::try_from(&[1u8, 2, 3][..]).expect("valid polynomial");
78        let b = Polynomial::try_from(&[4u8, 5, 6][..]).expect("valid polynomial");
79
80        let via_poly = (&a).mul(&b).expect("degree fits");
81        let via_slice = (&a).mul(b.coefficients()).expect("degree fits");
82
83        assert_eq!(via_poly, via_slice);
84    }
85}