diff --git a/Cargo.toml b/Cargo.toml index 5582d27..0fa2cc4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,3 @@ -cargo-features = ["edition"] - [package] authors = ["Without Boats "] description = "bridge non-PGP system to PGP data format" @@ -11,21 +9,42 @@ version = "0.4.0" repository = "https://github.com/withoutboats/pbp" [dependencies] -base64 = "0.9.2" -byteorder = "1.1.0" -digest = "0.7.0" -sha1 = "0.2.0" -typenum = "1.9.0" -failure = "0.1.1" -bitflags = "1.0.1" +base64 = "0.11" +byteorder = "1" +digest = "0.8" +sha1 = "0.6" +typenum = "1.11" +failure = "0.1" +bitflags = "1.2" +rand = "0.6" +sha2 = "0.8" [dependencies.ed25519-dalek] -version = "0.7.0" +version = "0.9" optional = true [features] dalek = ["ed25519-dalek"] [dev-dependencies] -rand = "0.5.4" -sha2 = "0.6.0" +ed25519-dalek = "0.9" + +[[example]] +required-features = ["dalek"] +name = "print" +path = "examples/print.rs" + +[[example]] +required-features = ["dalek"] +name = "read_sig" +path = "examples/read_sig.rs" + +[[example]] +required-features = ["dalek"] +name = "round_trip" +path = "examples/round_trip.rs" + +[[example]] +required-features = ["dalek"] +name = "verify_sig" +path = "examples/verify_sig.rs" diff --git a/examples/print.rs b/examples/print.rs index b3045c3..4006c65 100644 --- a/examples/print.rs +++ b/examples/print.rs @@ -1,17 +1,30 @@ -extern crate rand; -extern crate sha2; extern crate ed25519_dalek as dalek; extern crate pbp; +extern crate rand; +extern crate sha2; + +use std::time::SystemTime; -use rand::OsRng; -use sha2::{Sha256, Sha512}; use dalek::Keypair; -use pbp::{PgpKey, KeyFlags}; +use failure::Error; +use pbp::{KeyFlags, PgpKey}; +use rand::rngs::OsRng; +use sha2::{Sha256, Sha512}; -fn main() { +fn main() -> Result<(), Error> { let mut cspring = OsRng::new().unwrap(); - let keypair = Keypair::generate::(&mut cspring); + let keypair = Keypair::generate::(&mut cspring); + let timestamp = SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH)? + .as_secs(); - let key = PgpKey::from_dalek::(&keypair, KeyFlags::NONE, "withoutboats"); + let key = PgpKey::from_dalek::( + &keypair, + KeyFlags::NONE, + timestamp as u32, + "withoutboats", + ); println!("{}", key); + + Ok(()) } diff --git a/examples/read_sig.rs b/examples/read_sig.rs index fb4e168..355ecfa 100644 --- a/examples/read_sig.rs +++ b/examples/read_sig.rs @@ -1,7 +1,7 @@ -extern crate rand; -extern crate sha2; extern crate ed25519_dalek as dalek; extern crate pbp; +extern crate rand; +extern crate sha2; use std::io::{self, BufRead}; @@ -20,14 +20,17 @@ fn main() { stdin.read_line(&mut buf).unwrap(); if buf.trim().starts_with("-----") && buf.trim().ends_with("-----") { armor.push_str(&buf); - if in_armor { break } - else { in_armor = true; } + if in_armor { + break; + } else { + in_armor = true; + } } else if in_armor { armor.push_str(&buf); } } - if PgpSig::from_ascii_armor(&armor).is_some() { + if PgpSig::from_ascii_armor(&armor).ok().is_some() { println!("Valid PGP Signature"); } } diff --git a/examples/round_trip.rs b/examples/round_trip.rs index e1497bf..180b325 100644 --- a/examples/round_trip.rs +++ b/examples/round_trip.rs @@ -1,24 +1,45 @@ -extern crate rand; -extern crate sha2; extern crate ed25519_dalek as dalek; extern crate pbp; +extern crate rand; +extern crate sha2; + +use std::time::SystemTime; -use rand::OsRng; -use sha2::{Sha256, Sha512}; use dalek::Keypair; -use pbp::{PgpKey, PgpSig, SigType, KeyFlags}; +use failure::Error; +use pbp::{KeyFlags, PgpKey, PgpSig, SigType}; +use rand::rngs::OsRng; +use sha2::Digest; +use sha2::{Sha256, Sha512}; const DATA: &[u8] = b"How will I ever get out of this labyrinth?"; -fn main() { +fn main() -> Result<(), Error> { let mut cspring = OsRng::new().unwrap(); - let keypair = Keypair::generate::(&mut cspring); - - let key = PgpKey::from_dalek::(&keypair, KeyFlags::SIGN, "withoutboats"); - let sig = PgpSig::from_dalek::(&keypair, DATA, key.fingerprint(), SigType::BinaryDocument); - if sig.verify_dalek::(DATA, &keypair.public) { + let keypair = Keypair::generate::(&mut cspring); + let timestamp = SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH)? + .as_secs(); + let key = PgpKey::from_dalek::( + &keypair, + KeyFlags::NONE, + timestamp as u32, + "withoutboats", + ); + let sig = PgpSig::from_dalek::( + &keypair, + DATA, + key.fingerprint(), + SigType::BinaryDocument, + timestamp as u32, + ); + if sig.verify_dalek::(&keypair.public, |hasher| { + hasher.input(DATA); + }) { println!("Verified successfully."); } else { println!("Could not verify."); } + + Ok(()) } diff --git a/examples/verify_sig.rs b/examples/verify_sig.rs index 839d5ce..0f74ae9 100644 --- a/examples/verify_sig.rs +++ b/examples/verify_sig.rs @@ -1,5 +1,3 @@ -#![feature(fs_read_write)] - extern crate pbp; extern crate sha2; @@ -7,21 +5,24 @@ use std::env; use std::fs; use std::path::PathBuf; -use sha2::{Sha256, Sha512}; use pbp::{PgpKey, PgpSig}; +use sha2::Digest; +use sha2::{Sha256, Sha512}; fn main() { let root = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap()); let props = root.join("examples").join("props"); - let sig: String = fs::read_string(props.join("sig.txt")).unwrap(); - let key: String = fs::read_string(props.join("key.txt")).unwrap(); - let data: String = fs::read_string(props.join("data.txt")).unwrap(); + let sig: String = fs::read_to_string(props.join("sig.txt")).unwrap(); + let key: String = fs::read_to_string(props.join("key.txt")).unwrap(); + let data: String = fs::read_to_string(props.join("data.txt")).unwrap(); let sig = PgpSig::from_ascii_armor(&sig).unwrap(); let key = PgpKey::from_ascii_armor(&key).unwrap(); - if sig.verify_dalek::(data.as_bytes(), &key.to_dalek().unwrap()) { + if sig.verify_dalek::(&key.to_dalek().unwrap(), |hasher| { + hasher.input(&data); + }) { println!("Verified signature."); } else { println!("Could not verify signature."); diff --git a/src/ascii_armor.rs b/src/ascii_armor.rs index 37a0fca..de3d757 100644 --- a/src/ascii_armor.rs +++ b/src/ascii_armor.rs @@ -15,7 +15,11 @@ impl From for PgpError { } // Convert from an ASCII armored string into binary data. -pub fn remove_ascii_armor(s: &str, expected_header: &str, expected_footer: &str) -> Result, PgpError> { +pub fn remove_ascii_armor( + s: &str, + expected_header: &str, + expected_footer: &str, +) -> Result, PgpError> { let lines: Vec<&str> = s.lines().map(|s| s.trim()).collect(); let header = lines.first().ok_or(InvalidAsciiArmor)?; let footer = lines.last().ok_or(InvalidAsciiArmor)?; @@ -28,12 +32,14 @@ pub fn remove_ascii_armor(s: &str, expected_header: &str, expected_footer: &str) || header.trim_matches('-').trim() != expected_header || footer.trim_matches('-').trim() != expected_footer { - return Err(InvalidAsciiArmor) + return Err(InvalidAsciiArmor); } // Find the end of the header section let end_of_headers = 1 + lines.iter().take_while(|l| !l.is_empty()).count(); - if end_of_headers >= lines.len() - 2 { return Err(InvalidAsciiArmor) } + if end_of_headers >= lines.len() - 2 { + return Err(InvalidAsciiArmor); + } // Decode the base64'd data let ascii_armored: String = lines[end_of_headers..lines.len() - 2].concat(); @@ -41,38 +47,36 @@ pub fn remove_ascii_armor(s: &str, expected_header: &str, expected_footer: &str) // Confirm checksum let cksum_line = &lines[lines.len() - 2]; - if !cksum_line.starts_with("=") || !cksum_line.len() > 1 { - return Err(InvalidAsciiArmor) + + if !cksum_line.starts_with("=") || !(cksum_line.len() > 1) { + return Err(InvalidAsciiArmor); } let mut cksum = [0; 4]; - base64::decode_config_slice(&cksum_line[1..], base64::STANDARD, &mut cksum[..])?; + base64::decode_config_slice(&cksum_line[1..], base64::URL_SAFE, &mut cksum[1..])?; + let mut cksum_buf = [0; 4]; + BigEndian::write_u32(&mut cksum_buf, checksum_crc24(&data)); + if BigEndian::read_u32(&cksum[..]) != checksum_crc24(&data) { - return Err(InvalidAsciiArmor) + return Err(InvalidAsciiArmor); } Ok(data) -} +} // Ascii armors data into the formatter pub fn ascii_armor( header: &'static str, footer: &'static str, - data: &[u8], - f: &mut fmt::Formatter -) -> fmt::Result -{ + data: &[u8], + f: &mut fmt::Formatter, +) -> fmt::Result { // Header Line f.write_str("-----")?; f.write_str(header)?; f.write_str("-----\n\n")?; // Base64'd data - let b64_cfg = base64::Config::new( - base64::CharacterSet::Standard, - true, - false, - base64::LineWrap::Wrap(76, base64::LineEnding::LF), - ); + let b64_cfg = base64::Config::new(base64::CharacterSet::Standard, true); f.write_str(&base64::encode_config(data, b64_cfg))?; f.write_str("\n=")?; @@ -101,7 +105,6 @@ fn checksum_crc24(data: &[u8]) -> u32 { crc ^= (byte as u32) << 16; for _ in 0..8 { - crc <<= 1; if (crc & 0x_0100_0000) != 0 { diff --git a/src/key.rs b/src/key.rs index 1827acc..ca37477 100644 --- a/src/key.rs +++ b/src/key.rs @@ -1,30 +1,28 @@ -use std::fmt::{self, Display, Debug}; +use std::fmt::{self, Debug, Display}; use std::ops::Range; use std::str::FromStr; use std::u16; -use byteorder::{ByteOrder, BigEndian}; +use byteorder::{BigEndian, ByteOrder}; use digest::Digest; use sha1::Sha1; use typenum::U32; -#[cfg(feature = "dalek")] use ed25519_dalek as dalek; -#[cfg(feature = "dalek")] use typenum::U64; +#[cfg(feature = "dalek")] +use ed25519_dalek as dalek; +#[cfg(feature = "dalek")] +use typenum::U64; use crate::ascii_armor::{ascii_armor, remove_ascii_armor}; -use crate::Base64; use crate::packet::*; +use crate::Base64; -use crate::{Fingerprint, Signature, KeyFlags}; -use crate::{PgpSig, SubPacket, SigType}; use crate::PgpError; +use crate::{Fingerprint, KeyFlags, Signature}; +use crate::{PgpSig, SigType, SubPacket}; // curve identifier (curve25519) -const CURVE: &[u8] = &[ - 0x09, 0x2b, 0x06, 0x01, - 0x04, 0x01, 0xda, 0x47, - 0x0f, 0x01 -]; +const CURVE: &[u8] = &[0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xda, 0x47, 0x0f, 0x01]; /// An OpenPGP formatted ed25519 public key. /// @@ -66,7 +64,8 @@ impl PgpKey { user_id: &str, unix_time: u32, sign: F, - ) -> PgpKey where + ) -> PgpKey + where Sha256: Digest, F: Fn(&[u8]) -> Signature, { @@ -92,12 +91,18 @@ impl PgpKey { SigType::PositiveCertification, unix_time, &[ - SubPacket { tag: 27, data: &[flags.bits()] }, - SubPacket { tag: 23, data: &[0x80] }, + SubPacket { + tag: 27, + data: &[flags.bits()], + }, + SubPacket { + tag: 23, + data: &[0x80], + }, ], sign, ); - + data.extend(signature_packet.as_bytes()); PgpKey { data } @@ -120,23 +125,29 @@ impl PgpKey { if !is_ed25519_valid(packet_data) { return Err(PgpError::UnsupportedPublicKeyPacket); } - + // convert public key packet to the old style header, // two byte length. All methods on PgpKey assume the // public key is in that format (e.g. the fingerprint // method). - let data = if bytes[0] != 0x99 { + let data = if bytes[0] != 0x99 { let mut packet = prepare_packet(6, |packet| packet.extend(packet_data)); packet.extend(&bytes[end..]); packet - } else { bytes.to_owned() }; + } else { + bytes.to_owned() + }; Ok(PgpKey { data }) } /// Construct a PgpKey from an ASCII armored string. pub fn from_ascii_armor(string: &str) -> Result { - let data = remove_ascii_armor(string, "BEGIN PGP PUBLIC KEY BLOCK", "END PGP PUBLIC KEY BLOCK")?; + let data = remove_ascii_armor( + string, + "BEGIN PGP PUBLIC KEY BLOCK", + "END PGP PUBLIC KEY BLOCK", + )?; PgpKey::from_bytes(&data) } @@ -159,14 +170,23 @@ impl PgpKey { #[cfg(feature = "dalek")] /// Create a PgpKey from a dalek Keypair and a user_id string. - pub fn from_dalek(keypair: &dalek::Keypair, flags: KeyFlags, unix_time: u32, user_id: &str) -> PgpKey + pub fn from_dalek( + keypair: &dalek::Keypair, + flags: KeyFlags, + unix_time: u32, + user_id: &str, + ) -> PgpKey where - Sha256: Digest, - Sha512: Digest, + Sha256: Digest + Default, + Sha512: Digest + Default, { - PgpKey::new::(keypair.public.as_bytes(), flags, user_id, unix_time, |data| { - keypair.sign::(data).to_bytes() - }) + PgpKey::new::( + keypair.public.as_bytes(), + flags, + user_id, + unix_time, + |data| keypair.sign::(data).to_bytes(), + ) } #[cfg(feature = "dalek")] @@ -180,7 +200,9 @@ impl PgpKey { impl Debug for PgpKey { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("PgpKey").field("key", &Base64(&self.data[..])).finish() + f.debug_struct("PgpKey") + .field("key", &Base64(&self.data[..])) + .finish() } } @@ -227,26 +249,36 @@ fn write_user_id_packet(data: &mut Vec, user_id: &str) -> Range { // will return the data of that public key packet. fn find_public_key_packet(data: &[u8]) -> Result<(&[u8], usize), PgpError> { let (init, len) = match data.first() { - Some(&0x98) => { - if data.len() < 2 { return Err(PgpError::InvalidPacketHeader) } + Some(&0x98) => { + if data.len() < 2 { + return Err(PgpError::InvalidPacketHeader); + } let len = data[1] as usize; (2, len) } - Some(&0x99) => { - if data.len() < 3 { return Err(PgpError::InvalidPacketHeader) } + Some(&0x99) => { + if data.len() < 3 { + return Err(PgpError::InvalidPacketHeader); + } let len = BigEndian::read_u16(&data[1..3]) as usize; (3, len) } - Some(&0x9a) => { - if data.len() < 5 { return Err(PgpError::InvalidPacketHeader) } + Some(&0x9a) => { + if data.len() < 5 { + return Err(PgpError::InvalidPacketHeader); + } let len = BigEndian::read_u32(&data[1..5]) as usize; - if len > u16::MAX as usize { return Err(PgpError::UnsupportedPacketLength) } + if len > u16::MAX as usize { + return Err(PgpError::UnsupportedPacketLength); + } (5, len) } - _ => return Err(PgpError::UnsupportedPacketLength) + _ => return Err(PgpError::UnsupportedPacketLength), }; let end = init + len; - if data.len() < end { return Err(PgpError::InvalidPacketHeader) } + if data.len() < end { + return Err(PgpError::InvalidPacketHeader); + } Ok((&data[init..end], end)) } diff --git a/src/lib.rs b/src/lib.rs index 28cb694..ed258c7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,11 +7,12 @@ //! PGP formatted. If you don't want to use a heavyweight dependency like gpg, //! this library supports only the minimal necessary components of the PGP //! format to transmit your keys and signatures. -#![feature(rust_2018_preview)] #![deny(missing_docs, missing_debug_implementations)] -#[macro_use] extern crate failure; -#[macro_use] extern crate bitflags; +#[macro_use] +extern crate failure; +#[macro_use] +extern crate bitflags; #[cfg(feature = "dalek")] extern crate ed25519_dalek as dalek; @@ -23,7 +24,7 @@ mod key; mod sig; pub use crate::key::PgpKey; -pub use crate::sig::{PgpSig, SubPacket, SigType}; +pub use crate::sig::{PgpSig, SigType, SubPacket}; /// An OpenPGP public key fingerprint. pub type Fingerprint = [u8; 20]; @@ -79,4 +80,3 @@ impl<'a> std::fmt::Debug for Base64<'a> { f.write_str(&base64::encode(self.0)) } } - diff --git a/src/packet.rs b/src/packet.rs index 7160211..036c534 100644 --- a/src/packet.rs +++ b/src/packet.rs @@ -1,19 +1,23 @@ use std::ops::Range; use std::u16; -use byteorder::{ByteOrder, BigEndian}; +use byteorder::{BigEndian, ByteOrder}; -pub(crate) type BigEndianU32 = [u8; 4]; -pub(crate) type BigEndianU16 = [u8; 2]; +pub(crate) type BigEndianU32 = [u8; 4]; +pub(crate) type BigEndianU16 = [u8; 2]; -pub(crate) fn write_packet)>(data: &mut Vec, tag: u8, write: F) -> Range { +pub(crate) fn write_packet)>( + data: &mut Vec, + tag: u8, + write: F, +) -> Range { let init = data.len(); let header_tag = (tag << 2) | 0b_1000_0001; data.extend(&[header_tag, 0, 0]); write(data); let len = data.len() - init - 3; assert!(len < u16::MAX as usize); - BigEndian::write_u16(&mut data[(init+1)..(init+3)], len as u16); + BigEndian::write_u16(&mut data[(init + 1)..(init + 3)], len as u16); init..data.len() } @@ -26,8 +30,9 @@ pub(crate) fn prepare_packet)>(tag: u8, write: F) -> Vec packet } -pub(crate) fn write_subpackets(packet: &mut Vec, write_each_subpacket: F) where - F: Fn(&mut Vec) +pub(crate) fn write_subpackets(packet: &mut Vec, write_each_subpacket: F) +where + F: Fn(&mut Vec), { packet.extend(&[0, 0]); let init = packet.len(); diff --git a/src/sig.rs b/src/sig.rs index 76e21c4..b1327e8 100644 --- a/src/sig.rs +++ b/src/sig.rs @@ -1,43 +1,45 @@ -use std::fmt::{self, Display, Debug}; +use std::fmt::{self, Debug, Display}; use std::str::FromStr; use std::u16; -use byteorder::{ByteOrder, BigEndian}; +use byteorder::{BigEndian, ByteOrder}; use digest::Digest; use typenum::U32; -#[cfg(feature = "dalek")] use ed25519_dalek as dalek; -#[cfg(feature = "dalek")] use typenum::U64; +#[cfg(feature = "dalek")] +use ed25519_dalek as dalek; +#[cfg(feature = "dalek")] +use typenum::U64; use crate::ascii_armor::{ascii_armor, remove_ascii_armor}; -use crate::Base64; use crate::packet::*; -use crate::{Fingerprint, Signature}; +use crate::Base64; use crate::PgpError; +use crate::{Fingerprint, Signature}; /// The valid types of OpenPGP signatures. #[allow(missing_docs)] #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub enum SigType { - BinaryDocument = 0x00, - TextDocument = 0x01, - Standalone = 0x02, - GenericCertification = 0x10, - PersonaCertification = 0x11, - CasualCertification = 0x12, - PositiveCertification = 0x13, - SubkeyBinding = 0x18, - PrimaryKeyBinding = 0x19, - DirectlyOnKey = 0x1F, - KeyRevocation = 0x20, - SubkeyRevocation = 0x28, + BinaryDocument = 0x00, + TextDocument = 0x01, + Standalone = 0x02, + GenericCertification = 0x10, + PersonaCertification = 0x11, + CasualCertification = 0x12, + PositiveCertification = 0x13, + SubkeyBinding = 0x18, + PrimaryKeyBinding = 0x19, + DirectlyOnKey = 0x1F, + KeyRevocation = 0x20, + SubkeyRevocation = 0x28, CertificationRevocation = 0x30, - Timestamp = 0x40, - ThirdPartyConfirmation = 0x50, + Timestamp = 0x40, + ThirdPartyConfirmation = 0x50, } /// A subpacket to be hashed into the signed data. -/// +/// /// See RFC 4880 for more information. #[derive(Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd, Debug)] pub struct SubPacket<'a> { @@ -70,17 +72,17 @@ impl PgpSig { sig_type: SigType, unix_time: u32, subpackets: &[SubPacket], - sign: F + sign: F, ) -> PgpSig - where - Sha256: Digest, - F: Fn(&[u8]) -> Signature, + where + Sha256: Digest, + F: Fn(&[u8]) -> Signature, { let data = prepare_packet(2, |packet| { - packet.push(4); // version number - packet.push(sig_type as u8); // signature class - packet.push(22); // signing algorithm (EdDSA) - packet.push(8); // hash algorithm (SHA-256) + packet.push(4); // version number + packet.push(sig_type as u8); // signature class + packet.push(22); // signing algorithm (EdDSA) + packet.push(8); // hash algorithm (SHA-256) write_subpackets(packet, |hashed_subpackets| { // fingerprint @@ -90,7 +92,9 @@ impl PgpSig { }); // timestamp - write_single_subpacket(hashed_subpackets, 2, |packet| packet.extend(&bigendian_u32(unix_time))); + write_single_subpacket(hashed_subpackets, 2, |packet| { + packet.extend(&bigendian_u32(unix_time)) + }); for &SubPacket { tag, data } in subpackets { write_single_subpacket(hashed_subpackets, tag, |packet| packet.extend(data)); @@ -98,16 +102,16 @@ impl PgpSig { }); let hash = { - let mut hasher = Sha256::default(); + let mut hasher = Sha256::new(); - hasher.process(data); + hasher.input(data); - hasher.process(&packet[3..]); + hasher.input(&packet[3..]); - hasher.process(&[0x04, 0xff]); - hasher.process(&bigendian_u32((packet.len() - 3) as u32)); + hasher.input(&[0x04, 0xff]); + hasher.input(&bigendian_u32((packet.len() - 3) as u32)); - hasher.fixed_result() + hasher.result() }; write_subpackets(packet, |unhashed_subpackets| { @@ -190,7 +194,7 @@ impl PgpSig { 0x30 => SigType::CertificationRevocation, 0x40 => SigType::Timestamp, 0x50 => SigType::ThirdPartyConfirmation, - _ => panic!("Unrecognized signature type."), + _ => panic!("Unrecognized signature type."), } } @@ -199,23 +203,23 @@ impl PgpSig { /// The data to be verified should be inputed by hashing it into the /// SHA-256 hasher using the input function. pub fn verify(&self, input: F1, verify: F2) -> bool - where - Sha256: Digest, - F1: FnOnce(&mut Sha256), - F2: FnOnce(&[u8], Signature) -> bool, + where + Sha256: Digest, + F1: FnOnce(&mut Sha256), + F2: FnOnce(&[u8], Signature) -> bool, { let hash = { - let mut hasher = Sha256::default(); + let mut hasher = Sha256::new(); input(&mut hasher); let hashed_section = self.hashed_section(); - hasher.process(hashed_section); + hasher.input(hashed_section); - hasher.process(&[0x04, 0xff]); - hasher.process(&bigendian_u32(hashed_section.len() as u32)); + hasher.input(&[0x04, 0xff]); + hasher.input(&bigendian_u32(hashed_section.len() as u32)); - hasher.fixed_result() + hasher.result() }; verify(&hash[..], self.signature()) @@ -229,10 +233,10 @@ impl PgpSig { fingerprint: Fingerprint, sig_type: SigType, timestamp: u32, - ) -> PgpSig + ) -> PgpSig where - Sha256: Digest, - Sha512: Digest, + Sha256: Digest + Default, + Sha512: Digest + Default, { PgpSig::new::(data, fingerprint, sig_type, timestamp, &[], |data| { keypair.sign::(data).to_bytes() @@ -249,8 +253,8 @@ impl PgpSig { /// Verify this signature against an ed25519-dalek public key. pub fn verify_dalek(&self, key: &dalek::PublicKey, input: F) -> bool where - Sha256: Digest, - Sha512: Digest, + Sha256: Digest + Default, + Sha512: Digest + Default, F: FnOnce(&mut Sha256), { self.verify::(input, |data, signature| { @@ -262,7 +266,9 @@ impl PgpSig { impl Debug for PgpSig { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("PgpSig").field("key", &Base64(&self.data[..])).finish() + f.debug_struct("PgpSig") + .field("key", &Base64(&self.data[..])) + .finish() } } @@ -286,26 +292,34 @@ impl FromStr for PgpSig { fn find_signature_packet(data: &[u8]) -> Result<(Vec, &[u8]), PgpError> { let (init, len) = match data.first() { - Some(&0x88) => { - if data.len() < 2 { return Err(PgpError::InvalidPacketHeader) } + Some(&0x88) => { + if data.len() < 2 { + return Err(PgpError::InvalidPacketHeader); + } (2, data[1] as usize) } - Some(&0x89) => { - if data.len() < 3 { return Err(PgpError::InvalidPacketHeader) } + Some(&0x89) => { + if data.len() < 3 { + return Err(PgpError::InvalidPacketHeader); + } let len = BigEndian::read_u16(&data[1..3]); (3, len as usize) } - Some(&0x8a) => { - if data.len() < 5 { return Err(PgpError::InvalidPacketHeader) } + Some(&0x8a) => { + if data.len() < 5 { + return Err(PgpError::InvalidPacketHeader); + } let len = BigEndian::read_u32(&data[1..5]); - if len > u16::MAX as u32 { return Err(PgpError::UnsupportedPacketLength) } + if len > u16::MAX as u32 { + return Err(PgpError::UnsupportedPacketLength); + } (5, len as usize) } - _ => return Err(PgpError::UnsupportedPacketLength), + _ => return Err(PgpError::UnsupportedPacketLength), }; if data.len() < init + len { - return Err(PgpError::InvalidPacketHeader) + return Err(PgpError::InvalidPacketHeader); } let packet = &data[init..][..len]; @@ -325,21 +339,21 @@ fn find_signature_packet(data: &[u8]) -> Result<(Vec, &[u8]), PgpError> { fn has_correct_structure(packet: &[u8]) -> Result<(), PgpError> { if packet.len() < 6 { - return Err(PgpError::UnsupportedSignaturePacket) + return Err(PgpError::UnsupportedSignaturePacket); } if !(packet[0] == 04 && packet[2] == 22 && packet[3] == 08) { - return Err(PgpError::UnsupportedSignaturePacket) + return Err(PgpError::UnsupportedSignaturePacket); } let hashed_len = BigEndian::read_u16(&packet[4..6]) as usize; if packet.len() < hashed_len + 8 { - return Err(PgpError::UnsupportedSignaturePacket) + return Err(PgpError::UnsupportedSignaturePacket); } let unhashed_len = BigEndian::read_u16(&packet[(hashed_len + 6)..][..2]) as usize; if packet.len() != unhashed_len + hashed_len + 78 { - return Err(PgpError::UnsupportedSignaturePacket) + return Err(PgpError::UnsupportedSignaturePacket); } Ok(()) @@ -348,12 +362,12 @@ fn has_correct_structure(packet: &[u8]) -> Result<(), PgpError> { fn has_correct_hashed_subpackets(packet: &[u8]) -> Result<(), PgpError> { let hashed_len = BigEndian::read_u16(&packet[4..6]) as usize; if hashed_len < 23 { - return Err(PgpError::MissingFingerprintSubpacket) + return Err(PgpError::MissingFingerprintSubpacket); } // check that the first subpacket is a fingerprint subpacket if !(packet[6] == 22 && packet[7] == 33 && packet[8] == 4) { - return Err(PgpError::MissingFingerprintSubpacket) + return Err(PgpError::MissingFingerprintSubpacket); } Ok(())