1use std::io;
2
3use byteorder::{BigEndian, WriteBytesExt};
4use nom::number::streaming::be_u16;
5use nom::{Err, InputIter, InputTake};
6use num_bigint::BigUint;
7use zeroize::{Zeroize, ZeroizeOnDrop};
8
9use crate::errors::{self, Error, IResult};
10use crate::ser::Serialize;
11use crate::util::{bit_size, strip_leading_zeros, strip_leading_zeros_vec};
12
13const MAX_EXTERN_MPI_BITS: u32 = 16384;
16
17pub fn mpi(input: &[u8]) -> IResult<&[u8], MpiRef<'_>> {
33 let (number, len) = be_u16(input)?;
34
35 let bits = u32::from(len);
36 let len_actual = (bits + 7) >> 3;
37
38 if len_actual > MAX_EXTERN_MPI_BITS {
39 Err(Err::Error(Error::InvalidInput))
40 } else {
41 let cnt = len_actual as usize;
43 match number.slice_index(cnt) {
44 Err(needed) => Err(nom::Err::Incomplete(needed)),
45 Ok(index) => {
46 let (rest, n) = number.take_split(index);
47 let n_stripped: MpiRef<'_> = MpiRef::from_slice(strip_leading_zeros(n));
48
49 Ok((rest, n_stripped))
50 }
51 }
52 }
53}
54
55#[derive(Default, Clone, PartialEq, Eq, Zeroize, ZeroizeOnDrop, derive_more::Debug)]
58pub struct Mpi(#[debug("{}", hex::encode(_0))] Vec<u8>);
59
60#[derive(Clone, PartialEq, Eq, derive_more::Debug)]
63pub struct MpiRef<'a>(#[debug("{}", hex::encode(_0))] &'a [u8]);
64
65impl AsRef<[u8]> for Mpi {
66 fn as_ref(&self) -> &[u8] {
67 self.0.as_ref()
68 }
69}
70
71impl Mpi {
72 pub fn from_raw(mut v: Vec<u8>) -> Self {
73 strip_leading_zeros_vec(&mut v);
74 Mpi(v)
75 }
76
77 pub fn from_slice(raw: &[u8]) -> Self {
79 Mpi(strip_leading_zeros(raw).to_vec())
80 }
81
82 pub fn as_ref(&self) -> MpiRef<'_> {
83 MpiRef(&self.0)
84 }
85
86 pub fn as_bytes(&self) -> &[u8] {
87 &self.0
88 }
89}
90
91impl std::ops::Deref for Mpi {
92 type Target = [u8];
93
94 fn deref(&self) -> &Self::Target {
95 &self.0
96 }
97}
98
99impl<'a> std::ops::Deref for MpiRef<'a> {
100 type Target = [u8];
101
102 fn deref(&self) -> &Self::Target {
103 self.0
104 }
105}
106
107impl<'a> MpiRef<'a> {
108 pub fn from_slice(slice: &'a [u8]) -> Self {
109 MpiRef(strip_leading_zeros(slice))
110 }
111
112 pub fn to_owned(&self) -> Mpi {
113 Mpi(self.0.to_owned())
114 }
115
116 pub fn parse(slice: &'a [u8]) -> IResult<&'a [u8], MpiRef<'a>> {
117 mpi(slice)
118 }
119
120 pub fn as_bytes(&self) -> &[u8] {
121 self.0
122 }
123}
124
125impl Serialize for Mpi {
126 fn to_writer<W: io::Write>(&self, w: &mut W) -> errors::Result<()> {
127 MpiRef(&self.0).to_writer(w)
128 }
129}
130
131impl<'a> Serialize for MpiRef<'a> {
132 fn to_writer<W: io::Write>(&self, w: &mut W) -> errors::Result<()> {
133 let bytes = &self.0;
134 let size = bit_size(bytes);
135 w.write_u16::<BigEndian>(size as u16)?;
136 w.write_all(bytes)?;
137
138 Ok(())
139 }
140}
141
142impl From<BigUint> for Mpi {
143 fn from(other: BigUint) -> Self {
144 Mpi(other.to_bytes_be())
145 }
146}
147
148impl From<Mpi> for BigUint {
149 fn from(other: Mpi) -> Self {
150 BigUint::from_bytes_be(other.as_bytes())
151 }
152}
153
154impl<'a> From<&'a Mpi> for BigUint {
155 fn from(other: &'a Mpi) -> Self {
156 BigUint::from_bytes_be(other.as_bytes())
157 }
158}
159
160impl<'a> From<MpiRef<'a>> for BigUint {
161 fn from(other: MpiRef<'a>) -> Self {
162 BigUint::from_bytes_be(other.as_bytes())
163 }
164}
165
166impl<'a, 'b> From<&'b MpiRef<'a>> for BigUint {
167 fn from(other: &'b MpiRef<'a>) -> Self {
168 BigUint::from_bytes_be(other.as_bytes())
169 }
170}
171
172impl<'a> From<&'a BigUint> for Mpi {
173 fn from(other: &'a BigUint) -> Self {
174 Mpi(other.to_bytes_be())
175 }
176}
177
178#[cfg(test)]
179mod tests {
180 #![allow(clippy::unwrap_used)]
181
182 use super::*;
183
184 #[test]
185 fn test_mpi() {
186 assert_eq!(
188 mpi(&[0x00, 0x09, 0x01, 0xFF][..]).unwrap(),
189 (&b""[..], MpiRef::from_slice(&[0x01, 0xFF][..]))
190 );
191
192 assert_eq!(
194 mpi(&[
195 0x01, 0, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
196 0, 0, 0, 0, 0, 0, 0, 0x07
197 ][..])
198 .unwrap(),
199 (
200 &b""[..],
201 MpiRef::from_slice(
202 &[
203 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
204 0, 0, 0, 0, 0, 0, 0, 0x07
205 ][..]
206 )
207 )
208 );
209 }
210
211 #[test]
212 fn test_bignum_mpi() {
213 let fixtures = [
214 ("b4a71b058ac8aa1ddc453ab2663331c38f7645542815ac189a9af56d0e07a615469d3e08849650e03026d49259423cf00d089931cd700fd3a6e940bf83c81406e142a4b0a86f00738c7e1a9ff1b709f6bccc6cf900d0113a8e62e53d63be0a05105755b9efc6a4098c362c73fb422d40187d8e2382e88624d72caffceb13cec8fa0079c7d17883a46a1336471ab5be8cbb555c5d330d7fadb43318fa73b584edac312fa3302886bb5d04a05da3be2676c1fb94b3cf5c19d598659c3a7728ebab95f71721b662ac46aa9910726fe576d438f789c5ce2448f54546f254da814bcae1c35ee44b171e870ffa6403167a10e68573bdf155549274b431ff8e2418b627", "0800b4a71b058ac8aa1ddc453ab2663331c38f7645542815ac189a9af56d0e07a615469d3e08849650e03026d49259423cf00d089931cd700fd3a6e940bf83c81406e142a4b0a86f00738c7e1a9ff1b709f6bccc6cf900d0113a8e62e53d63be0a05105755b9efc6a4098c362c73fb422d40187d8e2382e88624d72caffceb13cec8fa0079c7d17883a46a1336471ab5be8cbb555c5d330d7fadb43318fa73b584edac312fa3302886bb5d04a05da3be2676c1fb94b3cf5c19d598659c3a7728ebab95f71721b662ac46aa9910726fe576d438f789c5ce2448f54546f254da814bcae1c35ee44b171e870ffa6403167a10e68573bdf155549274b431ff8e2418b627"),
215 ("00e57192fa7bd6abd7d01331f0411eebff4651290af1329369cc3bb3b8ccbd7ba6e352400c3f64f637967e24524921ee04f1e0a79168781f0bec9029e34c8a1fb1c328a4b8d74c31429616a6ff4707bb56b71ab66643243087c8ff0d0c4883b3473c56deece9a83dbd06eef09fac3558003ae45f8898b8a9490aa79672eebdd7d985d051d62698f2da7eee33ba740e30fc5a93c3f16ca1490dfd62b84ba016c9da7c087a28a4e97d8af79c6b638bc22f20a8b5953bb83caa3dddaaf1d0dc15a3f7ed47870174af74e5308b856138771a10019fe4374389eb89d2280776e33fa2dd3526cec35cd86a9cf6c94253fe00c4b8a87a36451745116456833bb1a237", "07f0e57192fa7bd6abd7d01331f0411eebff4651290af1329369cc3bb3b8ccbd7ba6e352400c3f64f637967e24524921ee04f1e0a79168781f0bec9029e34c8a1fb1c328a4b8d74c31429616a6ff4707bb56b71ab66643243087c8ff0d0c4883b3473c56deece9a83dbd06eef09fac3558003ae45f8898b8a9490aa79672eebdd7d985d051d62698f2da7eee33ba740e30fc5a93c3f16ca1490dfd62b84ba016c9da7c087a28a4e97d8af79c6b638bc22f20a8b5953bb83caa3dddaaf1d0dc15a3f7ed47870174af74e5308b856138771a10019fe4374389eb89d2280776e33fa2dd3526cec35cd86a9cf6c94253fe00c4b8a87a36451745116456833bb1a237"),
216 ];
217
218 for (i, (raw, encoded)) in fixtures.iter().enumerate() {
219 println!("fixture {i}");
220 let n = hex::decode(raw).unwrap();
221
222 let n_big = BigUint::from_bytes_be(&n);
223 let n_mpi: Mpi = n_big.clone().into();
224 let mut n_encoded = Vec::new();
225 n_mpi.to_writer(&mut n_encoded).unwrap();
226
227 assert_eq!(&n_encoded, &hex::decode(encoded).unwrap());
228
229 let (rest, n_big2) = mpi(&n_encoded).unwrap();
230 assert_eq!(rest.len(), 0);
231 assert_eq!(n_big, n_big2.into());
232 }
233 }
234}