1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
use super::error::{Error, ErrorKind, Result}; use byteorder::{BigEndian, ByteOrder}; /// A `Reader` is used for reading from a byte sequence /// representing an encoded OpenSSH public key or certificate. #[derive(Debug)] pub struct Reader<'a> { inner: &'a [u8], offset: usize, } impl<'a> Reader<'a> { /// Creates a new `Reader` instance from the given byte sequence. /// /// # Example /// ```rust /// # use sshkeys; /// let data = vec![0, 0, 0, 42]; /// let mut reader = sshkeys::Reader::new(&data); /// let num = reader.read_u32().unwrap(); /// assert_eq!(num, 42); /// ``` pub fn new<T: ?Sized + AsRef<[u8]>>(inner: &T) -> Reader { Reader { inner: inner.as_ref(), offset: 0, } } /// Sets the `Reader` current offset to a given position. /// /// # Example /// ```rust /// # use sshkeys; /// let data = vec![0, 0, 0, 42]; /// let mut reader = sshkeys::Reader::new(&data); /// let num = reader.read_u32().unwrap(); /// assert_eq!(num, 42); /// reader.set_offset(0); /// let num_42_again = reader.read_u32().unwrap(); /// assert_eq!(num_42_again, 42); /// ``` pub fn set_offset(&mut self, offset: usize) -> Result<()> { self.offset = offset; Ok(()) } /// Reads a byte buffer from the wrapped byte sequence and /// returns it as a `Vec<u8>`. /// The buffer is represented by it's length as `u32` value /// followed by the actual bytes to read. /// /// # Example /// ```rust /// # use sshkeys; /// let data = vec![0, 0, 0, 13, 97, 32, 116, 101, 115, 116, 32, 115, 116, 114, 105, 110, 103]; /// let mut reader = sshkeys::Reader::new(&data); /// let bytes = reader.read_bytes().unwrap(); /// assert_eq!(bytes, [97, 32, 116, 101, 115, 116, 32, 115, 116, 114, 105, 110, 103]); /// ``` pub fn read_bytes(&mut self) -> Result<Vec<u8>> { if self.offset >= self.inner.len() { return Err(Error::with_kind(ErrorKind::UnexpectedEof)); } let slice = &self.inner[self.offset..]; if slice.len() < 4 { return Err(Error::with_kind(ErrorKind::InvalidFormat)); } let size = BigEndian::read_u32(&slice[..4]) as usize; if slice.len() < size + 4 { return Err(Error::with_kind(ErrorKind::InvalidFormat)); } self.offset += size + 4; let result = slice[4..size + 4].to_vec(); Ok(result) } /// Reads an `mpint` value from the wrapped byte sequence. /// /// Drops the leading byte if it's value is zero according to the RFC 4251, section 5. /// /// # Example /// ```rust /// # use sshkeys; /// let data = vec![0, 0, 0, 3, 1, 0, 1]; /// let mut reader = sshkeys::Reader::new(&data); /// let mpint = reader.read_mpint().unwrap(); /// assert_eq!(mpint, [1, 0, 1]); /// ``` pub fn read_mpint(&mut self) -> Result<Vec<u8>> { let bytes = self.read_bytes()?; if bytes[0] == 0 { return Ok(bytes[1..].to_vec()); } Ok(bytes) } /// Reads a `string` value from the wrapped byte sequence and /// returns it as a `String`. The value that we read should be a valid UTF-8. /// /// # Example /// ```rust /// # use sshkeys; /// let data = vec![0, 0, 0, 13, 97, 32, 116, 101, 115, 116, 32, 115, 116, 114, 105, 110, 103]; /// let mut reader = sshkeys::Reader::new(&data); /// let result = reader.read_string().unwrap(); /// assert_eq!(result, "a test string"); /// ``` pub fn read_string(&mut self) -> Result<String> { let bytes = self.read_bytes()?; let result = String::from_utf8(bytes)?; Ok(result) } /// Reads an `u32` value from the wrapped byte sequence and returns it. /// /// # Example /// ```rust /// # use sshkeys; /// let data = vec![0, 0, 0, 42]; /// let mut reader = sshkeys::Reader::new(&data); /// let num = reader.read_u32().unwrap(); /// assert_eq!(num, 42); /// ``` pub fn read_u32(&mut self) -> Result<u32> { if self.offset >= self.inner.len() { return Err(Error::with_kind(ErrorKind::UnexpectedEof)); } let slice = &self.inner[self.offset..]; if slice.len() < 4 { return Err(Error::with_kind(ErrorKind::InvalidFormat)); } self.offset += 4; let value = BigEndian::read_u32(&slice[..4]); Ok(value) } /// Reads an `u64` value from the wrapped byte sequence and returns it. /// /// # Example /// ```rust /// # use sshkeys; /// let data = vec![0, 0, 0, 0, 0, 0, 0, 42]; /// let mut reader = sshkeys::Reader::new(&data); /// let num = reader.read_u64().unwrap(); /// assert_eq!(num, 42); /// ``` pub fn read_u64(&mut self) -> Result<u64> { if self.offset >= self.inner.len() { return Err(Error::with_kind(ErrorKind::UnexpectedEof)); } let slice = &self.inner[self.offset..]; if slice.len() < 8 { return Err(Error::with_kind(ErrorKind::InvalidFormat)); } self.offset += 8; let value = BigEndian::read_u64(&slice[..8]); Ok(value) } }