rustica_keys/ssh/reader.rs
1use super::error::{Error, ErrorKind, Result};
2use std::convert::TryInto;
3
4/// A `Reader` is used for reading from a byte sequence
5/// representing an encoded OpenSSH public key or certificate.
6#[derive(Debug)]
7pub struct Reader<'a> {
8 inner: &'a [u8],
9 offset: usize,
10}
11
12impl<'a> Reader<'a> {
13 /// Creates a new `Reader` instance from the given byte sequence.
14 ///
15 /// # Example
16 /// ```rust
17 /// # use rustica_keys::ssh::Reader;
18 /// let data = vec![0, 0, 0, 42];
19 /// let mut reader = Reader::new(&data);
20 /// let num = reader.read_u32().unwrap();
21 /// assert_eq!(num, 42);
22 /// ```
23 pub fn new<T: ?Sized + AsRef<[u8]>>(inner: &T) -> Reader {
24 Reader {
25 inner: inner.as_ref(),
26 offset: 0,
27 }
28 }
29
30 /// Sets the `Reader` current offset to a given position.
31 ///
32 /// # Example
33 /// ```rust
34 /// # use rustica_keys::ssh::Reader;
35 /// let data = vec![0, 0, 0, 42];
36 /// let mut reader = Reader::new(&data);
37 /// let num = reader.read_u32().unwrap();
38 /// assert_eq!(num, 42);
39 /// reader.set_offset(0);
40 /// let num_42_again = reader.read_u32().unwrap();
41 /// assert_eq!(num_42_again, 42);
42 /// ```
43 pub fn set_offset(&mut self, offset: usize) -> Result<()> {
44 self.offset = offset;
45
46 Ok(())
47 }
48
49 /// Gets the `Reader` current offset.
50 ///
51 /// # Example
52 /// ```rust
53 /// # use rustica_keys::ssh::Reader;
54 /// let data = vec![0, 0, 0, 42];
55 /// let mut reader = Reader::new(&data);
56 /// let num = reader.read_u32().unwrap();
57 /// assert_eq!(num, 42);
58 /// assert_eq!(reader.get_offset(), 4);
59 /// ```
60 pub fn get_offset(&self) -> usize {
61 self.offset
62 }
63
64 /// Reads a byte buffer from the wrapped byte sequence and
65 /// returns it as a `Vec<u8>`.
66 /// The buffer is represented by it's length as `u32` value
67 /// followed by the actual bytes to read.
68 ///
69 /// # Example
70 /// ```rust
71 /// # use rustica_keys::ssh::Reader;
72 /// let data = vec![0, 0, 0, 13, 97, 32, 116, 101, 115, 116, 32, 115, 116, 114, 105, 110, 103];
73 /// let mut reader = Reader::new(&data);
74 /// let bytes = reader.read_bytes().unwrap();
75 /// assert_eq!(bytes, [97, 32, 116, 101, 115, 116, 32, 115, 116, 114, 105, 110, 103]);
76 /// ```
77 pub fn read_bytes(&mut self) -> Result<Vec<u8>> {
78 if self.offset >= self.inner.len() {
79 return Err(Error::with_kind(ErrorKind::UnexpectedEof));
80 }
81
82 let slice = &self.inner[self.offset..];
83 if slice.len() < 4 {
84 return Err(Error::with_kind(ErrorKind::InvalidFormat));
85 }
86
87 let size = u32::from_be_bytes(slice[..4].try_into().unwrap()) as usize;
88 if slice.len() < size + 4 {
89 return Err(Error::with_kind(ErrorKind::InvalidFormat));
90 }
91
92 self.offset += size + 4;
93 let result = slice[4..size + 4].to_vec();
94
95 Ok(result)
96 }
97
98 /// Reads `len` bytes from the wrapped buffer as raw data
99 /// # Example
100 /// ```rust
101 /// # use rustica_keys::ssh::Reader;
102 /// let data = vec![0, 0, 0, 13, 97, 32, 116, 101, 115, 116, 32, 115, 116, 114, 105, 110, 103];
103 /// let mut reader = Reader::new(&data);
104 /// let bytes = reader.read_raw_bytes(4).unwrap();
105 /// assert_eq!(bytes, [0, 0, 0, 13]);
106 /// ```
107 pub fn read_raw_bytes(&mut self, len: usize) -> Result<Vec<u8>> {
108 if self.offset >= self.inner.len() {
109 return Err(Error::with_kind(ErrorKind::UnexpectedEof));
110 }
111
112 if len + self.offset > self.inner.len() {
113 return Err(Error::with_kind(ErrorKind::UnexpectedEof));
114 }
115
116 let slice = &self.inner[self.offset..];
117
118 self.offset += len;
119 let result = slice[..len].to_vec();
120
121 Ok(result)
122 }
123
124 /// Reads an `mpint` value from the wrapped byte sequence.
125 ///
126 /// Drops the leading byte if it's value is zero according to the RFC 4251, section 5.
127 ///
128 /// # Example
129 /// ```rust
130 /// # use rustica_keys::ssh::Reader;
131 /// let data = vec![0, 0, 0, 3, 1, 0, 1];
132 /// let mut reader = Reader::new(&data);
133 /// let mpint = reader.read_mpint().unwrap();
134 /// assert_eq!(mpint, [1, 0, 1]);
135 /// ```
136 pub fn read_mpint(&mut self) -> Result<Vec<u8>> {
137 let bytes = self.read_bytes()?;
138
139 if bytes[0] == 0 {
140 return Ok(bytes[1..].to_vec());
141 }
142
143 Ok(bytes)
144 }
145
146 /// Reads a `string` value from the wrapped byte sequence and
147 /// returns it as a `String`. The value that we read should be a valid UTF-8.
148 ///
149 /// # Example
150 /// ```rust
151 /// # use rustica_keys::ssh::Reader;
152 /// let data = vec![0, 0, 0, 13, 97, 32, 116, 101, 115, 116, 32, 115, 116, 114, 105, 110, 103];
153 /// let mut reader = Reader::new(&data);
154 /// let result = reader.read_string().unwrap();
155 /// assert_eq!(result, "a test string");
156 /// ```
157 pub fn read_string(&mut self) -> Result<String> {
158 let bytes = self.read_bytes()?;
159 let result = String::from_utf8(bytes)?;
160
161 Ok(result)
162 }
163
164 /// Read a null terminated string from the reader's buffer.
165 /// This is different than read_string in that the length
166 /// is unknown and will continue until it reads a null byte
167 /// or reaches the end of the data.
168 ///
169 /// In the event the buffer runs out before a null byte, the offset will be
170 /// reset and an error returned.
171 pub fn read_cstring(&mut self) -> Result<String> {
172 let original_offset = self.offset;
173 let mut s = String::new();
174
175 while self.offset < self.inner.len() {
176 let chr = self.inner[self.offset];
177 if chr == 0x0 {
178 // Count the final null byte as read
179 self.offset += 1;
180 return Ok(s);
181 }
182
183 s.push(chr as char);
184 self.offset += 1;
185 }
186 self.offset = original_offset;
187 Err(Error::with_kind(ErrorKind::UnexpectedEof))
188 }
189
190 /// Reads an `u32` value from the wrapped byte sequence and returns it.
191 ///
192 /// # Example
193 /// ```rust
194 /// # use rustica_keys::ssh::Reader;
195 /// let data = vec![0, 0, 0, 42];
196 /// let mut reader = Reader::new(&data);
197 /// let num = reader.read_u32().unwrap();
198 /// assert_eq!(num, 42);
199 /// ```
200 pub fn read_u32(&mut self) -> Result<u32> {
201 if self.offset >= self.inner.len() {
202 return Err(Error::with_kind(ErrorKind::UnexpectedEof));
203 }
204
205 let slice = &self.inner[self.offset..];
206 if slice.len() < 4 {
207 return Err(Error::with_kind(ErrorKind::InvalidFormat));
208 }
209
210 self.offset += 4;
211 let value = u32::from_be_bytes(slice[..4].try_into().unwrap());
212
213 Ok(value)
214 }
215
216 /// Reads an `u64` value from the wrapped byte sequence and returns it.
217 ///
218 /// # Example
219 /// ```rust
220 /// # use rustica_keys::ssh::Reader;
221 /// let data = vec![0, 0, 0, 0, 0, 0, 0, 42];
222 /// let mut reader = Reader::new(&data);
223 /// let num = reader.read_u64().unwrap();
224 /// assert_eq!(num, 42);
225 /// ```
226 pub fn read_u64(&mut self) -> Result<u64> {
227 if self.offset >= self.inner.len() {
228 return Err(Error::with_kind(ErrorKind::UnexpectedEof));
229 }
230
231 let slice = &self.inner[self.offset..];
232 if slice.len() < 8 {
233 return Err(Error::with_kind(ErrorKind::InvalidFormat));
234 }
235
236 self.offset += 8;
237 let value = u64::from_be_bytes(slice[..8].try_into().unwrap());
238
239 Ok(value)
240 }
241}