diff options
author | Neal H. Walfield <neal@pep.foundation> | 2018-05-17 12:32:14 +0200 |
---|---|---|
committer | Neal H. Walfield <neal@pep.foundation> | 2018-05-17 12:32:14 +0200 |
commit | 1406b481db870b13e66ee542d21159e32dd99d56 (patch) | |
tree | 248bb751ee65b4bf3d2da88d1d9772d0fddadca0 /openpgp/src/keyid.rs | |
parent | df4549921627c0706c32abffe68806c2afb65806 (diff) |
openpgp: Move KeyID and Fingerprint details to their own modules
- Move the KeyID and Fingerprint implementation details to their own
modules.
Diffstat (limited to 'openpgp/src/keyid.rs')
-rw-r--r-- | openpgp/src/keyid.rs | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/openpgp/src/keyid.rs b/openpgp/src/keyid.rs new file mode 100644 index 00000000..976ad7ba --- /dev/null +++ b/openpgp/src/keyid.rs @@ -0,0 +1,135 @@ +use std::fmt; + +use KeyID; + +impl fmt::Display for KeyID { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.to_string()) + } +} + +impl fmt::Debug for KeyID { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_tuple("KeyID") + .field(&self.to_string()) + .finish() + } +} + +impl From<KeyID> for Vec<u8> { + fn from(id: KeyID) -> Self { + let mut r = Vec::with_capacity(8); + match id { + KeyID::V4(ref b) => r.extend_from_slice(b), + KeyID::Invalid(ref b) => r.extend_from_slice(b), + } + r + } +} + +impl KeyID { + /// Converts a u64 to a KeyID. + pub fn new(data: u64) -> KeyID { + let bytes = [ + (data >> (7 * 8)) as u8, + (data >> (6 * 8)) as u8, + (data >> (5 * 8)) as u8, + (data >> (4 * 8)) as u8, + (data >> (3 * 8)) as u8, + (data >> (2 * 8)) as u8, + (data >> (1 * 8)) as u8, + (data >> (0 * 8)) as u8 + ]; + Self::from_bytes(&bytes[..]) + } + + /// Reads a binary key ID. + pub fn from_bytes(raw: &[u8]) -> KeyID { + if raw.len() == 8 { + let mut keyid : [u8; 8] = Default::default(); + keyid.copy_from_slice(raw); + KeyID::V4(keyid) + } else { + KeyID::Invalid(raw.to_vec().into_boxed_slice()) + } + } + + /// Reads a hex-encoded Key ID. + pub fn from_hex(hex: &str) -> Option<KeyID> { + let bytes = ::from_hex(hex, true)?; + + // A KeyID is exactly 8 bytes long. + if bytes.len() != 8 { + return None; + } + + Some(KeyID::from_bytes(&bytes[..])) + } + + /// Returns a reference to the raw KeyID. + pub fn as_slice(&self) -> &[u8] { + match self { + &KeyID::V4(ref id) => id, + &KeyID::Invalid(ref id) => id, + } + } + + /// Converts the key ID to its standard representation. + /// + /// Returns the fingerprint suitable for human consumption. + pub fn to_string(&self) -> String { + self.convert_to_string(true) + } + + /// Converts the key ID to a hexadecimal number. + pub fn to_hex(&self) -> String { + self.convert_to_string(false) + } + + /// Common code for the above functions. + fn convert_to_string(&self, pretty: bool) -> String { + let raw = match self { + &KeyID::V4(ref fp) => &fp[..], + &KeyID::Invalid(ref fp) => &fp[..], + }; + + // We currently only handle V4 key IDs, which look like: + // + // AACB 3243 6300 52D9 + // + // Since we have no idea how to format an invalid key ID, just + // format it like a V4 fingerprint and hope for the best. + + let mut output = Vec::with_capacity( + // Each byte results in to hex characters. + raw.len() * 2 + + if pretty { + // Every 2 bytes of output, we insert a space. + raw.len() / 2 + } else { 0 }); + + for (i, b) in raw.iter().enumerate() { + if pretty && i > 0 && i % 2 == 0 { + output.push(' ' as u8); + } + + let top = b >> 4; + let bottom = b & 0xFu8; + + if top < 10u8 { + output.push('0' as u8 + top) + } else { + output.push('A' as u8 + (top - 10u8)) + } + + if bottom < 10u8 { + output.push('0' as u8 + bottom) + } else { + output.push('A' as u8 + (bottom - 10u8)) + } + } + + // We know the content is valid UTF-8. + String::from_utf8(output).unwrap() + } +} |