1 // Bitcoin Hashes Library
2 // Written in 2018 by
3 //   Andrew Poelstra <apoelstra@wpsoftware.net>
4 //
5 // To the extent possible under law, the author(s) have dedicated all
6 // copyright and related and neighboring rights to this software to
7 // the public domain worldwide. This software is distributed without
8 // any warranty.
9 //
10 // You should have received a copy of the CC0 Public Domain Dedication
11 // along with this software.
12 // If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
13 //
14 
15 //! # Hex encoding and decoding
16 //!
17 
18 #[cfg(any(feature = "std", feature = "alloc"))]
19 use alloc::{string::String, vec::Vec};
20 #[cfg(feature = "alloc")]
21 use alloc::format;
22 
23 use core::{fmt, str};
24 use Hash;
25 
26 /// Hex decoding error
27 #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
28 pub enum Error {
29     /// non-hexadecimal character
30     InvalidChar(u8),
31     /// purported hex string had odd length
32     OddLengthString(usize),
33     /// tried to parse fixed-length hash from a string with the wrong type (expected, got)
34     InvalidLength(usize, usize),
35 }
36 
37 impl fmt::Display for Error {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result38     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
39         match *self {
40             Error::InvalidChar(ch) => write!(f, "invalid hex character {}", ch),
41             Error::OddLengthString(ell) => write!(f, "odd hex string length {}", ell),
42             Error::InvalidLength(ell, ell2) => write!(f, "bad hex string length {} (expected {})", ell2, ell),
43         }
44     }
45 }
46 
47 /// Trait for objects that can be serialized as hex strings
48 #[cfg(any(test, feature = "std", feature = "alloc"))]
49 pub trait ToHex {
50     /// Hex representation of the object
to_hex(&self) -> String51     fn to_hex(&self) -> String;
52 }
53 
54 /// Trait for objects that can be deserialized from hex strings
55 pub trait FromHex: Sized {
56     /// Produce an object from a byte iterator
from_byte_iter<I>(iter: I) -> Result<Self, Error> where I: Iterator<Item=Result<u8, Error>> + ExactSizeIterator + DoubleEndedIterator57     fn from_byte_iter<I>(iter: I) -> Result<Self, Error>
58         where I: Iterator<Item=Result<u8, Error>> +
59             ExactSizeIterator +
60             DoubleEndedIterator;
61 
62     /// Produce an object from a hex string
from_hex(s: &str) -> Result<Self, Error>63     fn from_hex(s: &str) -> Result<Self, Error> {
64         Self::from_byte_iter(HexIterator::new(s)?)
65     }
66 }
67 
68 #[cfg(any(test, feature = "std", feature = "alloc"))]
69 impl<T: fmt::LowerHex> ToHex for T {
70     /// Outputs the hash in hexadecimal form
to_hex(&self) -> String71     fn to_hex(&self) -> String {
72         format!("{:x}", self)
73     }
74 }
75 
76 impl<T: Hash> FromHex for T {
from_byte_iter<I>(iter: I) -> Result<Self, Error> where I: Iterator<Item=Result<u8, Error>> + ExactSizeIterator + DoubleEndedIterator,77     fn from_byte_iter<I>(iter: I) -> Result<Self, Error>
78         where I: Iterator<Item=Result<u8, Error>> +
79             ExactSizeIterator +
80             DoubleEndedIterator,
81     {
82         let inner;
83         if Self::DISPLAY_BACKWARD {
84             inner = T::Inner::from_byte_iter(iter.rev())?;
85         } else {
86             inner = T::Inner::from_byte_iter(iter)?;
87         }
88         Ok(Hash::from_inner(inner))
89     }
90 }
91 
92 /// Iterator over a hex-encoded string slice which decodes hex and yields bytes.
93 pub struct HexIterator<'a> {
94     /// The `Bytes` iterator whose next two bytes will be decoded to yield
95     /// the next byte.
96     iter: str::Bytes<'a>,
97 }
98 
99 impl<'a> HexIterator<'a> {
100     /// Constructs a new `HexIterator` from a string slice. If the string is of
101     /// odd length it returns an error.
new(s: &'a str) -> Result<HexIterator<'a>, Error>102     pub fn new(s: &'a str) -> Result<HexIterator<'a>, Error> {
103         if s.len() % 2 != 0 {
104             Err(Error::OddLengthString(s.len()))
105         } else {
106             Ok(HexIterator { iter: s.bytes() })
107         }
108     }
109 }
110 
chars_to_hex(hi: u8, lo: u8) -> Result<u8, Error>111 fn chars_to_hex(hi: u8, lo: u8) -> Result<u8, Error> {
112     let hih = (hi as char)
113         .to_digit(16)
114         .ok_or(Error::InvalidChar(hi))?;
115     let loh = (lo as char)
116         .to_digit(16)
117         .ok_or(Error::InvalidChar(lo))?;
118 
119     let ret = (hih << 4) + loh;
120     Ok(ret as u8)
121 }
122 
123 impl<'a> Iterator for HexIterator<'a> {
124     type Item = Result<u8, Error>;
125 
next(&mut self) -> Option<Result<u8, Error>>126     fn next(&mut self) -> Option<Result<u8, Error>> {
127         let hi = self.iter.next()?;
128         let lo = self.iter.next().unwrap();
129         Some(chars_to_hex(hi, lo))
130     }
131 
size_hint(&self) -> (usize, Option<usize>)132     fn size_hint(&self) -> (usize, Option<usize>) {
133         let (min, max) = self.iter.size_hint();
134         (min / 2, max.map(|x| x /2))
135     }
136 }
137 
138 impl<'a> DoubleEndedIterator for HexIterator<'a> {
next_back(&mut self) -> Option<Result<u8, Error>>139     fn next_back(&mut self) -> Option<Result<u8, Error>> {
140         let lo = self.iter.next_back()?;
141         let hi = self.iter.next_back().unwrap();
142         Some(chars_to_hex(hi, lo))
143     }
144 }
145 
146 impl<'a> ExactSizeIterator for HexIterator<'a> {}
147 
148 /// Output hex into an object implementing `fmt::Write`, which is usually more
149 /// efficient than going through a `String` using `ToHex`.
format_hex(data: &[u8], f: &mut fmt::Formatter) -> fmt::Result150 pub fn format_hex(data: &[u8], f: &mut fmt::Formatter) -> fmt::Result {
151     let prec = f.precision().unwrap_or(2 * data.len());
152     let width = f.width().unwrap_or(2 * data.len());
153     for _ in (2 * data.len())..width {
154         f.write_str("0")?;
155     }
156     for ch in data.iter().take(prec / 2) {
157         write!(f, "{:02x}", *ch)?;
158     }
159     if prec < 2 * data.len() && prec % 2 == 1 {
160         write!(f, "{:x}", data[prec / 2] / 16)?;
161     }
162     Ok(())
163 }
164 
165 /// Output hex in reverse order; used for Sha256dHash whose standard hex encoding
166 /// has the bytes reversed.
format_hex_reverse(data: &[u8], f: &mut fmt::Formatter) -> fmt::Result167 pub fn format_hex_reverse(data: &[u8], f: &mut fmt::Formatter) -> fmt::Result {
168     let prec = f.precision().unwrap_or(2 * data.len());
169     let width = f.width().unwrap_or(2 * data.len());
170     for _ in (2 * data.len())..width {
171         f.write_str("0")?;
172     }
173     for ch in data.iter().rev().take(prec / 2) {
174         write!(f, "{:02x}", *ch)?;
175     }
176     if prec < 2 * data.len() && prec % 2 == 1 {
177         write!(f, "{:x}", data[data.len() - 1 - prec / 2] / 16)?;
178     }
179     Ok(())
180 }
181 
182 #[cfg(any(test, feature = "alloc", feature = "std"))]
183 impl ToHex for [u8] {
to_hex(&self) -> String184     fn to_hex(&self) -> String {
185         use core::fmt::Write;
186         let mut ret = String::with_capacity(2 * self.len());
187         for ch in self {
188             write!(ret, "{:02x}", ch).expect("writing to string");
189         }
190         ret
191     }
192 }
193 
194 #[cfg(any(test, feature = "std", feature = "alloc"))]
195 impl FromHex for Vec<u8> {
from_byte_iter<I>(iter: I) -> Result<Self, Error> where I: Iterator<Item=Result<u8, Error>> + ExactSizeIterator + DoubleEndedIterator,196     fn from_byte_iter<I>(iter: I) -> Result<Self, Error>
197         where I: Iterator<Item=Result<u8, Error>> +
198             ExactSizeIterator +
199             DoubleEndedIterator,
200     {
201         iter.collect()
202     }
203 }
204 
205 macro_rules! impl_fromhex_array {
206     ($len:expr) => {
207         impl FromHex for [u8; $len] {
208             fn from_byte_iter<I>(iter: I) -> Result<Self, Error>
209                 where I: Iterator<Item=Result<u8, Error>> +
210                     ExactSizeIterator +
211                     DoubleEndedIterator,
212             {
213                 if iter.len() == $len {
214                     let mut ret = [0; $len];
215                     for (n, byte) in iter.enumerate() {
216                         ret[n] = byte?;
217                     }
218                     Ok(ret)
219                 } else {
220                     Err(Error::InvalidLength(2 * $len, 2 * iter.len()))
221                 }
222             }
223         }
224     }
225 }
226 
227 impl_fromhex_array!(2);
228 impl_fromhex_array!(4);
229 impl_fromhex_array!(6);
230 impl_fromhex_array!(8);
231 impl_fromhex_array!(10);
232 impl_fromhex_array!(12);
233 impl_fromhex_array!(14);
234 impl_fromhex_array!(16);
235 impl_fromhex_array!(20);
236 impl_fromhex_array!(24);
237 impl_fromhex_array!(28);
238 impl_fromhex_array!(32);
239 impl_fromhex_array!(33);
240 impl_fromhex_array!(64);
241 impl_fromhex_array!(65);
242 impl_fromhex_array!(128);
243 impl_fromhex_array!(256);
244 impl_fromhex_array!(384);
245 impl_fromhex_array!(512);
246 
247 #[cfg(test)]
248 mod tests {
249     use super::*;
250 
251     use core::fmt;
252 
253     #[test]
hex_roundtrip()254     fn hex_roundtrip() {
255         let expected = "0123456789abcdef";
256         let expected_up = "0123456789ABCDEF";
257 
258         let parse: Vec<u8> = FromHex::from_hex(expected).expect("parse lowercase string");
259         assert_eq!(parse, vec![0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef]);
260         let ser = parse.to_hex();
261         assert_eq!(ser, expected);
262 
263         let parse: Vec<u8> = FromHex::from_hex(expected_up).expect("parse uppercase string");
264         assert_eq!(parse, vec![0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef]);
265         let ser = parse.to_hex();
266         assert_eq!(ser, expected);
267 
268         let parse: [u8; 8] = FromHex::from_hex(expected_up).expect("parse uppercase string");
269         assert_eq!(parse, [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef]);
270         let ser = parse.to_hex();
271         assert_eq!(ser, expected);
272     }
273 
274     #[test]
hex_truncate()275     fn hex_truncate() {
276         struct HexBytes(Vec<u8>);
277         impl fmt::LowerHex for HexBytes {
278             fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
279                 format_hex(&self.0, f)
280             }
281         }
282 
283         let bytes = HexBytes(vec![1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
284 
285         assert_eq!(
286             format!("{:x}", bytes),
287             "0102030405060708090a"
288         );
289 
290         for i in 0..20 {
291             assert_eq!(
292                 format!("{:.prec$x}", bytes, prec = i),
293                 &"0102030405060708090a"[0..i]
294             );
295         }
296 
297         assert_eq!(
298             format!("{:25x}", bytes),
299             "000000102030405060708090a"
300         );
301         assert_eq!(
302             format!("{:26x}", bytes),
303             "0000000102030405060708090a"
304         );
305     }
306 
307     #[test]
hex_truncate_rev()308     fn hex_truncate_rev() {
309         struct HexBytes(Vec<u8>);
310         impl fmt::LowerHex for HexBytes {
311             fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
312                 format_hex_reverse(&self.0, f)
313             }
314         }
315 
316         let bytes = HexBytes(vec![1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
317 
318         assert_eq!(
319             format!("{:x}", bytes),
320             "0a090807060504030201"
321         );
322 
323         for i in 0..20 {
324             assert_eq!(
325                 format!("{:.prec$x}", bytes, prec = i),
326                 &"0a090807060504030201"[0..i]
327             );
328         }
329 
330         assert_eq!(
331             format!("{:25x}", bytes),
332             "000000a090807060504030201"
333         );
334         assert_eq!(
335             format!("{:26x}", bytes),
336             "0000000a090807060504030201"
337         );
338     }
339 
340     #[test]
hex_error()341     fn hex_error() {
342         let oddlen = "0123456789abcdef0";
343         let badchar1 = "Z123456789abcdef";
344         let badchar2 = "012Y456789abcdeb";
345         let badchar3 = "«23456789abcdef";
346 
347         assert_eq!(
348             Vec::<u8>::from_hex(oddlen),
349             Err(Error::OddLengthString(17))
350         );
351         assert_eq!(
352             <[u8; 4]>::from_hex(oddlen),
353             Err(Error::OddLengthString(17))
354         );
355         assert_eq!(
356             <[u8; 8]>::from_hex(oddlen),
357             Err(Error::OddLengthString(17))
358         );
359         assert_eq!(
360             Vec::<u8>::from_hex(badchar1),
361             Err(Error::InvalidChar(b'Z'))
362         );
363         assert_eq!(
364             Vec::<u8>::from_hex(badchar2),
365             Err(Error::InvalidChar(b'Y'))
366         );
367         assert_eq!(
368             Vec::<u8>::from_hex(badchar3),
369             Err(Error::InvalidChar(194))
370         );
371     }
372 }
373 
374