diff options
-rw-r--r-- | openpgp/src/conversions.rs | 114 | ||||
-rw-r--r-- | openpgp/src/fingerprint.rs | 2 | ||||
-rw-r--r-- | openpgp/src/keyid.rs | 2 | ||||
-rw-r--r-- | openpgp/src/lib.rs | 62 | ||||
-rw-r--r-- | openpgp/src/mpis.rs | 2 | ||||
-rw-r--r-- | openpgp/src/parse/hashed_reader.rs | 7 | ||||
-rw-r--r-- | openpgp/src/parse/parse.rs | 21 | ||||
-rw-r--r-- | openpgp/src/s2k.rs | 2 | ||||
-rw-r--r-- | openpgp/src/signature.rs | 5 |
9 files changed, 138 insertions, 79 deletions
diff --git a/openpgp/src/conversions.rs b/openpgp/src/conversions.rs index b2dfc549..46f7171c 100644 --- a/openpgp/src/conversions.rs +++ b/openpgp/src/conversions.rs @@ -52,3 +52,117 @@ impl Duration for time::Duration { Ok(secs as u32) } } + + +/// A helpful debugging function. +#[allow(dead_code)] +pub(crate) fn to_hex(s: &[u8], pretty: bool) -> String { + use std::fmt::Write; + + let mut result = String::new(); + for (i, b) in s.iter().enumerate() { + // Add spaces every four digits to make the output more + // readable. + if pretty && i > 0 && i % 2 == 0 { + write!(&mut result, " ").unwrap(); + } + write!(&mut result, "{:02X}", b).unwrap(); + } + result +} + +/// A helpful function for converting a hexadecimal string to binary. +/// This function skips whitespace if `skip_whipspace` is set. +pub(crate) fn from_hex(hex: &str, skip_whitespace: bool) -> Option<Vec<u8>> { + let nibbles = hex.as_bytes().iter().filter_map(|x| { + match *x as char { + '0' => Some(0u8), + '1' => Some(1u8), + '2' => Some(2u8), + '3' => Some(3u8), + '4' => Some(4u8), + '5' => Some(5u8), + '6' => Some(6u8), + '7' => Some(7u8), + '8' => Some(8u8), + '9' => Some(9u8), + 'a' | 'A' => Some(10u8), + 'b' | 'B' => Some(11u8), + 'c' | 'C' => Some(12u8), + 'd' | 'D' => Some(13u8), + 'e' | 'E' => Some(14u8), + 'f' | 'F' => Some(15u8), + ' ' if skip_whitespace => None, + _ => Some(255u8), + } + }).collect::<Vec<u8>>(); + + if nibbles.iter().any(|&b| b == 255u8) { + // Not a hex character. + return None; + } + + // We need an even number of nibbles. + if nibbles.len() % 2 != 0 { + return None; + } + + let bytes = nibbles.chunks(2).map(|nibbles| { + (nibbles[0] << 4) | nibbles[1] + }).collect::<Vec<u8>>(); + + Some(bytes) +} + +#[cfg(test)] +mod test { + #[test] + fn from_hex() { + use super::from_hex as fh; + assert_eq!(fh("", false), Some(vec![])); + assert_eq!(fh("0", false), None); + assert_eq!(fh("00", false), Some(vec![0x00])); + assert_eq!(fh("09", false), Some(vec![0x09])); + assert_eq!(fh("0f", false), Some(vec![0x0f])); + assert_eq!(fh("99", false), Some(vec![0x99])); + assert_eq!(fh("ff", false), Some(vec![0xff])); + assert_eq!(fh("000", false), None); + assert_eq!(fh("0000", false), Some(vec![0x00, 0x00])); + assert_eq!(fh("0009", false), Some(vec![0x00, 0x09])); + assert_eq!(fh("000f", false), Some(vec![0x00, 0x0f])); + assert_eq!(fh("0099", false), Some(vec![0x00, 0x99])); + assert_eq!(fh("00ff", false), Some(vec![0x00, 0xff])); + } + + #[test] + fn from_pretty_hex() { + use super::from_hex as fh; + assert_eq!(fh(" ", true), Some(vec![])); + assert_eq!(fh(" 0", true), None); + assert_eq!(fh(" 00", true), Some(vec![0x00])); + assert_eq!(fh(" 09", true), Some(vec![0x09])); + assert_eq!(fh(" 0f", true), Some(vec![0x0f])); + assert_eq!(fh(" 99", true), Some(vec![0x99])); + assert_eq!(fh(" ff", true), Some(vec![0xff])); + assert_eq!(fh(" 00 0", true), None); + assert_eq!(fh(" 00 00", true), Some(vec![0x00, 0x00])); + assert_eq!(fh(" 00 09", true), Some(vec![0x00, 0x09])); + assert_eq!(fh(" 00 0f", true), Some(vec![0x00, 0x0f])); + assert_eq!(fh(" 00 99", true), Some(vec![0x00, 0x99])); + assert_eq!(fh(" 00 ff", true), Some(vec![0x00, 0xff])); + } + + quickcheck! { + fn hex_roundtrip(data: Vec<u8>) -> bool { + let hex = super::to_hex(&data, false); + data == super::from_hex(&hex, false).unwrap() + } + } + + quickcheck! { + fn pretty_hex_roundtrip(data: Vec<u8>) -> bool { + let hex = super::to_hex(&data, true); + data == super::from_hex(&hex, true).unwrap() + } + } +} diff --git a/openpgp/src/fingerprint.rs b/openpgp/src/fingerprint.rs index 46b24bc3..1f090d83 100644 --- a/openpgp/src/fingerprint.rs +++ b/openpgp/src/fingerprint.rs @@ -43,7 +43,7 @@ impl Fingerprint { /// assert_eq!(fp.unwrap().to_hex(), hex); /// ``` pub fn from_hex(hex: &str) -> Option<Fingerprint> { - Some(Fingerprint::from_bytes(&::from_hex(hex, true)?[..])) + Some(Fingerprint::from_bytes(&::conversions::from_hex(hex, true)?[..])) } /// Returns a reference to the raw Fingerprint. diff --git a/openpgp/src/keyid.rs b/openpgp/src/keyid.rs index e112779b..ae51d27e 100644 --- a/openpgp/src/keyid.rs +++ b/openpgp/src/keyid.rs @@ -57,7 +57,7 @@ impl KeyID { /// Reads a hex-encoded Key ID. pub fn from_hex(hex: &str) -> Option<KeyID> { - let bytes = ::from_hex(hex, true)?; + let bytes = ::conversions::from_hex(hex, true)?; // A KeyID is exactly 8 bytes long. if bytes.len() == 8 { diff --git a/openpgp/src/lib.rs b/openpgp/src/lib.rs index c43fe89e..a7e1401b 100644 --- a/openpgp/src/lib.rs +++ b/openpgp/src/lib.rs @@ -224,66 +224,6 @@ pub enum Error { #[fail(display = "Index out of range")] IndexOutOfRange, } - -/// A helpful debugging function. -#[allow(dead_code)] -fn to_hex(s: &[u8], pretty: bool) -> String { - use std::fmt::Write; - - let mut result = String::new(); - for (i, b) in s.iter().enumerate() { - // Add spaces every four digits to make the output more - // readable. - if pretty && i > 0 && i % 2 == 0 { - write!(&mut result, " ").unwrap(); - } - write!(&mut result, "{:02X}", b).unwrap(); - } - result -} - -/// A helpful function for converting a hexadecimal string to binary. -/// This function skips whitespace if `skip_whipspace` is set. -fn from_hex(hex: &str, skip_whitespace: bool) -> Option<Vec<u8>> { - let nibbles = hex.as_bytes().iter().filter_map(|x| { - match *x as char { - '0' => Some(0u8), - '1' => Some(1u8), - '2' => Some(2u8), - '3' => Some(3u8), - '4' => Some(4u8), - '5' => Some(5u8), - '6' => Some(6u8), - '7' => Some(7u8), - '8' => Some(8u8), - '9' => Some(9u8), - 'a' | 'A' => Some(10u8), - 'b' | 'B' => Some(11u8), - 'c' | 'C' => Some(12u8), - 'd' | 'D' => Some(13u8), - 'e' | 'E' => Some(14u8), - 'f' | 'F' => Some(15u8), - ' ' if skip_whitespace => None, - _ => Some(255u8), - } - }).collect::<Vec<u8>>(); - - if nibbles.iter().any(|&b| b == 255u8) { - // Not a hex character. - return None; - } - - // We need an even number of nibbles. - if nibbles.len() % 2 != 0 { - return None; - } - - let bytes = nibbles.chunks(2).map(|nibbles| { - (nibbles[0] << 4) | nibbles[1] - }).collect::<Vec<u8>>(); - - Some(bytes) -} /// Holds an unknown packet. /// @@ -767,7 +707,7 @@ fn hash_file_test() { hash.digest(&mut digest); assert_eq!(*expected_algo, algo); - assert_eq!(*expected_digest, ::to_hex(&digest[..], false)); + assert_eq!(*expected_digest, ::conversions::to_hex(&digest[..], false)); } } diff --git a/openpgp/src/mpis.rs b/openpgp/src/mpis.rs index bb52e9fa..44caa0ad 100644 --- a/openpgp/src/mpis.rs +++ b/openpgp/src/mpis.rs @@ -54,7 +54,7 @@ impl MPI { impl fmt::Debug for MPI { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_fmt(format_args!( - "{} bits: {}", self.bits, ::to_hex(&*self.value, true))) + "{} bits: {}", self.bits, ::conversions::to_hex(&*self.value, true))) } } diff --git a/openpgp/src/parse/hashed_reader.rs b/openpgp/src/parse/hashed_reader.rs index 74cf3b35..b6000f46 100644 --- a/openpgp/src/parse/hashed_reader.rs +++ b/openpgp/src/parse/hashed_reader.rs @@ -51,7 +51,7 @@ impl Cookie { if TRACE { eprintln!("{} hash_update: NOT hashing {} bytes: {}.", indent(cmp::max(0, self.level.unwrap_or(0)) as u8), - data.len(), ::to_hex(data, true)); + data.len(), ::conversions::to_hex(data, true)); } return; @@ -63,7 +63,7 @@ impl Cookie { indent(cmp::max(0, self.level.unwrap_or(0)) as u8), self.hashes_for, algo, data.len()); if false { - eprintln!("{}", ::to_hex(data, true)); + eprintln!("{}", ::conversions::to_hex(data, true)); } } h.update(data); @@ -238,7 +238,8 @@ mod test { hash.digest(&mut digest); assert_eq!(digest, - &::from_hex(test.expected[i], true).unwrap()[..], + &::conversions::from_hex(test.expected[i], true) + .unwrap()[..], "{}: Algo: {:?}", i, algo); } } diff --git a/openpgp/src/parse/parse.rs b/openpgp/src/parse/parse.rs index 3dbd3dc6..95f706d7 100644 --- a/openpgp/src/parse/parse.rs +++ b/openpgp/src/parse/parse.rs @@ -1006,10 +1006,10 @@ fn one_pass_sig_test () { } else if let Packet::Signature(ref sig) = pp.packet { eprintln!(" {}:\n prefix: expected: {}, in sig: {}", test.filename, - ::to_hex(&test.hash_prefix[sigs][..], false), - ::to_hex(&sig.hash_prefix[..], false)); + ::conversions::to_hex(&test.hash_prefix[sigs][..], false), + ::conversions::to_hex(&sig.hash_prefix[..], false)); eprintln!(" computed hash: {}", - ::to_hex(&sig.computed_hash.as_ref().unwrap().1, false)); + ::conversions::to_hex(&sig.computed_hash.as_ref().unwrap().1, false)); assert_eq!(test.hash_prefix[sigs], sig.hash_prefix); assert_eq!(&test.hash_prefix[sigs][..], @@ -1511,7 +1511,7 @@ fn skesk_parser_test() { match skesk.decrypt(test.password) { Ok((_symm_algo, key)) => { - let key = ::to_hex(&key[..], false); + let key = ::conversions::to_hex(&key[..], false); assert_eq!(&key[..], &test.key_hex[..]); } Err(e) => { @@ -1552,7 +1552,7 @@ impl MPI { if TRACE { eprintln!("bits: {}, value: {}", - bits, ::to_hex(&value, true)); + bits, ::conversions::to_hex(&value, true)); } let unused_bits = bytes * 8 - bits; @@ -2844,7 +2844,7 @@ impl<'a> PacketParser<'a> { && header[bl - 1] == header[bl + 1]) { return Err(Error::InvalidSessionKey( format!("Last two 16-bit quantities don't match: {}", - ::to_hex(&header[..], false))) + ::conversions::to_hex(&header[..], false))) .into()); } } @@ -2948,7 +2948,8 @@ mod test { loop { if let Packet::SEIP(_) = pp.packet { - let key = ::from_hex(test.key_hex, false).unwrap(); + let key = ::conversions::from_hex(test.key_hex, false) + .unwrap(); pp.decrypt(test.algo, &key[..]).unwrap(); @@ -3011,7 +3012,8 @@ mod test { loop { if let Packet::SEIP(_) = pp.packet { - let key = ::from_hex(test.key_hex, false).unwrap(); + let key = ::conversions::from_hex(test.key_hex, false) + .unwrap(); pp.decrypt(test.algo, &key[..]).unwrap(); @@ -3088,7 +3090,8 @@ mod test { match pp.packet { Packet::SEIP(_) => { - let key = ::from_hex(test.key_hex, false).unwrap(); + let key = ::conversions::from_hex(test.key_hex, false) + .unwrap(); pp.decrypt(test.algo, &key[..]).unwrap(); }, Packet::Literal(_) => { diff --git a/openpgp/src/s2k.rs b/openpgp/src/s2k.rs index d12d922e..1d80b78a 100644 --- a/openpgp/src/s2k.rs +++ b/openpgp/src/s2k.rs @@ -256,7 +256,7 @@ impl Arbitrary for S2K { mod tests { use super::*; - use to_hex; + use conversions::to_hex; use SymmetricAlgorithm; use Packet; use parse::PacketParser; diff --git a/openpgp/src/signature.rs b/openpgp/src/signature.rs index da52d060..d2bbb2cd 100644 --- a/openpgp/src/signature.rs +++ b/openpgp/src/signature.rs @@ -85,10 +85,11 @@ impl fmt::Debug for Signature { .field("hash_algo", &self.hash_algo) .field("hashed_area", &self.hashed_area) .field("unhashed_area", &self.unhashed_area) - .field("hash_prefix", &::to_hex(&self.hash_prefix, false)) + .field("hash_prefix", + &::conversions::to_hex(&self.hash_prefix, false)) .field("computed_hash", &if let Some((algo, ref hash)) = self.computed_hash { - Some((algo, ::to_hex(&hash[..], false))) + Some((algo, ::conversions::to_hex(&hash[..], false))) } else { None }) |