summaryrefslogtreecommitdiffstats
path: root/openpgp/src/fingerprint.rs
diff options
context:
space:
mode:
authorNeal H. Walfield <neal@pep.foundation>2018-05-17 12:32:14 +0200
committerNeal H. Walfield <neal@pep.foundation>2018-05-17 12:32:14 +0200
commit1406b481db870b13e66ee542d21159e32dd99d56 (patch)
tree248bb751ee65b4bf3d2da88d1d9772d0fddadca0 /openpgp/src/fingerprint.rs
parentdf4549921627c0706c32abffe68806c2afb65806 (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/fingerprint.rs')
-rw-r--r--openpgp/src/fingerprint.rs128
1 files changed, 128 insertions, 0 deletions
diff --git a/openpgp/src/fingerprint.rs b/openpgp/src/fingerprint.rs
new file mode 100644
index 00000000..c33d995b
--- /dev/null
+++ b/openpgp/src/fingerprint.rs
@@ -0,0 +1,128 @@
+use std::fmt;
+
+use Fingerprint;
+use KeyID;
+
+impl fmt::Display for Fingerprint {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{}", self.to_string())
+ }
+}
+
+impl fmt::Debug for Fingerprint {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_tuple("Fingerprint")
+ .field(&self.to_string())
+ .finish()
+ }
+}
+
+impl Fingerprint {
+ /// Reads a binary fingerprint.
+ pub fn from_bytes(raw: &[u8]) -> Fingerprint {
+ if raw.len() == 20 {
+ let mut fp : [u8; 20] = Default::default();
+ fp.copy_from_slice(raw);
+ Fingerprint::V4(fp)
+ } else {
+ Fingerprint::Invalid(raw.to_vec().into_boxed_slice())
+ }
+ }
+
+ /// Reads a hexadecimal fingerprint.
+ ///
+ /// This function ignores whitespace.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// # use openpgp::Fingerprint;
+ /// let hex = "3E8877C877274692975189F5D03F6F865226FE8B";
+ /// let fp = Fingerprint::from_hex(hex);
+ /// assert!(fp.is_some());
+ /// assert_eq!(fp.unwrap().to_hex(), hex);
+ /// ```
+ pub fn from_hex(hex: &str) -> Option<Fingerprint> {
+ Some(Fingerprint::from_bytes(&::from_hex(hex, true)?[..]))
+ }
+
+ /// Converts the fingerprint to its standard representation.
+ ///
+ /// Returns the fingerprint suitable for human consumption.
+ pub fn to_string(&self) -> String {
+ self.convert_to_string(true)
+ }
+
+ /// Converts the fingerprint 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 {
+ &Fingerprint::V4(ref fp) => &fp[..],
+ &Fingerprint::Invalid(ref fp) => &fp[..],
+ };
+
+ // We currently only handle V4 fingerprints, which look like:
+ //
+ // 8F17 7771 18A3 3DDA 9BA4 8E62 AACB 3243 6300 52D9
+ //
+ // Since we have no idea how to format an invalid fingerprint,
+ // 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
+ // After 5 groups, there is another space.
+ + raw.len() / 10
+ } else { 0 });
+
+ for (i, b) in raw.iter().enumerate() {
+ if pretty && i > 0 && i % 2 == 0 {
+ output.push(' ' as u8);
+ }
+
+ if pretty && i > 0 && i % 10 == 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()
+ }
+
+ /// Converts the fingerprint to a key ID.
+ pub fn to_keyid(&self) -> KeyID {
+ match self {
+ &Fingerprint::V4(ref fp) =>
+ KeyID::from_bytes(&fp[fp.len() - 8..]),
+ &Fingerprint::Invalid(ref fp) => {
+ if fp.len() < 8 {
+ KeyID::from_bytes(&[0; 8])
+ } else {
+ KeyID::from_bytes(&fp[fp.len() - 8..])
+ }
+ }
+ }
+ }
+}