der/asn1/integer/
bigint.rs
1use super::uint;
4use crate::{
5 asn1::Any, ByteSlice, DecodeValue, Decoder, EncodeValue, Encoder, Error, ErrorKind, FixedTag,
6 Length, Result, Tag,
7};
8
9#[cfg(feature = "bigint")]
10use crypto_bigint::{generic_array::GenericArray, ArrayEncoding, UInt};
11
12#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd)]
20pub struct UIntBytes<'a> {
21 inner: ByteSlice<'a>,
23}
24
25impl<'a> UIntBytes<'a> {
26 pub fn new(bytes: &'a [u8]) -> Result<Self> {
28 let inner = ByteSlice::new(uint::strip_leading_zeroes(bytes))
29 .map_err(|_| ErrorKind::Length { tag: Self::TAG })?;
30
31 Ok(Self { inner })
32 }
33
34 pub fn as_bytes(&self) -> &'a [u8] {
37 self.inner.as_bytes()
38 }
39
40 pub fn len(&self) -> Length {
42 self.inner.len()
43 }
44
45 pub fn is_empty(&self) -> bool {
47 self.inner.is_empty()
48 }
49}
50
51impl<'a> DecodeValue<'a> for UIntBytes<'a> {
52 fn decode_value(decoder: &mut Decoder<'a>, length: Length) -> Result<Self> {
53 let bytes = ByteSlice::decode_value(decoder, length)?.as_bytes();
54 let result = Self::new(uint::decode_to_slice(bytes)?)?;
55
56 if result.value_len()? != length {
58 return Err(Self::TAG.non_canonical_error());
59 }
60
61 Ok(result)
62 }
63}
64
65impl<'a> EncodeValue for UIntBytes<'a> {
66 fn value_len(&self) -> Result<Length> {
67 uint::encoded_len(self.inner.as_bytes())
68 }
69
70 fn encode_value(&self, encoder: &mut Encoder<'_>) -> Result<()> {
71 if self.value_len()? > self.len() {
73 encoder.byte(0)?;
74 }
75
76 encoder.bytes(self.as_bytes())
77 }
78}
79
80impl<'a> From<&UIntBytes<'a>> for UIntBytes<'a> {
81 fn from(value: &UIntBytes<'a>) -> UIntBytes<'a> {
82 *value
83 }
84}
85
86impl<'a> TryFrom<Any<'a>> for UIntBytes<'a> {
87 type Error = Error;
88
89 fn try_from(any: Any<'a>) -> Result<UIntBytes<'a>> {
90 any.decode_into()
91 }
92}
93
94impl<'a> FixedTag for UIntBytes<'a> {
95 const TAG: Tag = Tag::Integer;
96}
97
98#[cfg(feature = "bigint")]
99#[cfg_attr(docsrs, doc(cfg(feature = "bigint")))]
100impl<'a, const LIMBS: usize> TryFrom<Any<'a>> for UInt<LIMBS>
101where
102 UInt<LIMBS>: ArrayEncoding,
103{
104 type Error = Error;
105
106 fn try_from(any: Any<'a>) -> Result<UInt<LIMBS>> {
107 UIntBytes::try_from(any)?.try_into()
108 }
109}
110
111#[cfg(feature = "bigint")]
112#[cfg_attr(docsrs, doc(cfg(feature = "bigint")))]
113impl<'a, const LIMBS: usize> TryFrom<UIntBytes<'a>> for UInt<LIMBS>
114where
115 UInt<LIMBS>: ArrayEncoding,
116{
117 type Error = Error;
118
119 fn try_from(bytes: UIntBytes<'a>) -> Result<UInt<LIMBS>> {
120 let mut array = GenericArray::default();
121 let offset = array.len().saturating_sub(bytes.len().try_into()?);
122 array[offset..].copy_from_slice(bytes.as_bytes());
123 Ok(UInt::from_be_byte_array(array))
124 }
125}
126
127#[cfg(feature = "bigint")]
128#[cfg_attr(docsrs, doc(cfg(feature = "bigint")))]
129impl<const LIMBS: usize> EncodeValue for UInt<LIMBS>
130where
131 UInt<LIMBS>: ArrayEncoding,
132{
133 fn value_len(&self) -> Result<Length> {
134 let array = self.to_be_byte_array();
136 UIntBytes::new(&array)?.value_len()
137 }
138
139 fn encode_value(&self, encoder: &mut Encoder<'_>) -> Result<()> {
140 let array = self.to_be_byte_array();
141 UIntBytes::new(&array)?.encode_value(encoder)
142 }
143}
144
145#[cfg(feature = "bigint")]
146#[cfg_attr(docsrs, doc(cfg(feature = "bigint")))]
147impl<const LIMBS: usize> FixedTag for UInt<LIMBS>
148where
149 UInt<LIMBS>: ArrayEncoding,
150{
151 const TAG: Tag = Tag::Integer;
152}
153
154#[cfg(test)]
155mod tests {
156 use super::UIntBytes;
157 use crate::{
158 asn1::{integer::tests::*, Any},
159 Decodable, Encodable, Encoder, ErrorKind, Tag,
160 };
161
162 #[test]
163 fn decode_uint_bytes() {
164 assert_eq!(&[0], UIntBytes::from_der(I0_BYTES).unwrap().as_bytes());
165 assert_eq!(&[127], UIntBytes::from_der(I127_BYTES).unwrap().as_bytes());
166 assert_eq!(&[128], UIntBytes::from_der(I128_BYTES).unwrap().as_bytes());
167 assert_eq!(&[255], UIntBytes::from_der(I255_BYTES).unwrap().as_bytes());
168
169 assert_eq!(
170 &[0x01, 0x00],
171 UIntBytes::from_der(I256_BYTES).unwrap().as_bytes()
172 );
173
174 assert_eq!(
175 &[0x7F, 0xFF],
176 UIntBytes::from_der(I32767_BYTES).unwrap().as_bytes()
177 );
178 }
179
180 #[test]
181 fn encode_uint_bytes() {
182 for &example in &[
183 I0_BYTES,
184 I127_BYTES,
185 I128_BYTES,
186 I255_BYTES,
187 I256_BYTES,
188 I32767_BYTES,
189 ] {
190 let uint = UIntBytes::from_der(example).unwrap();
191
192 let mut buf = [0u8; 128];
193 let mut encoder = Encoder::new(&mut buf);
194 uint.encode(&mut encoder).unwrap();
195
196 let result = encoder.finish().unwrap();
197 assert_eq!(example, result);
198 }
199 }
200
201 #[test]
202 fn reject_oversize_without_extra_zero() {
203 let err = UIntBytes::try_from(Any::new(Tag::Integer, &[0x81]).unwrap())
204 .err()
205 .unwrap();
206
207 assert_eq!(err.kind(), ErrorKind::Value { tag: Tag::Integer });
208 }
209}