-
Notifications
You must be signed in to change notification settings - Fork 172
x501+x509: CertificateDocument, X509Version, and more additions
#393
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 19 commits
f2ab456
213e9a2
945bfe9
c2d3b40
40cf4aa
7504101
30c77d0
66e6b9a
89dc750
b34f48b
bc391a7
c2f9377
1e44e55
fb203b6
ee9f1a3
c226d37
b600b99
6fe650f
a9dab3e
b7a19de
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,166 @@ | ||
| //! CertificateDocument implementation | ||
| use crate::Certificate; | ||
| use der::{Error, Result}; | ||
|
|
||
| use alloc::vec::Vec; | ||
| use core::fmt; | ||
| use der::{Decodable, Document}; | ||
|
|
||
| #[cfg(feature = "std")] | ||
| use std::path::Path; | ||
|
|
||
| #[cfg(feature = "pem")] | ||
| use { | ||
| alloc::string::String, | ||
| core::str::FromStr, | ||
| der::pem::{self, LineEnding}, | ||
| }; | ||
|
|
||
| /// Certificate document. | ||
| /// | ||
| /// This type provides storage for [`Certificate`] encoded as ASN.1 | ||
| /// DER with the invariant that the contained-document is "well-formed", i.e. | ||
| /// it will parse successfully according to this crate's parsing rules. | ||
| #[derive(Clone)] | ||
| #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] | ||
| pub struct CertificateDocument(Vec<u8>); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @tarcieri I know I've implemented one of these document types for
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems like a complicated and important enough issue I did a long-form write up on it, so as not to lose the answers to these questions in a PR comment: #421 Some short answers though:
|
||
|
|
||
| impl<'a> TryFrom<&'a [u8]> for Certificate<'a> { | ||
| type Error = Error; | ||
|
|
||
| fn try_from(bytes: &'a [u8]) -> Result<Self> { | ||
| Self::from_der(bytes) | ||
| } | ||
| } | ||
|
|
||
| impl<'a> Document<'a> for CertificateDocument { | ||
| type Message = Certificate<'a>; | ||
| const SENSITIVE: bool = false; | ||
| } | ||
|
|
||
| impl CertificateDocument { | ||
| /// Parse [`Certificate`] from buffer containing DER-encoded certificate | ||
| pub fn from_certificate_der(bytes: &[u8]) -> Result<Self> { | ||
tarcieri marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| Self::from_der(bytes) | ||
| } | ||
|
|
||
| #[cfg(feature = "pem")] | ||
| #[cfg_attr(docsrs, doc(cfg(feature = "pem")))] | ||
| /// Parse [`Certificate`] from buffer containing PEM-encoded certificate | ||
| pub fn from_certificate_pem(s: &str) -> Result<Self> { | ||
| Self::from_pem(s) | ||
| } | ||
|
|
||
| #[cfg(feature = "std")] | ||
| #[cfg_attr(docsrs, doc(cfg(feature = "std")))] | ||
| /// Read DER-encdoed [`Certificate`] from file | ||
| pub fn read_certificate_der_file(path: impl AsRef<Path>) -> Result<Self> { | ||
| Self::read_der_file(path) | ||
| } | ||
|
|
||
| #[cfg(all(feature = "pem", feature = "std"))] | ||
| #[cfg_attr(docsrs, doc(cfg(all(feature = "pem", feature = "std"))))] | ||
| /// Read PEM-encdoed [`Certificate`] from file | ||
| pub fn read_certificate_pem_file(path: impl AsRef<Path>) -> Result<Self> { | ||
| Self::read_pem_file(path) | ||
| } | ||
| } | ||
|
|
||
| #[cfg(any(feature = "alloc", feature = "std"))] | ||
| #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] | ||
| impl CertificateDocument { | ||
| /// Generate DER-encoded [`Certificate`] | ||
| pub fn to_certificate_der(&self) -> Result<CertificateDocument> { | ||
| Ok(self.clone()) | ||
| } | ||
|
|
||
| #[cfg(feature = "pem")] | ||
| #[cfg_attr(docsrs, doc(cfg(feature = "pem")))] | ||
| /// Generate PEM-encoded [`Certificate`] | ||
| pub fn to_certificate_pem(&self, line_ending: LineEnding) -> Result<String> { | ||
| self.to_pem(line_ending) | ||
| } | ||
|
|
||
| #[cfg(feature = "std")] | ||
| #[cfg_attr(docsrs, doc(cfg(feature = "std")))] | ||
| /// Write DER-encoded [`Certificate`] to a file | ||
| pub fn write_certificate_der_file(&self, path: impl AsRef<Path>) -> Result<()> { | ||
| self.write_der_file(path) | ||
| } | ||
|
|
||
| #[cfg(all(feature = "pem", feature = "std"))] | ||
| #[cfg_attr(docsrs, doc(cfg(all(feature = "pem", feature = "std"))))] | ||
| /// Write PEM-encoded [`Certificate`] to a file | ||
| pub fn write_certificate_pem_file( | ||
| &self, | ||
| path: impl AsRef<Path>, | ||
| line_ending: LineEnding, | ||
| ) -> Result<()> { | ||
| self.write_pem_file(path, line_ending) | ||
| } | ||
| } | ||
|
|
||
| impl AsRef<[u8]> for CertificateDocument { | ||
| fn as_ref(&self) -> &[u8] { | ||
| self.0.as_ref() | ||
| } | ||
| } | ||
|
|
||
| impl TryFrom<&[u8]> for CertificateDocument { | ||
| type Error = Error; | ||
|
|
||
| fn try_from(bytes: &[u8]) -> Result<Self> { | ||
| Self::from_der(bytes) | ||
| } | ||
| } | ||
|
|
||
| impl TryFrom<Certificate<'_>> for CertificateDocument { | ||
| type Error = Error; | ||
|
|
||
| fn try_from(cert: Certificate<'_>) -> Result<CertificateDocument> { | ||
| Self::try_from(&cert) | ||
| } | ||
| } | ||
|
|
||
| impl TryFrom<&Certificate<'_>> for CertificateDocument { | ||
| type Error = Error; | ||
|
|
||
| fn try_from(cert: &Certificate<'_>) -> Result<CertificateDocument> { | ||
| Self::from_msg(cert) | ||
| } | ||
| } | ||
|
|
||
| impl TryFrom<Vec<u8>> for CertificateDocument { | ||
| type Error = der::Error; | ||
|
|
||
| fn try_from(bytes: Vec<u8>) -> der::Result<Self> { | ||
| // Ensure document is well-formed | ||
| Certificate::from_der(bytes.as_slice())?; | ||
| Ok(Self(bytes)) | ||
| } | ||
| } | ||
|
|
||
| impl fmt::Debug for CertificateDocument { | ||
| fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
| fmt.debug_tuple("CertificateDocument") | ||
| .field(&self.decode()) | ||
| .finish() | ||
| } | ||
| } | ||
|
|
||
| #[cfg(feature = "pem")] | ||
| #[cfg_attr(docsrs, doc(cfg(feature = "pem")))] | ||
| impl FromStr for CertificateDocument { | ||
| type Err = Error; | ||
|
|
||
| fn from_str(s: &str) -> Result<Self> { | ||
| Self::from_certificate_pem(s) | ||
| } | ||
| } | ||
|
|
||
| #[cfg(feature = "pem")] | ||
| #[cfg_attr(docsrs, doc(cfg(feature = "pem")))] | ||
| impl pem::PemLabel for CertificateDocument { | ||
| const TYPE_LABEL: &'static str = "CERTIFICATE"; | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@carl-wallace All the changes in this file are obsolete if we merge #410 instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure. Further review of this until after alignment with changes to dependencies is likely not worthwhile.