diff options
Diffstat (limited to 'openpgp')
-rw-r--r-- | openpgp/NEWS | 1 | ||||
-rw-r--r-- | openpgp/src/cert/raw.rs | 91 |
2 files changed, 88 insertions, 4 deletions
diff --git a/openpgp/NEWS b/openpgp/NEWS index 841241ea..61cd54e7 100644 --- a/openpgp/NEWS +++ b/openpgp/NEWS @@ -13,6 +13,7 @@ - fmt::hex::Dumper::with_offset - parse::buffered_reader re-export - policy::AsymmetricAlgorithm::BrainpoolP384 + - RawCert implements Parse ** Deprecated functionality - crypto::mpi::SecretKeyMaterial::parse - crypto::mpi::SecretKeyMaterial::parse_with_checksum diff --git a/openpgp/src/cert/raw.rs b/openpgp/src/cert/raw.rs index fa99b9ae..cc3efe7d 100644 --- a/openpgp/src/cert/raw.rs +++ b/openpgp/src/cert/raw.rs @@ -116,7 +116,7 @@ pub use iter::KeyIter; /// use sequoia_openpgp as openpgp; /// # use openpgp::Result; /// # use openpgp::cert::prelude::*; -/// use openpgp::cert::raw::RawCertParser; +/// # use openpgp::cert::raw::RawCert; /// use openpgp::packet::Packet; /// use openpgp::packet::Tag; /// # use openpgp::parse::Parse; @@ -135,9 +135,7 @@ pub use iter::KeyIter; /// # cert.as_tsk().serialize(&mut bytes); /// # let mut count = 0; /// # -/// # let rawcert = RawCertParser::from_bytes(&bytes)? -/// # .next().expect("got a cert") -/// # .expect("valid cert"); +/// # let rawcert = RawCert::from_bytes(&bytes)?; /// for p in rawcert.packets() { /// if p.tag() == Tag::SecretSubkey { /// if let Ok(packet) = Packet::try_from(p) { @@ -457,6 +455,26 @@ impl<'a> TryFrom<RawCert<'a>> for Cert { } } +impl<'a> Parse<'a, RawCert<'a>> for RawCert<'a> { + /// Returns the first RawCert encountered in the reader. + /// + /// Returns an error if there are multiple certificates. + fn from_reader<R: 'a + Read + Send + Sync>(reader: R) -> Result<Self> { + let mut parser = RawCertParser::from_reader(reader)?; + if let Some(cert_result) = parser.next() { + if parser.next().is_some() { + Err(Error::MalformedCert( + "Additional packets found, is this a keyring?".into() + ).into()) + } else { + cert_result + } + } else { + Err(Error::MalformedCert("No data".into()).into()) + } + } +} + impl<'a> crate::seal::Sealed for RawCert<'a> {} impl<'a> crate::serialize::Marshal for RawCert<'a> { fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> { @@ -1531,4 +1549,69 @@ mod test { .collect::<Vec<_>>(), vec![ "Testy McTestface <testy@example.org>" ]); } + + // Test the raw cert parser implementation. + #[test] + fn raw_cert_parser_impl() { + // Read one certificate. + let testy = crate::tests::key("testy.pgp"); + + let raw = RawCert::from_bytes(testy).expect("valid"); + let cert = Cert::from_bytes(testy).expect("valid"); + + assert_eq!( + raw.keys().map(|k| k.fingerprint()).collect::<Vec<_>>(), + cert.keys().map(|k| k.fingerprint()).collect::<Vec<_>>()); + + assert_eq!( + raw.userids().collect::<Vec<_>>(), + cert.userids().map(|ua| ua.userid().clone()).collect::<Vec<_>>()); + + // Parse zero certificates. + eprintln!("Parsing 0 bytes"); + let raw = RawCert::from_bytes(b""); + match &raw { + Ok(_) => eprintln!("raw: Ok"), + Err(err) => eprintln!("raw: {}", err), + } + let cert = Cert::from_bytes(b""); + match &cert { + Ok(_) => eprintln!("cert: Ok"), + Err(err) => eprintln!("cert: {}", err), + } + + assert!( + matches!(cert.map_err(|e| e.downcast::<Error>()), + Err(Ok(Error::MalformedCert(_))))); + assert!( + matches!(raw.map_err(|e| e.downcast::<Error>()), + Err(Ok(Error::MalformedCert(_))))); + + // Parse two certificates. + let mut bytes = Vec::new(); + bytes.extend(testy); + bytes.extend(testy); + + let parser = CertParser::from_bytes(&bytes).expect("valid"); + assert_eq!(parser.count(), 2); + + eprintln!("Parsing two certificates"); + let raw = RawCert::from_bytes(&bytes); + match &raw { + Ok(_) => eprintln!("raw: Ok"), + Err(err) => eprintln!("raw: {}", err), + } + let cert = Cert::from_bytes(&bytes); + match &cert { + Ok(_) => eprintln!("cert: Ok"), + Err(err) => eprintln!("cert: {}", err), + } + + assert!( + matches!(cert.map_err(|e| e.downcast::<Error>()), + Err(Ok(Error::MalformedCert(_))))); + assert!( + matches!(raw.map_err(|e| e.downcast::<Error>()), + Err(Ok(Error::MalformedCert(_))))); + } } |