diff --git a/Cargo.lock b/Cargo.lock index 27f364814..e112eb458 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -261,7 +261,7 @@ dependencies = [ "const-oid 0.9.5", "crmf", "der", - "hex-literal", + "hex-literal 0.4.1", "spki", "x509-cert", ] @@ -277,7 +277,7 @@ dependencies = [ "der", "ecdsa", "getrandom", - "hex-literal", + "hex-literal 0.4.1", "p256", "pem-rfc7468", "pkcs5", @@ -306,7 +306,7 @@ name = "const-oid" version = "0.10.0-pre" dependencies = [ "arbitrary", - "hex-literal", + "hex-literal 0.4.1", ] [[package]] @@ -440,7 +440,7 @@ dependencies = [ "const-oid 0.9.5", "der_derive", "flagset", - "hex-literal", + "hex-literal 0.4.1", "pem-rfc7468", "proptest", "time", @@ -728,7 +728,7 @@ name = "gss-api" version = "0.1.0" dependencies = [ "der", - "hex-literal", + "hex-literal 0.4.1", "spki", "x509-cert", ] @@ -751,6 +751,12 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" +[[package]] +name = "hex-literal" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" + [[package]] name = "hex-literal" version = "0.4.1" @@ -995,7 +1001,7 @@ version = "0.7.5" dependencies = [ "const-oid 0.9.5", "der", - "hex-literal", + "hex-literal 0.4.1", "pkcs8", "spki", "tempfile", @@ -1005,11 +1011,18 @@ dependencies = [ name = "pkcs12" version = "0.0.0" dependencies = [ + "cms", + "const-oid 0.9.5", "der", "digest", - "hex-literal", + "hex-literal 0.3.4", + "pkcs5", + "pkcs8", "sha2", + "spki", + "subtle-encoding", "whirlpool", + "x509-cert", "zeroize", ] @@ -1021,7 +1034,7 @@ dependencies = [ "cbc", "der", "des", - "hex-literal", + "hex-literal 0.4.1", "pbkdf2", "scrypt", "sha1", @@ -1034,7 +1047,7 @@ name = "pkcs7" version = "0.4.1" dependencies = [ "der", - "hex-literal", + "hex-literal 0.4.1", "spki", "x509-cert", ] @@ -1044,7 +1057,7 @@ name = "pkcs8" version = "0.10.2" dependencies = [ "der", - "hex-literal", + "hex-literal 0.4.1", "pkcs5", "rand_core", "spki", @@ -1394,7 +1407,7 @@ dependencies = [ "base16ct", "der", "generic-array", - "hex-literal", + "hex-literal 0.4.1", "pkcs8", "serdect", "subtle", @@ -1465,7 +1478,7 @@ dependencies = [ "base16ct", "bincode", "ciborium", - "hex-literal", + "hex-literal 0.4.1", "proptest", "serde", "serde-json-core", @@ -1544,7 +1557,7 @@ dependencies = [ "arbitrary", "base64ct", "der", - "hex-literal", + "hex-literal 0.4.1", "sha2", "tempfile", ] @@ -1555,6 +1568,15 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +[[package]] +name = "subtle-encoding" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dcb1ed7b8330c5eed5441052651dd7a12c75e2ed88f2ec024ae1fa3a5e59945" +dependencies = [ + "zeroize", +] + [[package]] name = "syn" version = "2.0.29" @@ -1930,7 +1952,7 @@ dependencies = [ "const-oid 0.9.5", "der", "ecdsa", - "hex-literal", + "hex-literal 0.4.1", "p256", "rand", "rsa", @@ -1958,7 +1980,7 @@ version = "0.2.0-pre" dependencies = [ "const-oid 0.9.5", "der", - "hex-literal", + "hex-literal 0.4.1", "spki", "x509-cert", ] @@ -1970,7 +1992,7 @@ dependencies = [ "cmpv2", "cms", "der", - "hex-literal", + "hex-literal 0.4.1", "x509-cert", ] diff --git a/pkcs12/Cargo.toml b/pkcs12/Cargo.toml index 2988718b8..c343ce744 100644 --- a/pkcs12/Cargo.toml +++ b/pkcs12/Cargo.toml @@ -15,14 +15,19 @@ edition = "2021" rust-version = "1.65" [dependencies] -der = { version = "0.7.8", features = ["alloc"] } -zeroize = "1.6" - -# optional dependencies -digest = { version = "0.10.7", features = ["alloc"], optional = true } +der = { version = "0.7.8", features = ["alloc", "derive", "oid", "pem"] } +spki = { version = "0.7" } +x509-cert = { version = "0.2.3", default-features = false, features = ["pem"] } +const-oid = { version = "0.9", features = ["db"] } # TODO: path = "../const-oid" +cms = "0.2.1" +digest = { version = "0.10.7", features=["alloc"], optional = true } +zeroize = "1.6.0" [dev-dependencies] -hex-literal = "0.4" +hex-literal = "0.3.3" +pkcs8 = { version = "0.10.2", features = ["pkcs5", "getrandom"] } +pkcs5 = {version = "0.7.1", features = ["pbes2", "3des"]} +subtle-encoding = "0.5.1" sha2 = "0.10.7" whirlpool = "0.10.4" @@ -32,3 +37,4 @@ kdf = ["dep:digest"] [package.metadata.docs.rs] all-features = true rustdoc-args = ["--cfg", "docsrs"] + diff --git a/pkcs12/src/authenticated_safe.rs b/pkcs12/src/authenticated_safe.rs new file mode 100644 index 000000000..1a48cca4a --- /dev/null +++ b/pkcs12/src/authenticated_safe.rs @@ -0,0 +1,16 @@ +//! AuthenticatedSafe-related types + +use alloc::vec::Vec; +use cms::content_info::ContentInfo; + +/// The `AuthenticatedSafe` type is defined in [RFC 7292 Section 4.1]. +/// +/// ```text +/// AuthenticatedSafe ::= SEQUENCE OF ContentInfo +/// -- Data if unencrypted +/// -- EncryptedData if password-encrypted +/// -- EnvelopedData if public key-encrypted +/// ``` +/// +/// [RFC 7292 Section 4.1]: https://www.rfc-editor.org/rfc/rfc7292#section-4.1 +pub type AuthenticatedSafe<'a> = Vec; diff --git a/pkcs12/src/bag_type.rs b/pkcs12/src/bag_type.rs new file mode 100644 index 000000000..5dbf5ab2c --- /dev/null +++ b/pkcs12/src/bag_type.rs @@ -0,0 +1,59 @@ +//! BagType-related types + +use der::asn1::ObjectIdentifier; +use der::{ErrorKind, FixedTag, Tag}; + +/// Indicates the type of content. +#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)] +pub enum BagType { + /// Plain data content type + Key, + + /// Signed-data content type + Pkcs8, + + /// Enveloped-data content type + Cert, + + /// Signed-and-enveloped-data content type + Crl, + + /// Digested-data content type + Secret, + + /// Encrypted-data content type + SafeContents, +} + +impl FixedTag for BagType { + const TAG: Tag = Tag::ObjectIdentifier; +} + +impl From for ObjectIdentifier { + fn from(content_type: BagType) -> ObjectIdentifier { + match content_type { + BagType::Key => crate::PKCS_12_KEY_BAG_OID, + BagType::Pkcs8 => crate::PKCS_12_PKCS8_KEY_BAG_OID, + BagType::Cert => crate::PKCS_12_CERT_BAG_OID, + BagType::Crl => crate::PKCS_12_CRL_BAG_OID, + BagType::Secret => crate::PKCS_12_SECRET_BAG_OID, + BagType::SafeContents => crate::PKCS_12_SAFE_CONTENTS_BAG_OID, + } + } +} + +impl TryFrom for BagType { + type Error = der::Error; + + fn try_from(oid: ObjectIdentifier) -> der::Result { + match oid { + crate::PKCS_12_KEY_BAG_OID => Ok(Self::Key), + crate::PKCS_12_PKCS8_KEY_BAG_OID => Ok(Self::Pkcs8), + crate::PKCS_12_CERT_BAG_OID => Ok(Self::Cert), + crate::PKCS_12_CRL_BAG_OID => Ok(Self::Crl), + crate::PKCS_12_SECRET_BAG_OID => Ok(Self::Secret), + crate::PKCS_12_SAFE_CONTENTS_BAG_OID => Ok(Self::SafeContents), + _ => Err(ErrorKind::OidUnknown { oid }.into()), + } + } +} diff --git a/pkcs12/src/cert_type.rs b/pkcs12/src/cert_type.rs new file mode 100644 index 000000000..7261c337e --- /dev/null +++ b/pkcs12/src/cert_type.rs @@ -0,0 +1,43 @@ +//! CertBag-related types + +use der::asn1::{ObjectIdentifier, OctetString}; +use der::Sequence; + +/// The `CertBag` type is defined in [RFC 7292 Section 4.2.3]. +/// +///```text +/// CertBag ::= SEQUENCE { +/// certId BAG-TYPE.&id ({CertTypes}), +/// certValue [0] EXPLICIT BAG-TYPE.&Type ({CertTypes}{@certId}) +/// } +///``` +/// +/// [RFC 7292 Section 4.2.3]: https://www.rfc-editor.org/rfc/rfc7292#section-4.2.3 +#[derive(Clone, Debug, Eq, PartialEq, Sequence)] +#[allow(missing_docs)] +pub struct CertBag { + pub cert_id: ObjectIdentifier, + #[asn1(context_specific = "0", tag_mode = "EXPLICIT")] + pub cert_value: CertTypes, +} + +// todo defer: add sdsiCertificate support +/// The `CertTypes` type is defined in [RFC 7292 Section 4.2.3]. +/// +///```text +/// x509Certificate BAG-TYPE ::= +/// {OCTET STRING IDENTIFIED BY {certTypes 1}} +/// -- DER-encoded X.509 certificate stored in OCTET STRING +/// sdsiCertificate BAG-TYPE ::= +/// {IA5String IDENTIFIED BY {certTypes 2}} +/// -- Base64-encoded SDSI certificate stored in IA5String +/// +/// CertTypes BAG-TYPE ::= { +/// x509Certificate | +/// sdsiCertificate, +/// ... -- For future extensions +/// } +///``` +/// +/// [RFC 7292 Section 4.2.3]: https://www.rfc-editor.org/rfc/rfc7292#section-4.2.3 +pub type CertTypes = OctetString; diff --git a/pkcs12/src/crl_type.rs b/pkcs12/src/crl_type.rs new file mode 100644 index 000000000..b93ce5a6b --- /dev/null +++ b/pkcs12/src/crl_type.rs @@ -0,0 +1,39 @@ +//! CertBag-related types + +use der::asn1::{ObjectIdentifier, OctetString}; +use der::Sequence; + +/// The `CertBag` type is defined in [RFC 7292 Section 4.2.4]. +/// +///```text +/// CRLBag ::= SEQUENCE { +/// crlId BAG-TYPE.&id ({CRLTypes}), +/// crltValue [0] EXPLICIT BAG-TYPE.&Type ({CRLTypes}{@crlId}) +/// } +///``` +/// +/// [RFC 7292 Section 4.2.4]: https://www.rfc-editor.org/rfc/rfc7292#section-4.2.4 +#[derive(Clone, Debug, Eq, PartialEq, Sequence)] +#[allow(missing_docs)] +pub struct CrlBag { + pub crl_id: ObjectIdentifier, + #[asn1(context_specific = "0", tag_mode = "EXPLICIT")] + pub crl_value: CrlTypes, +} + +// todo defer: add support for other CRL types +/// The `CRLTypes` type is defined in [RFC 7292 Section 4.2.4]. +/// +///```text +/// x509CRL BAG-TYPE ::= +/// {OCTET STRING IDENTIFIED BY {crlTypes 1}} +/// -- DER-encoded X.509 CRL stored in OCTET STRING +/// +/// CRLTypes BAG-TYPE ::= { +/// x509CRL, +/// ... -- For future extensions +/// } +///``` +/// +/// [RFC 7292 Section 4.2.4]: https://www.rfc-editor.org/rfc/rfc7292#section-4.2.4 +pub type CrlTypes = OctetString; diff --git a/pkcs12/src/digest_info.rs b/pkcs12/src/digest_info.rs new file mode 100644 index 000000000..2753ed3b2 --- /dev/null +++ b/pkcs12/src/digest_info.rs @@ -0,0 +1,18 @@ +//! DigestInfo-related types + +use der::{asn1::OctetString, Sequence, ValueOrd}; +use spki::AlgorithmIdentifierOwned; + +/// ```text +/// DigestInfo ::= SEQUENCE { +/// digestAlgorithm DigestAlgorithmIdentifier, +/// digest Digest } +/// ``` +#[derive(Clone, Debug, Eq, PartialEq, Sequence, ValueOrd)] +pub struct DigestInfo { + /// the algorithm. + pub algorithm: AlgorithmIdentifierOwned, + + /// the digest + pub digest: OctetString, +} diff --git a/pkcs12/src/lib.rs b/pkcs12/src/lib.rs index 29abfabb4..49baa6a6c 100644 --- a/pkcs12/src/lib.rs +++ b/pkcs12/src/lib.rs @@ -14,10 +14,84 @@ unused_qualifications )] -//! TODO: complete PKCS#12 crate - -#[cfg(feature = "kdf")] +use const_oid::ObjectIdentifier; extern crate alloc; +pub mod authenticated_safe; +pub mod bag_type; +pub mod cert_type; +pub mod crl_type; +pub mod digest_info; +pub mod mac_data; +pub mod pbe_params; +pub mod pfx; +pub mod safe_bag; + #[cfg(feature = "kdf")] pub mod kdf; + +// pbe oids +/// `pbeWithSHAAnd128BitRC4` Object Identifier (OID). +pub const PKCS_12_PBE_WITH_SHAAND128_BIT_RC4: ObjectIdentifier = + ObjectIdentifier::new_unwrap("1.2.840.113549.1.12.1.1"); + +/// `pbeWithSHAAnd128BitRC4` Object Identifier (OID). +pub const PKCS_12_PBE_WITH_SHAAND40_BIT_RC4: ObjectIdentifier = + ObjectIdentifier::new_unwrap("1.2.840.113549.1.12.1.2"); + +/// `pbeWithSHAAnd128BitRC4` Object Identifier (OID). +pub const PKCS_12_PBE_WITH_SHAAND3_KEY_TRIPLE_DES_CBC: ObjectIdentifier = + ObjectIdentifier::new_unwrap("1.2.840.113549.1.12.1.3"); + +/// `pbeWithSHAAnd128BitRC4` Object Identifier (OID). +pub const PKCS_12_PBE_WITH_SHAAND2_KEY_TRIPLE_DES_CBC: ObjectIdentifier = + ObjectIdentifier::new_unwrap("1.2.840.113549.1.12.1.4"); + +/// `pbeWithSHAAnd128BitRC4` Object Identifier (OID). +pub const PKCS_12_PBE_WITH_SHAAND128_BIT_RC2_CBC: ObjectIdentifier = + ObjectIdentifier::new_unwrap("1.2.840.113549.1.12.1.5"); + +/// `pbeWithSHAAnd128BitRC4` Object Identifier (OID). +pub const PKCS_12_PBEWITH_SHAAND40_BIT_RC2_CBC: ObjectIdentifier = + ObjectIdentifier::new_unwrap("1.2.840.113549.1.12.1.6"); + +// bag types +/// `pkcs-12 keyBag` Object Identifier (OID). +pub const PKCS_12_KEY_BAG_OID: ObjectIdentifier = + ObjectIdentifier::new_unwrap("1.2.840.113549.1.12.10.1.1"); + +/// `pkcs-12 pkcs8ShroudedKeyBag` Object Identifier (OID). +pub const PKCS_12_PKCS8_KEY_BAG_OID: ObjectIdentifier = + ObjectIdentifier::new_unwrap("1.2.840.113549.1.12.10.1.2"); + +/// `pkcs-12 certBag` Object Identifier (OID). +pub const PKCS_12_CERT_BAG_OID: ObjectIdentifier = + ObjectIdentifier::new_unwrap("1.2.840.113549.1.12.10.1.3"); + +/// `pkcs-12 crlBag` Object Identifier (OID). +pub const PKCS_12_CRL_BAG_OID: ObjectIdentifier = + ObjectIdentifier::new_unwrap("1.2.840.113549.1.12.10.1.4"); + +/// `pkcs-12 secretBag` Object Identifier (OID). +pub const PKCS_12_SECRET_BAG_OID: ObjectIdentifier = + ObjectIdentifier::new_unwrap("1.2.840.113549.1.12.10.1.5"); + +/// `pkcs-12 safeContentsBag` Object Identifier (OID). +pub const PKCS_12_SAFE_CONTENTS_BAG_OID: ObjectIdentifier = + ObjectIdentifier::new_unwrap("1.2.840.113549.1.12.10.1.6"); + +// cert types +/// `pkcs-9 x509Certificate for pkcs-12` Object Identifier (OID). +pub const PKCS_12_X509_CERT_OID: ObjectIdentifier = + ObjectIdentifier::new_unwrap("1.2.840.113549.1.9.22.1"); + +/// `pkcs-9 sdsiCertificate for pkcs-12` Object Identifier (OID). +pub const PKCS_12_SDSI_CERT_OID: ObjectIdentifier = + ObjectIdentifier::new_unwrap("1.2.840.113549.1.9.22.2"); + +// todo: return the friendly name if present? (minimally, defer until BMPString support is available) +// todo: support separate mac and encryption passwords? +// todo: add decryption support +// todo: add more encryption tests +// todo: add a builder +// todo: add RC2 support diff --git a/pkcs12/src/mac_data.rs b/pkcs12/src/mac_data.rs new file mode 100644 index 000000000..14a697fb0 --- /dev/null +++ b/pkcs12/src/mac_data.rs @@ -0,0 +1,34 @@ +//! MacData-related types + +use crate::digest_info::DigestInfo; +use der::{asn1::OctetString, Sequence, ValueOrd}; + +/// The `MacData` type is defined in [RFC 7292 Section 4]. +/// +/// ```text +/// MacData ::= SEQUENCE { +/// mac DigestInfo, +/// macSalt OCTET STRING, +/// iterations INTEGER DEFAULT 1 +/// -- Note: The default is for historical reasons and its +/// -- use is deprecated. +///} +/// ``` +/// +/// [RFC 7292 Section 4]: https://www.rfc-editor.org/rfc/rfc7292#section-4 +#[derive(Clone, Debug, Eq, PartialEq, Sequence, ValueOrd)] +pub struct MacData { + /// the MAC digest info + pub mac: DigestInfo, + + /// the MAC salt + pub mac_salt: OctetString, + + /// the number of iterations + #[asn1(default = "default_one")] + pub iterations: i32, +} + +fn default_one() -> i32 { + 1 +} diff --git a/pkcs12/src/pbe_params.rs b/pkcs12/src/pbe_params.rs new file mode 100644 index 000000000..2687d8c8b --- /dev/null +++ b/pkcs12/src/pbe_params.rs @@ -0,0 +1,77 @@ +//! pkcs-12PbeParams implementation + +use der::{asn1::OctetString, Sequence, ValueOrd}; +use spki::AlgorithmIdentifierOwned; + +/// The `pkcs-12PbeParams` type is defined in [RFC 7292 Appendix C]. +/// +///```text +/// pkcs-12PbeParams ::= SEQUENCE { +// salt OCTET STRING, +// iterations INTEGER +// } +///``` +/// +/// [RFC 7292 Appendix C]: https://www.rfc-editor.org/rfc/rfc7292#appendix-C +#[derive(Clone, Debug, Eq, PartialEq, Sequence, ValueOrd)] +pub struct Pkcs12PbeParams { + /// the MAC digest info + pub salt: OctetString, + + /// the number of iterations + pub iterations: i32, +} + +/// Password-Based Key Derivation Scheme 2 parameters as defined in +/// [RFC 8018 Appendix A.2]. +/// +/// ```text +/// PBKDF2-params ::= SEQUENCE { +/// salt CHOICE { +/// specified OCTET STRING, +/// otherSource AlgorithmIdentifier {{PBKDF2-SaltSources}} +/// }, +/// iterationCount INTEGER (1..MAX), +/// keyLength INTEGER (1..MAX) OPTIONAL, +/// prf AlgorithmIdentifier {{PBKDF2-PRFs}} DEFAULT +/// algid-hmacWithSHA1 } +/// ``` +/// +/// [RFC 8018 Appendix A.2]: https://tools.ietf.org/html/rfc8018#appendix-A.2 +#[derive(Clone, Debug, Eq, PartialEq, Sequence)] +pub struct Pbkdf2Params { + /// PBKDF2 salt + // TODO(tarcieri): support `CHOICE` with `otherSource` + pub salt: OctetString, + + /// PBKDF2 iteration count + pub iteration_count: u32, + + /// PBKDF2 output length + pub key_length: Option, + + /// Pseudo-random function to use with PBKDF2 + pub prf: AlgorithmIdentifierOwned, +} + +/// EncryptedPrivateKeyInfo ::= SEQUENCE { +/// encryptionAlgorithm EncryptionAlgorithmIdentifier, +/// encryptedData EncryptedData } +#[derive(Clone, Debug, Eq, PartialEq, Sequence)] +#[allow(missing_docs)] +pub struct EncryptedPrivateKeyInfo { + pub encryption_algorithm: AlgorithmIdentifierOwned, + pub encrypted_data: OctetString, +} + +///```text +/// PBES2-params ::= SEQUENCE { +/// keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}}, +/// encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} } +///``` +#[derive(Clone, Debug, Eq, PartialEq, Sequence)] +#[allow(missing_docs)] +pub struct Pbes2Params { + pub kdf: AlgorithmIdentifierOwned, + pub encryption: AlgorithmIdentifierOwned, +} diff --git a/pkcs12/src/pfx.rs b/pkcs12/src/pfx.rs new file mode 100644 index 000000000..a606f3e79 --- /dev/null +++ b/pkcs12/src/pfx.rs @@ -0,0 +1,47 @@ +//! PFX-related types + +use core::cmp::Ordering; + +use der::{Enumerated, Sequence, ValueOrd}; + +use crate::mac_data::MacData; +use cms::content_info::ContentInfo; + +/// just the version v3 +#[derive(Clone, Copy, Debug, Enumerated, Eq, PartialEq, PartialOrd, Ord)] +#[asn1(type = "INTEGER")] +#[repr(u8)] +pub enum Version { + /// syntax version 3 + V3 = 3, +} + +impl ValueOrd for Version { + fn value_cmp(&self, other: &Self) -> der::Result { + Ok(self.cmp(other)) + } +} + +/// The `PFX` type is defined in [RFC 7292 Section 4]. +/// +/// ```text +/// PFX ::= SEQUENCE { +/// version INTEGER {v3(3)}(v3,...), +/// authSafe ContentInfo, +/// macData MacData OPTIONAL +/// } +/// +/// ``` +/// +/// [RFC 7292 Section 4]: https://www.rfc-editor.org/rfc/rfc7292#section-4 +#[derive(Debug, Sequence)] +pub struct Pfx { + /// the syntax version number. + pub version: Version, + + /// the authenticated safe + pub auth_safe: ContentInfo, + + /// the message digest info + pub mac_data: Option, +} diff --git a/pkcs12/src/safe_bag.rs b/pkcs12/src/safe_bag.rs new file mode 100644 index 000000000..0e5fd02a3 --- /dev/null +++ b/pkcs12/src/safe_bag.rs @@ -0,0 +1,130 @@ +//! SafeBag-related types + +use alloc::vec::Vec; +use const_oid::ObjectIdentifier; +use der::asn1::OctetString; +use der::{AnyRef, Decode, Enumerated, Sequence}; +use spki::AlgorithmIdentifierOwned; +use x509_cert::attr::Attributes; + +/// The `SafeContents` type is defined in [RFC 7292 Section 4.1]. +/// +/// ```text +/// SafeContents ::= SEQUENCE OF SafeBag +/// ``` +/// +/// [RFC 7292 Section 4]: https://www.rfc-editor.org/rfc/rfc7292#section-4.2 +pub type SafeContents = Vec; + +/// The `SafeBag` type is defined in [RFC 7292 Section 4.1]. +/// +/// ```text +/// SafeBag ::= SEQUENCE { +/// bagId BAG-TYPE.&id ({PKCS12BagSet}) +/// bagValue [0] EXPLICIT BAG-TYPE.&Type({PKCS12BagSet}{@bagId}), +/// bagAttributes SET OF PKCS12Attribute OPTIONAL +/// } +/// ``` +/// +/// [RFC 7292 Section 4]: https://www.rfc-editor.org/rfc/rfc7292#section-4.2 +#[derive(Clone, Debug, Eq, PartialEq)] +#[allow(missing_docs)] +pub struct SafeBag { + pub bag_id: ObjectIdentifier, + //#[asn1(context_specific = "0", tag_mode = "EXPLICIT")] + pub bag_value: Vec, + pub bag_attributes: Option, +} + +impl<'a> ::der::DecodeValue<'a> for SafeBag { + fn decode_value>( + reader: &mut R, + header: ::der::Header, + ) -> ::der::Result { + use ::der::Reader as _; + reader.read_nested(header.length, |reader| { + let bag_id = reader.decode()?; + let bag_value = match reader.tlv_bytes() { + Ok(v) => v.to_vec(), + Err(e) => return Err(e), + }; + let bag_attributes = reader.decode()?; + Ok(Self { + bag_id, + bag_value, + bag_attributes, + }) + }) + } +} +impl ::der::EncodeValue for SafeBag { + fn value_len(&self) -> ::der::Result<::der::Length> { + let content = AnyRef::from_der(&self.bag_value)?; + use ::der::Encode as _; + [ + self.bag_id.encoded_len()?, + ::der::asn1::ContextSpecificRef { + tag_number: ::der::TagNumber::N0, + tag_mode: ::der::TagMode::Explicit, + value: &content, + } + .encoded_len()?, + self.bag_attributes.encoded_len()?, + ] + .into_iter() + .try_fold(::der::Length::ZERO, |acc, len| acc + len) + } + fn encode_value(&self, writer: &mut impl ::der::Writer) -> ::der::Result<()> { + use ::der::Encode as _; + self.bag_id.encode(writer)?; + let content = AnyRef::from_der(&self.bag_value)?; + ::der::asn1::ContextSpecificRef { + tag_number: ::der::TagNumber::N0, + tag_mode: ::der::TagMode::Explicit, + value: &content, + } + .encode(writer)?; + self.bag_attributes.encode(writer)?; + Ok(()) + } +} +impl<'a> ::der::Sequence<'a> for SafeBag {} + +/// Version for the PrivateKeyInfo structure as defined in [RFC 5208 Section 5]. +/// +/// [RFC 5208 Section 5]: https://www.rfc-editor.org/rfc/rfc5208#section-5 +#[derive(Clone, Copy, Debug, Enumerated, Eq, PartialEq, PartialOrd, Ord)] +#[asn1(type = "INTEGER")] +#[repr(u8)] +pub enum Pkcs8Version { + /// syntax version 3 + V0 = 0, +} + +// PrivateKeyInfo is defined in the pkcs8 crate but without Debug, PartialEq, Eq, Sequence +/// The `PrivateKeyInfo` type is defined in [RFC 5208 Section 5]. +/// +/// ```text +/// PrivateKeyInfo ::= SEQUENCE { +/// version Version, +/// privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, +/// privateKey PrivateKey, +/// attributes [0] IMPLICIT Attributes OPTIONAL } +/// ``` +/// +/// [RFC 5208 Section 5]: https://www.rfc-editor.org/rfc/rfc5208#section-5 +#[derive(Clone, Debug, PartialEq, Eq, Sequence)] +pub struct PrivateKeyInfo { + /// Syntax version number (always 0 for RFC 5208) + pub version: Pkcs8Version, + + /// X.509 `AlgorithmIdentifier` for the private key type. + pub algorithm: AlgorithmIdentifierOwned, + + /// Private key data. + pub private_key: OctetString, + + /// Public key data, optionally available if version is V2. + #[asn1(context_specific = "0", tag_mode = "IMPLICIT", optional = "true")] + pub attributes: Option, +} diff --git a/pkcs12/tests/cert_tests.rs b/pkcs12/tests/cert_tests.rs new file mode 100644 index 000000000..c5d744714 --- /dev/null +++ b/pkcs12/tests/cert_tests.rs @@ -0,0 +1,649 @@ +use cms::encrypted_data::EncryptedData; +use const_oid::db::rfc5911::{ID_DATA, ID_ENCRYPTED_DATA}; +use const_oid::db::rfc5912::ID_SHA_256; +use der::asn1::OctetString; +use der::{Decode, Encode}; +use hex_literal::hex; + +use der::asn1::ContextSpecific; +use pkcs12::authenticated_safe::AuthenticatedSafe; +use pkcs12::cert_type::CertBag; +use pkcs12::pbe_params::Pbkdf2Params; +use pkcs12::pfx::Pfx; +use pkcs12::pfx::Version; +use pkcs12::safe_bag::SafeContents; + +use pkcs8::pkcs5::pbes2::{AES_256_CBC_OID, HMAC_WITH_SHA256_OID, PBES2_OID, PBKDF2_OID}; +use pkcs8::{pkcs5, EncryptedPrivateKeyInfo}; +use spki::AlgorithmIdentifierOwned; + +// 0 1871: SEQUENCE { +// 4 1: INTEGER 3 +// 7 1797: SEQUENCE { +// 11 9: OBJECT IDENTIFIER data (1 2 840 113549 1 7 1) +// 22 1782: [0] { +// 26 1778: OCTET STRING, encapsulates { +// 30 1774: SEQUENCE { +// 34 946: SEQUENCE { +// 38 9: OBJECT IDENTIFIER encryptedData (1 2 840 113549 1 7 6) +// 49 931: [0] { +// 53 927: SEQUENCE { +// 57 1: INTEGER 0 +// 60 920: SEQUENCE { +// 64 9: OBJECT IDENTIFIER data (1 2 840 113549 1 7 1) +// 75 87: SEQUENCE { +// 77 9: OBJECT IDENTIFIER +// : pkcs5PBES2 (1 2 840 113549 1 5 13) +// 88 74: SEQUENCE { +// 90 41: SEQUENCE { +// 92 9: OBJECT IDENTIFIER +// : pkcs5PBKDF2 (1 2 840 113549 1 5 12) +// 103 28: SEQUENCE { +// 105 8: OCTET STRING 9A A2 77 B5 F0 51 B4 50 +// 115 2: INTEGER 2048 +// 119 12: SEQUENCE { +// 121 8: OBJECT IDENTIFIER +// : hmacWithSHA256 (1 2 840 113549 2 9) +// 131 0: NULL +// : } +// : } +// : } +// 133 29: SEQUENCE { +// 135 9: OBJECT IDENTIFIER +// : aes256-CBC (2 16 840 1 101 3 4 1 42) +// 146 16: OCTET STRING +// : 2E 23 6C 8C 7A 44 0C 3E 0F 4E 0D 32 C9 90 E9 97 +// : } +// : } +// : } +// 164 816: [0] +// : 85 52 18 B2 A1 7A 46 59 0D 64 F8 39 52 CC BF 79 +// : 50 AA 2B 7A DF 24 9C 8F A4 9E 3A FB 03 7F 05 CD +// : 8A 18 F4 6E 28 B0 AA 99 D0 07 4E 4C DF 31 A5 E7 +// : C0 4B 8E 55 49 39 B9 5D 52 07 00 06 A1 39 53 17 +// : A8 D1 9B 16 7B 31 51 0C 67 9A 5C 5E B7 16 B5 E2 +// : BB 24 2E A8 7C 30 95 2B 0F 3C FF D7 3F F1 B2 13 +// : E5 8D 4D 49 70 F3 41 2B 20 57 51 C8 53 C4 EA 60 +// : 11 05 AF 87 A7 8B 40 E7 96 61 0D 7E B2 6A 8A 76 +// : [ Another 688 bytes skipped ] +// : } +// : } +// : } +// : } +// 984 820: SEQUENCE { +// 988 9: OBJECT IDENTIFIER data (1 2 840 113549 1 7 1) +// 999 805: [0] { +// 1003 801: OCTET STRING, encapsulates { +// 1007 797: SEQUENCE { +// 1011 793: SEQUENCE { +// 1015 11: OBJECT IDENTIFIER +// : pkcs-12-pkcs-8ShroudedKeyBag (1 2 840 113549 1 12 10 1 2) +// 1028 737: [0] { +// 1032 733: SEQUENCE { +// 1036 87: SEQUENCE { +// 1038 9: OBJECT IDENTIFIER +// : pkcs5PBES2 (1 2 840 113549 1 5 13) +// 1049 74: SEQUENCE { +// 1051 41: SEQUENCE { +// 1053 9: OBJECT IDENTIFIER +// : pkcs5PBKDF2 (1 2 840 113549 1 5 12) +// 1064 28: SEQUENCE { +// 1066 8: OCTET STRING 10 AF 41 1E 77 84 BA CD +// 1076 2: INTEGER 2048 +// 1080 12: SEQUENCE { +// 1082 8: OBJECT IDENTIFIER +// : hmacWithSHA256 (1 2 840 113549 2 9) +// 1092 0: NULL +// : } +// : } +// : } +// 1094 29: SEQUENCE { +// 1096 9: OBJECT IDENTIFIER +// : aes256-CBC (2 16 840 1 101 3 4 1 42) +// 1107 16: OCTET STRING +// : 46 21 13 61 4C 99 4D 1F DA 70 B4 71 16 5A AE 4A +// : } +// : } +// : } +// 1125 640: OCTET STRING +// : 2F 92 BB F4 9C B4 53 90 85 09 54 3B 4F 67 01 3A +// : F5 5E 69 14 3A 03 B7 0A 12 3F 9E 80 CB 8A 1F 19 +// : 42 84 5F AC 3E C2 D4 0F 97 F5 B4 66 F1 A8 A3 68 +// : F9 59 E2 7B 62 52 15 1B 61 63 48 3D 83 8A 9E 88 +// : 6F F3 BA 9D A7 91 B6 CF 6B 87 87 E6 2E 72 2C D3 +// : A6 C5 54 43 D3 84 3D 16 78 80 A7 E8 AD 50 8F D6 +// : 87 82 B6 8A 70 84 AB 93 26 9D A9 9B 64 7E 98 41 +// : 5D CB 59 04 24 94 39 71 B0 F1 94 4A E8 5D 8C B4 +// : [ Another 512 bytes skipped ] +// : } +// : } +// 1769 37: SET { +// 1771 35: SEQUENCE { +// 1773 9: OBJECT IDENTIFIER +// : localKeyID (for PKCS #12) (1 2 840 113549 1 9 21) +// 1784 22: SET { +// 1786 20: OCTET STRING +// : EF 09 61 31 5F 51 9D 61 F2 69 7D 9E 75 E5 52 15 +// : D0 7B 00 6D +// : } +// : } +// : } +// : } +// : } +// : } +// : } +// : } +// : } +// : } +// : } +// : } +// 1808 65: SEQUENCE { +// 1810 49: SEQUENCE { +// 1812 13: SEQUENCE { +// 1814 9: OBJECT IDENTIFIER sha-256 (2 16 840 1 101 3 4 2 1) +// 1825 0: NULL +// : } +// 1827 32: OCTET STRING +// : 10 06 A1 92 F8 EE F8 A4 A2 46 6F EB 87 16 69 57 +// : B9 63 CD CB C9 DC D7 73 6F 47 3C BB 11 EC 00 D7 +// : } +// 1861 8: OCTET STRING FF 08 ED 21 81 C8 A8 E3 +// 1871 2: INTEGER 2048 +// : } +// : } +#[test] +fn decode_sample_pfx() { + let bytes = include_bytes!("examples/example.pfx"); + + let pfx = Pfx::from_der(bytes).expect("expected valid data"); + let reenc_content = pfx.to_der().unwrap(); + assert_eq!(bytes, reenc_content.as_slice()); + println!("{:?}", pfx); + + assert_eq!(Version::V3, pfx.version); + assert_eq!(ID_DATA, pfx.auth_safe.content_type); + let auth_safes_os = OctetString::from_der(&pfx.auth_safe.content.to_der().unwrap()).unwrap(); + let auth_safes = AuthenticatedSafe::from_der(auth_safes_os.as_bytes()).unwrap(); + + // Process first auth safe (from offset 34) + let auth_safe0 = auth_safes.get(0).unwrap(); + assert_eq!(ID_ENCRYPTED_DATA, auth_safe0.content_type); + let enc_data_os = &auth_safe0.content.to_der().unwrap(); + let enc_data = EncryptedData::from_der(enc_data_os.as_slice()).unwrap(); + assert_eq!(ID_DATA, enc_data.enc_content_info.content_type); + assert_eq!(PBES2_OID, enc_data.enc_content_info.content_enc_alg.oid); + let enc_params = enc_data + .enc_content_info + .content_enc_alg + .parameters + .as_ref() + .unwrap() + .to_der() + .unwrap(); + + let params = pkcs8::pkcs5::pbes2::Parameters::from_der(&enc_params).unwrap(); + + let scheme = pkcs5::EncryptionScheme::try_from(params.clone()).unwrap(); + let ciphertext_os = enc_data.enc_content_info.encrypted_content.clone().unwrap(); + let mut ciphertext = ciphertext_os.as_bytes().to_vec(); + let plaintext = scheme.decrypt_in_place("", &mut ciphertext).unwrap(); + let cert_bags = SafeContents::from_der(&plaintext).unwrap(); + for cert_bag in cert_bags { + match cert_bag.bag_id { + pkcs12::PKCS_12_CERT_BAG_OID => { + let cs: der::asn1::ContextSpecific = + ContextSpecific::from_der(&cert_bag.bag_value).unwrap(); + let cb = cs.value; + assert_eq!( + include_bytes!("examples/cert.der"), + cb.cert_value.as_bytes() + ); + } + _ => panic!(), + }; + } + + let k = params.kdf.to_der().unwrap(); + let kdf_alg_info = AlgorithmIdentifierOwned::from_der(&k).unwrap(); + assert_eq!(PBKDF2_OID, kdf_alg_info.oid); + let k_params = kdf_alg_info.parameters.unwrap().to_der().unwrap(); + + let pbkdf2_params = Pbkdf2Params::from_der(&k_params).unwrap(); + assert_eq!(2048, pbkdf2_params.iteration_count); + assert_eq!( + hex!("9A A2 77 B5 F0 51 B4 50"), + pbkdf2_params.salt.as_bytes() + ); + assert_eq!(HMAC_WITH_SHA256_OID, pbkdf2_params.prf.oid); + + let e = params.encryption.to_der().unwrap(); + let enc_alg_info = AlgorithmIdentifierOwned::from_der(&e).unwrap(); + assert_eq!(AES_256_CBC_OID, enc_alg_info.oid); + assert_eq!( + hex!("04 10 2E 23 6C 8C 7A 44 0C 3E 0F 4E 0D 32 C9 90 E9 97"), + enc_alg_info.parameters.to_der().unwrap().as_slice() + ); + + // Process second auth safe (from offset 984) + let auth_safe1 = auth_safes.get(1).unwrap(); + assert_eq!(ID_DATA, auth_safe1.content_type); + + let auth_safe1_auth_safes_os = + OctetString::from_der(&auth_safe1.content.to_der().unwrap()).unwrap(); + let safe_bags = SafeContents::from_der(auth_safe1_auth_safes_os.as_bytes()).unwrap(); + for safe_bag in safe_bags { + match safe_bag.bag_id { + pkcs12::PKCS_12_PKCS8_KEY_BAG_OID => { + let cs: ContextSpecific = + ContextSpecific::from_der(&safe_bag.bag_value).unwrap(); + let mut ciphertext = cs.value.encrypted_data.to_vec(); + let plaintext = cs + .value + .encryption_algorithm + .decrypt_in_place("", &mut ciphertext) + .unwrap(); + assert_eq!(include_bytes!("examples/key.der"), plaintext); + + //todo inspect parameters + } + _ => panic!(), + }; + } + + // process mac data + let mac_data = pfx.mac_data.unwrap(); + assert_eq!(ID_SHA_256, mac_data.mac.algorithm.oid); + assert_eq!(hex!("10 06 A1 92 F8 EE F8 A4 A2 46 6F EB 87 16 69 57 B9 63 CD CB C9 DC D7 73 6F 47 3C BB 11 EC 00 D7"), mac_data.mac.digest.as_bytes()); + assert_eq!( + hex!("FF 08 ED 21 81 C8 A8 E3"), + mac_data.mac_salt.as_bytes() + ); + assert_eq!(2048, mac_data.iterations); +} + +// 0 1752: SEQUENCE { +// 4 1: INTEGER 3 +// 7 1678: SEQUENCE { +// 11 9: OBJECT IDENTIFIER data (1 2 840 113549 1 7 1) +// 22 1663: [0] { +// 26 1659: OCTET STRING, encapsulates { +// 30 1655: SEQUENCE { +// 34 827: SEQUENCE { +// 38 9: OBJECT IDENTIFIER data (1 2 840 113549 1 7 1) +// 49 812: [0] { +// 53 808: OCTET STRING, encapsulates { +// 57 804: SEQUENCE { +// 61 800: SEQUENCE { +// 65 11: OBJECT IDENTIFIER +// : pkcs-12-certBag (1 2 840 113549 1 12 10 1 3) +// 78 744: [0] { +// 82 740: SEQUENCE { +// 86 10: OBJECT IDENTIFIER +// : x509Certificate (for PKCS #12) (1 2 840 113549 1 9 22 1) +// 98 724: [0] { +// 102 720: OCTET STRING, encapsulates { +// 106 716: SEQUENCE { +// 110 565: SEQUENCE { +// 114 3: [0] { +// 116 1: INTEGER 2 +// : } +// 119 20: INTEGER +// : 64 C0 EB 72 59 55 A3 2A 66 1F D7 7C 98 67 4F 00 +// : 29 30 59 1B +// 141 13: SEQUENCE { +// 143 9: OBJECT IDENTIFIER +// : sha256WithRSAEncryption (1 2 840 113549 1 1 11) +// 154 0: NULL +// : } +// 156 120: SEQUENCE { +// 158 11: SET { +// 160 9: SEQUENCE { +// 162 3: OBJECT IDENTIFIER +// : countryName (2 5 4 6) +// 167 2: PrintableString 'DK' +// : } +// : } +// 171 20: SET { +// 173 18: SEQUENCE { +// 175 3: OBJECT IDENTIFIER +// : stateOrProvinceName (2 5 4 8) +// 180 11: UTF8String 'Hovedstaden' +// : } +// : } +// 193 21: SET { +// 195 19: SEQUENCE { +// 197 3: OBJECT IDENTIFIER +// : localityName (2 5 4 7) +// 202 12: UTF8String 'K....benhavn' +// : } +// : } +// 216 12: SET { +// 218 10: SEQUENCE { +// 220 3: OBJECT IDENTIFIER +// : organizationName (2 5 4 10) +// 225 3: UTF8String '...' +// : } +// : } +// 230 12: SET { +// 232 10: SEQUENCE { +// 234 3: OBJECT IDENTIFIER +// : organizationalUnitName (2 5 4 11) +// 239 3: UTF8String '...' +// : } +// : } +// 244 12: SET { +// 246 10: SEQUENCE { +// 248 3: OBJECT IDENTIFIER +// : commonName (2 5 4 3) +// 253 3: UTF8String '...' +// : } +// : } +// 258 18: SET { +// 260 16: SEQUENCE { +// 262 9: OBJECT IDENTIFIER +// : emailAddress (1 2 840 113549 1 9 1) +// 273 3: IA5String '...' +// : } +// : } +// : } +// 278 30: SEQUENCE { +// 280 13: UTCTime 03/01/2023 17:20:50 GMT +// 295 13: UTCTime 03/01/2024 17:20:50 GMT +// : } +// 310 120: SEQUENCE { +// 312 11: SET { +// 314 9: SEQUENCE { +// 316 3: OBJECT IDENTIFIER +// : countryName (2 5 4 6) +// 321 2: PrintableString 'DK' +// : } +// : } +// 325 20: SET { +// 327 18: SEQUENCE { +// 329 3: OBJECT IDENTIFIER +// : stateOrProvinceName (2 5 4 8) +// 334 11: UTF8String 'Hovedstaden' +// : } +// : } +// 347 21: SET { +// 349 19: SEQUENCE { +// 351 3: OBJECT IDENTIFIER +// : localityName (2 5 4 7) +// 356 12: UTF8String 'K....benhavn' +// : } +// : } +// 370 12: SET { +// 372 10: SEQUENCE { +// 374 3: OBJECT IDENTIFIER +// : organizationName (2 5 4 10) +// 379 3: UTF8String '...' +// : } +// : } +// 384 12: SET { +// 386 10: SEQUENCE { +// 388 3: OBJECT IDENTIFIER +// : organizationalUnitName (2 5 4 11) +// 393 3: UTF8String '...' +// : } +// : } +// 398 12: SET { +// 400 10: SEQUENCE { +// 402 3: OBJECT IDENTIFIER +// : commonName (2 5 4 3) +// 407 3: UTF8String '...' +// : } +// : } +// 412 18: SET { +// 414 16: SEQUENCE { +// 416 9: OBJECT IDENTIFIER +// : emailAddress (1 2 840 113549 1 9 1) +// 427 3: IA5String '...' +// : } +// : } +// : } +// 432 159: SEQUENCE { +// 435 13: SEQUENCE { +// 437 9: OBJECT IDENTIFIER +// : rsaEncryption (1 2 840 113549 1 1 1) +// 448 0: NULL +// : } +// 450 141: BIT STRING, encapsulates { +// 454 137: SEQUENCE { +// 457 129: INTEGER +// : 00 B1 71 2C BD AB C7 58 A5 6D F5 E2 23 78 8C 22 +// : B8 C8 7A 7B B7 B9 C1 F2 B0 C6 21 D2 DD 5F EA 64 +// : F2 02 A0 EC 83 B0 B9 54 48 79 08 44 85 6C 61 1C +// : D7 4B EE E5 9A C6 7F 1D E2 44 4A 45 CA E2 BF B0 +// : C7 F8 0C 9F 89 1C DC 39 9D E9 8C 05 C4 72 79 D1 +// : DC 73 1D AA 2C 3A 9E 4E 6B 70 45 00 8F 69 22 66 +// : E8 3D 69 18 00 91 46 3A 43 32 5F EC F8 51 64 C4 +// : F5 01 78 61 9E AE 42 65 6E 8C 3E AC 2E 40 9D 94 +// : B7 +// 589 3: INTEGER 65537 +// : } +// : } +// : } +// 594 83: [3] { +// 596 81: SEQUENCE { +// 598 29: SEQUENCE { +// 600 3: OBJECT IDENTIFIER +// : subjectKeyIdentifier (2 5 29 14) +// 605 22: OCTET STRING, encapsulates { +// 607 20: OCTET STRING +// : 7A 80 DB 37 D1 0D FE 24 FA B1 D2 74 DD C9 6D 4E +// : 0C 15 94 43 +// : } +// : } +// 629 31: SEQUENCE { +// 631 3: OBJECT IDENTIFIER +// : authorityKeyIdentifier (2 5 29 35) +// 636 24: OCTET STRING, encapsulates { +// 638 22: SEQUENCE { +// 640 20: [0] +// : 7A 80 DB 37 D1 0D FE 24 FA B1 D2 74 DD C9 6D 4E +// : 0C 15 94 43 +// : } +// : } +// : } +// 662 15: SEQUENCE { +// 664 3: OBJECT IDENTIFIER +// : basicConstraints (2 5 29 19) +// 669 1: BOOLEAN TRUE +// 672 5: OCTET STRING, encapsulates { +// 674 3: SEQUENCE { +// 676 1: BOOLEAN TRUE +// : } +// : } +// : } +// : } +// : } +// : } +// 679 13: SEQUENCE { +// 681 9: OBJECT IDENTIFIER +// : sha256WithRSAEncryption (1 2 840 113549 1 1 11) +// 692 0: NULL +// : } +// 694 129: BIT STRING +// : 03 2F 63 C5 7D 4A 2F B5 66 31 91 40 2A 92 4E D9 +// : 64 69 A9 18 38 47 E0 9D FA 97 39 46 C6 36 73 BA +// : EE FB 09 6D 25 F7 4B 40 86 D1 C8 8C 6D A2 31 C8 +// : C1 B6 4E 44 73 49 F2 62 38 33 9B 94 2E 51 9D 78 +// : 3B 10 5D 27 53 4A 0D 04 86 30 DC 56 38 D2 54 C3 +// : AC 28 2A 41 5E 1A 11 84 9C 3C 29 AE 1D 2E E9 18 +// : CF 3B 55 3A DC C5 B3 18 FB 5B CF AB A8 92 69 D9 +// : F8 8A 38 9F 39 A0 69 8F B6 79 7A C5 B0 55 A5 29 +// : } +// : } +// : } +// : } +// : } +// 826 37: SET { +// 828 35: SEQUENCE { +// 830 9: OBJECT IDENTIFIER +// : localKeyID (for PKCS #12) (1 2 840 113549 1 9 21) +// 841 22: SET { +// 843 20: OCTET STRING +// : EF 09 61 31 5F 51 9D 61 F2 69 7D 9E 75 E5 52 15 +// : D0 7B 00 6D +// : } +// : } +// : } +// : } +// : } +// : } +// : } +// : } +// 865 820: SEQUENCE { +// 869 9: OBJECT IDENTIFIER data (1 2 840 113549 1 7 1) +// 880 805: [0] { +// 884 801: OCTET STRING, encapsulates { +// 888 797: SEQUENCE { +// 892 793: SEQUENCE { +// 896 11: OBJECT IDENTIFIER +// : pkcs-12-pkcs-8ShroudedKeyBag (1 2 840 113549 1 12 10 1 2) +// 909 737: [0] { +// 913 733: SEQUENCE { +// 917 87: SEQUENCE { +// 919 9: OBJECT IDENTIFIER +// : pkcs5PBES2 (1 2 840 113549 1 5 13) +// 930 74: SEQUENCE { +// 932 41: SEQUENCE { +// 934 9: OBJECT IDENTIFIER +// : pkcs5PBKDF2 (1 2 840 113549 1 5 12) +// 945 28: SEQUENCE { +// 947 8: OCTET STRING CA 65 8B 95 83 F0 79 23 +// 957 2: INTEGER 2048 +// 961 12: SEQUENCE { +// 963 8: OBJECT IDENTIFIER +// : hmacWithSHA256 (1 2 840 113549 2 9) +// 973 0: NULL +// : } +// : } +// : } +// 975 29: SEQUENCE { +// 977 9: OBJECT IDENTIFIER +// : aes256-CBC (2 16 840 1 101 3 4 1 42) +// 988 16: OCTET STRING +// : 74 4C 0F 63 4C 1D 26 94 80 08 C0 F0 DD E7 CA 4E +// : } +// : } +// : } +// 1006 640: OCTET STRING +// : 1D D7 61 88 5D EE CB C2 A5 90 EA 53 92 94 16 B5 +// : C1 58 EA CA 50 E3 AA 31 33 36 48 52 E9 6B 3D 4A +// : 54 C1 1E 2A 4E D3 42 9E B2 3A DC F1 A2 A1 05 D2 +// : 62 59 B2 81 6A 63 C3 8C 8E CD E4 2F 45 47 EB 0C +// : A6 9D A5 21 72 C2 4C 39 9F 03 70 BF 19 4B 21 78 +// : 72 39 47 16 CE B8 42 0A 84 11 90 CA 02 13 69 BF +// : 58 7F E3 D9 44 C1 FA 21 75 0A 13 46 43 FB BE 3F +// : 41 78 0A 8C C0 87 97 4E D6 EF F5 E5 D3 6E B6 96 +// : [ Another 512 bytes skipped ] +// : } +// : } +// 1650 37: SET { +// 1652 35: SEQUENCE { +// 1654 9: OBJECT IDENTIFIER +// : localKeyID (for PKCS #12) (1 2 840 113549 1 9 21) +// 1665 22: SET { +// 1667 20: OCTET STRING +// : EF 09 61 31 5F 51 9D 61 F2 69 7D 9E 75 E5 52 15 +// : D0 7B 00 6D +// : } +// : } +// : } +// : } +// : } +// : } +// : } +// : } +// : } +// : } +// : } +// : } +// 1689 65: SEQUENCE { +// 1691 49: SEQUENCE { +// 1693 13: SEQUENCE { +// 1695 9: OBJECT IDENTIFIER sha-256 (2 16 840 1 101 3 4 2 1) +// 1706 0: NULL +// : } +// 1708 32: OCTET STRING +// : BC 79 0E 04 37 14 F1 8F 9C 07 66 1D FE 53 82 E3 +// : E7 F4 31 13 27 E4 C8 E7 61 D0 BA 7A EA 54 A8 A8 +// : } +// 1742 8: OCTET STRING E1 14 4F 8C B4 AF B2 FE +// 1752 2: INTEGER 2048 +// : } +// : } +#[test] +fn decode_sample_pfx2() { + let bytes = include_bytes!("examples/example2.pfx"); + + let pfx = Pfx::from_der(bytes).expect("expected valid data"); + let reenc_content = pfx.to_der().unwrap(); + assert_eq!(bytes, reenc_content.as_slice()); + println!("{:?}", pfx); + + assert_eq!(Version::V3, pfx.version); + assert_eq!(ID_DATA, pfx.auth_safe.content_type); + let auth_safes_os = OctetString::from_der(&pfx.auth_safe.content.to_der().unwrap()).unwrap(); + let auth_safes = AuthenticatedSafe::from_der(auth_safes_os.as_bytes()).unwrap(); + + // Process first auth safe (from offset 34) + let auth_safe0 = auth_safes.get(0).unwrap(); + assert_eq!(ID_DATA, auth_safe0.content_type); + + let auth_safe0_auth_safes_os = + OctetString::from_der(&auth_safe0.content.to_der().unwrap()).unwrap(); + let safe_bags = SafeContents::from_der(auth_safe0_auth_safes_os.as_bytes()).unwrap(); + for safe_bag in safe_bags { + match safe_bag.bag_id { + pkcs12::PKCS_12_CERT_BAG_OID => { + let cs: ContextSpecific = + ContextSpecific::from_der(&safe_bag.bag_value).unwrap(); + assert_eq!( + include_bytes!("examples/cert.der"), + cs.value.cert_value.as_bytes() + ); + } + _ => panic!(), + }; + //todo inspect attributes + } + + // Process second auth safe (from offset 984) + let auth_safe1 = auth_safes.get(1).unwrap(); + assert_eq!(ID_DATA, auth_safe1.content_type); + + let auth_safe1_auth_safes_os = + OctetString::from_der(&auth_safe1.content.to_der().unwrap()).unwrap(); + let safe_bags = SafeContents::from_der(auth_safe1_auth_safes_os.as_bytes()).unwrap(); + for safe_bag in safe_bags { + match safe_bag.bag_id { + pkcs12::PKCS_12_PKCS8_KEY_BAG_OID => { + let cs: ContextSpecific = + ContextSpecific::from_der(&safe_bag.bag_value).unwrap(); + let mut ciphertext = cs.value.encrypted_data.to_vec(); + let plaintext = cs + .value + .encryption_algorithm + .decrypt_in_place("1234", &mut ciphertext) + .unwrap(); + assert_eq!(include_bytes!("examples/key.der"), plaintext); + + //todo inspect parameters + } + _ => panic!(), + }; + //todo inspect attributes + } + + // process mac data + let mac_data = pfx.mac_data.unwrap(); + assert_eq!(ID_SHA_256, mac_data.mac.algorithm.oid); + assert_eq!(hex!("BC 79 0E 04 37 14 F1 8F 9C 07 66 1D FE 53 82 E3 E7 F4 31 13 27 E4 C8 E7 61 D0 BA 7A EA 54 A8 A8"), mac_data.mac.digest.as_bytes()); + assert_eq!( + hex!("E1 14 4F 8C B4 AF B2 FE"), + mac_data.mac_salt.as_bytes() + ); + assert_eq!(2048, mac_data.iterations); +} diff --git a/pkcs12/tests/examples/GoodCACert.crt b/pkcs12/tests/examples/GoodCACert.crt new file mode 100644 index 000000000..8d4a96b82 --- /dev/null +++ b/pkcs12/tests/examples/GoodCACert.crt @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDfDCCAmSgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf +MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg +QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowQDELMAkGA1UE +BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExEDAOBgNVBAMT +B0dvb2QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCQWJpHYo37 +Xfb7oJSPe+WvfTlzIG21WQ7MyMbGtK/m8mejCzR6c+f/pJhEH/OcDSMsXq8h5kXa +BGqWK+vSwD/Pzp5OYGptXmGPcthDtAwlrafkGOS4GqIJ8+k9XGKs+vQUXJKsOk47 +RuzD6PZupq4s16xaLVqYbUC26UcY08GpnoLNHJZS/EmXw1ZZ3d4YZjNlpIpWFNHn +UGmdiGKXUPX/9H0fVjIAaQwjnGAbpgyCumWgzIwPpX+ElFOUr3z7BoVnFKhIXze+ +VmQGSWxZxvWDUN90Ul0tLEpLgk3OVxUB4VUGuf15OJOpgo1xibINPmWt14Vda2N9 +yrNKloJGZNqLAgMBAAGjfDB6MB8GA1UdIwQYMBaAFOR9X9FclYYILAWuvnW2ZafZ +XahmMB0GA1UdDgQWBBRYAYQkG7wrUpRKPaUQchRR9a86yTAOBgNVHQ8BAf8EBAMC +AQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wDQYJ +KoZIhvcNAQELBQADggEBADWHlxbmdTXNwBL/llwhQqwnazK7CC2WsXBBqgNPWj7m +tvQ+aLG8/50Qc2Sun7o2VnwF9D18UUe8Gj3uPUYH+oSI1vDdyKcjmMbKRU4rk0eo +3UHNDXwqIVc9CQS9smyV+x1HCwL4TTrq+LXLKx/qVij0Yqk+UJfAtrg2jnYKXsCu +FMBQQnWCGrwa1g1TphRp/RmYHnMynYFmZrXtzFz+U9XEA7C+gPq4kqDI/iVfIT1s +6lBtdB50lrDVwl2oYfAvW/6sC2se2QleZidUmrziVNP4oEeXINokU6T6p//HM1FG +QYw2jOvpKcKtWCSAnegEbgsGYzATKjmPJPJ0npHFqzM= +-----END CERTIFICATE----- diff --git a/pkcs12/tests/examples/GoodCACert.der b/pkcs12/tests/examples/GoodCACert.der new file mode 100644 index 000000000..edbfa648f Binary files /dev/null and b/pkcs12/tests/examples/GoodCACert.der differ diff --git a/pkcs12/tests/examples/ValidCertificatePathTest1EE.crt b/pkcs12/tests/examples/ValidCertificatePathTest1EE.crt new file mode 100644 index 000000000..69ba3019d Binary files /dev/null and b/pkcs12/tests/examples/ValidCertificatePathTest1EE.crt differ diff --git a/pkcs12/tests/examples/ValidCertificatePathTest1EE.key b/pkcs12/tests/examples/ValidCertificatePathTest1EE.key new file mode 100644 index 000000000..315eab08f Binary files /dev/null and b/pkcs12/tests/examples/ValidCertificatePathTest1EE.key differ diff --git a/pkcs12/tests/examples/ValidCertificatePathTest1EE.p12 b/pkcs12/tests/examples/ValidCertificatePathTest1EE.p12 new file mode 100644 index 000000000..a70d70b15 Binary files /dev/null and b/pkcs12/tests/examples/ValidCertificatePathTest1EE.p12 differ diff --git a/pkcs12/tests/examples/ValidCertificatePathTest1EE.pem b/pkcs12/tests/examples/ValidCertificatePathTest1EE.pem new file mode 100644 index 000000000..c95522b55 --- /dev/null +++ b/pkcs12/tests/examples/ValidCertificatePathTest1EE.pem @@ -0,0 +1,58 @@ +Bag Attributes + localKeyID: E1 28 46 4B E7 34 D0 F8 4B D9 28 51 6C 50 F1 5A 18 B5 2B 96 + friendlyName: Valid Certificate Path Test1 EE +subject=/C=US/O=Test Certificates 2011/CN=Valid EE Certificate Test1 +issuer=/C=US/O=Test Certificates 2011/CN=Good CA +-----BEGIN CERTIFICATE----- +MIIDeTCCAmGgAwIBAgIBATANBgkqhkiG9w0BAQsFADBAMQswCQYDVQQGEwJVUzEf +MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEQMA4GA1UEAxMHR29vZCBD +QTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaMFMxCzAJBgNVBAYTAlVT +MR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMSMwIQYDVQQDExpWYWxp +ZCBFRSBDZXJ0aWZpY2F0ZSBUZXN0MTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +AQoCggEBANncdxgQEBhgQfvneBAP+IR3cO8tblU7EaaZUj9t9L2hl/o2Hm5EQhHI +U/51hpteNxKIon3ZcQjUSTVxzkbPW9BZjmUf60I9yg7cTJDYVGnPXjiyIGDdg1Eu +39vVWziRWi3PmjO0b5aQ5XYUYkNphBDPVEH5Neqe1FqXnV4QWb3g5MNZidfe8nmw +h2sCwFmhKgCCFW9rEREAUzR0PfThzFZiouRl6COxgx1YUwiyMy2WvuV9M54QWidz +U91dmOJLEVNYkY/qchHsu5TyDQ9QrfIWtRoAJDHlFb0XBpCqJLGs3QxSHvCLaqu4 +9+3fY7TOlGi/XpbQRJbx+PR6Ogp5FVMCAwEAAaNrMGkwHwYDVR0jBBgwFoAUWAGE +JBu8K1KUSj2lEHIUUfWvOskwHQYDVR0OBBYEFKg8CZ1n9thHuqLQ/BhyVohAbZWV +MA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDQYJKoZI +hvcNAQELBQADggEBAB5a2Q+vYqW5Ury87AxhiBMBqgoPDUejnqmyFxv4o9ks0o04 +vjuyz9QxiM/OafSOx7lwBVHABofGlbT2avoxni3EF7Pt5XoZYRhujNHkDtqbbWyN +BpDuLNF5WNiEzZtB0xji/pHGXwAnFGV7Evovvai/NI4tzxdMWFswDy5pZkUmJiGY +0/OQrimHWk7Gvegofg+glOb/XLVcT92KYVkOBdL/xWnA04lK0cLlyPTICMP9KiNP +hABcLEQtg4rCPSLHPGDyinjjG0Zl2pmP+GPB1HqgcKZ6pxCbnax/vhTwRCOHWKwQ +FejzoL8eJcs2qwJpWq7/wG6wQ54Inhk8pzBujcI= +-----END CERTIFICATE----- +Bag Attributes + localKeyID: E1 28 46 4B E7 34 D0 F8 4B D9 28 51 6C 50 F1 5A 18 B5 2B 96 + friendlyName: Valid Certificate Path Test1 EE +Key Attributes: +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDZ3HcYEBAYYEH7 +53gQD/iEd3DvLW5VOxGmmVI/bfS9oZf6Nh5uREIRyFP+dYabXjcSiKJ92XEI1Ek1 +cc5Gz1vQWY5lH+tCPcoO3EyQ2FRpz144siBg3YNRLt/b1Vs4kVotz5oztG+WkOV2 +FGJDaYQQz1RB+TXqntRal51eEFm94OTDWYnX3vJ5sIdrAsBZoSoAghVvaxERAFM0 +dD304cxWYqLkZegjsYMdWFMIsjMtlr7lfTOeEFonc1PdXZjiSxFTWJGP6nIR7LuU +8g0PUK3yFrUaACQx5RW9FwaQqiSxrN0MUh7wi2qruPft32O0zpRov16W0ESW8fj0 +ejoKeRVTAgMBAAECggEAYWTP0PANYfhWRzj5UaTyIrYKxMH4mx2nDGVqgXS0frno +6TCcdgsJxk1aT11W6co6sIxop/43LA1LFRtlbf5xOzluEQMt9xUMaYxOpkovooXT +x2DKXMNqWzarWOmOuEEyoVw3wXmekR8BlcITE7PuGF23ey7fzZ1nrYAuF8kTdXBr +XeIrzSYHdR11Y9YQoDZQMQPeR9QiHOmHRD1JQLJUplEt+z8Z7af1P22CgRtLDC8I +ULhtVCbCGOjXjf4UzWHtMrqVlp0Yw/kn/L6kC4D3tasVQkDxpfl24H8OfOlRsMQY ++cWyWOSwLCxgXAByW25oP7DRw3STGyyRGqHW4j9yQQKBgQDx2VCj+0z/f1FdKdXO +jFEO2bTvGzHsW9Lf0nwdm2S4cmrVh6lWOtnJveIebJYE4bf9kygQyYtWsNGMTbo0 +P6ye9A8RzoZouEx2loncD13J6rkmb8EIzfH26T+QJw8WOHpF5hZ0TwCiUI7ZS+Nn +3rKegMMh9cu6ni4gUGpj1fp4EQKBgQDmm9Xjrt93MDk4m7QznNhKM6U5YUqVpLOB +I1T2DwvS9odPJlfUkoOkIMCv5Q4TohgSHQsBD++T2YSkxwEOK7DuTaxxbrUuXx0z +8D8MBSpHHB6aIoMEnJiJdsRn0hgN4OZPzDFjzBqHD0xVDGdVS4VkxUCAU7hgGjdX +DIFYT2L7IwKBgHH7MJVIL77Om2Mj/19MJDuygSKbl4jEsfrIsbQmc262hgFC4Z0B +OXlqI3KhTIbadqNswlo/Eot15ByS2WochFeZwKxswE4EZg0R38E2AMbT+BTUYI6s +uRfcUBe5QNQBJCdjTDveq/bTrq9co71laJtpJg4QUMcQG78hBzMsOtJxAoGBAOVB +BuHSd1WGG1yrbfnhcyRRM3BXyE377nfzKAN18ctISjvlYmtxPG1uIiC7FcNu4X8g +YFAuB350P+mP7Pypcrt1fHlIFdaDuARqUkMg32bSDZottRJgm0QNTjPoKQGjE1NB +K9iKj9S04K2sJw4khfgoIHdyw1jGtz1SsUOZqE0BAoGAXYne8Sfkk+85JJpCamvW +7ziUul7LNdz3eit8YGFsc209Ll6aW5q+HdTw0OvaDkP6ubniihq4ikh7oyxRWJHl +mFCfdOD9g+T2/11lIv++URzEWI0JQgKTrxMhcOhpH1MYK7IHDYyQQHB0PYff9U18 +1Vy+pKyH6RtWdRoDDkzuM3M= +-----END PRIVATE KEY----- diff --git a/pkcs12/tests/examples/ValidCertificatePathTest1EE_firefox.p12 b/pkcs12/tests/examples/ValidCertificatePathTest1EE_firefox.p12 new file mode 100644 index 000000000..e0119db1c Binary files /dev/null and b/pkcs12/tests/examples/ValidCertificatePathTest1EE_firefox.p12 differ diff --git a/pkcs12/tests/examples/ValidCertificatePathTest1EE_macos.p12 b/pkcs12/tests/examples/ValidCertificatePathTest1EE_macos.p12 new file mode 100644 index 000000000..f6a525fbb Binary files /dev/null and b/pkcs12/tests/examples/ValidCertificatePathTest1EE_macos.p12 differ diff --git a/pkcs12/tests/examples/ValidCertificatePathTest1EE_windows_aes.p12.pfx b/pkcs12/tests/examples/ValidCertificatePathTest1EE_windows_aes.p12.pfx new file mode 100644 index 000000000..8163d8819 Binary files /dev/null and b/pkcs12/tests/examples/ValidCertificatePathTest1EE_windows_aes.p12.pfx differ diff --git a/pkcs12/tests/examples/ValidCertificatePathTest1EE_windows_tdes.p12.pfx b/pkcs12/tests/examples/ValidCertificatePathTest1EE_windows_tdes.p12.pfx new file mode 100644 index 000000000..dc0ceb6ba Binary files /dev/null and b/pkcs12/tests/examples/ValidCertificatePathTest1EE_windows_tdes.p12.pfx differ diff --git a/pkcs12/tests/examples/cert.der b/pkcs12/tests/examples/cert.der new file mode 100644 index 000000000..214457402 Binary files /dev/null and b/pkcs12/tests/examples/cert.der differ diff --git a/pkcs12/tests/examples/cert.pem b/pkcs12/tests/examples/cert.pem new file mode 100644 index 000000000..3f7664224 --- /dev/null +++ b/pkcs12/tests/examples/cert.pem @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICzDCCAjWgAwIBAgIUZMDrcllVoypmH9d8mGdPACkwWRswDQYJKoZIhvcNAQEL +BQAweDELMAkGA1UEBhMCREsxFDASBgNVBAgMC0hvdmVkc3RhZGVuMRUwEwYDVQQH +DAxLw4PCuGJlbmhhdm4xDDAKBgNVBAoMAy4uLjEMMAoGA1UECwwDLi4uMQwwCgYD +VQQDDAMuLi4xEjAQBgkqhkiG9w0BCQEWAy4uLjAeFw0yMzAxMDMxNzIwNTBaFw0y +NDAxMDMxNzIwNTBaMHgxCzAJBgNVBAYTAkRLMRQwEgYDVQQIDAtIb3ZlZHN0YWRl +bjEVMBMGA1UEBwwMS8ODwrhiZW5oYXZuMQwwCgYDVQQKDAMuLi4xDDAKBgNVBAsM +Ay4uLjEMMAoGA1UEAwwDLi4uMRIwEAYJKoZIhvcNAQkBFgMuLi4wgZ8wDQYJKoZI +hvcNAQEBBQADgY0AMIGJAoGBALFxLL2rx1ilbfXiI3iMIrjIenu3ucHysMYh0t1f +6mTyAqDsg7C5VEh5CESFbGEc10vu5ZrGfx3iREpFyuK/sMf4DJ+JHNw5nemMBcRy +edHccx2qLDqeTmtwRQCPaSJm6D1pGACRRjpDMl/s+FFkxPUBeGGerkJlbow+rC5A +nZS3AgMBAAGjUzBRMB0GA1UdDgQWBBR6gNs30Q3+JPqx0nTdyW1ODBWUQzAfBgNV +HSMEGDAWgBR6gNs30Q3+JPqx0nTdyW1ODBWUQzAPBgNVHRMBAf8EBTADAQH/MA0G +CSqGSIb3DQEBCwUAA4GBAAMvY8V9Si+1ZjGRQCqSTtlkaakYOEfgnfqXOUbGNnO6 +7vsJbSX3S0CG0ciMbaIxyMG2TkRzSfJiODOblC5RnXg7EF0nU0oNBIYw3FY40lTD +rCgqQV4aEYScPCmuHS7pGM87VTrcxbMY+1vPq6iSadn4ijifOaBpj7Z5esWwVaUp +-----END CERTIFICATE----- diff --git a/pkcs12/tests/examples/example.pfx b/pkcs12/tests/examples/example.pfx new file mode 100644 index 000000000..d591096d8 Binary files /dev/null and b/pkcs12/tests/examples/example.pfx differ diff --git a/pkcs12/tests/examples/example10.pfx b/pkcs12/tests/examples/example10.pfx new file mode 100644 index 000000000..380db35bf Binary files /dev/null and b/pkcs12/tests/examples/example10.pfx differ diff --git a/pkcs12/tests/examples/example11.pfx b/pkcs12/tests/examples/example11.pfx new file mode 100644 index 000000000..1474eaf26 Binary files /dev/null and b/pkcs12/tests/examples/example11.pfx differ diff --git a/pkcs12/tests/examples/example12.pfx b/pkcs12/tests/examples/example12.pfx new file mode 100644 index 000000000..9f45748e9 Binary files /dev/null and b/pkcs12/tests/examples/example12.pfx differ diff --git a/pkcs12/tests/examples/example13.pfx b/pkcs12/tests/examples/example13.pfx new file mode 100644 index 000000000..e38a8dbd8 Binary files /dev/null and b/pkcs12/tests/examples/example13.pfx differ diff --git a/pkcs12/tests/examples/example14.pfx b/pkcs12/tests/examples/example14.pfx new file mode 100644 index 000000000..6ede0a324 Binary files /dev/null and b/pkcs12/tests/examples/example14.pfx differ diff --git a/pkcs12/tests/examples/example15.pfx b/pkcs12/tests/examples/example15.pfx new file mode 100644 index 000000000..a4d5a3b16 Binary files /dev/null and b/pkcs12/tests/examples/example15.pfx differ diff --git a/pkcs12/tests/examples/example16.pfx b/pkcs12/tests/examples/example16.pfx new file mode 100644 index 000000000..719d0ff0d Binary files /dev/null and b/pkcs12/tests/examples/example16.pfx differ diff --git a/pkcs12/tests/examples/example17.pfx b/pkcs12/tests/examples/example17.pfx new file mode 100644 index 000000000..5ef36a150 Binary files /dev/null and b/pkcs12/tests/examples/example17.pfx differ diff --git a/pkcs12/tests/examples/example2.pfx b/pkcs12/tests/examples/example2.pfx new file mode 100644 index 000000000..6ff4319f7 Binary files /dev/null and b/pkcs12/tests/examples/example2.pfx differ diff --git a/pkcs12/tests/examples/example3.pfx b/pkcs12/tests/examples/example3.pfx new file mode 100644 index 000000000..c47198fc1 Binary files /dev/null and b/pkcs12/tests/examples/example3.pfx differ diff --git a/pkcs12/tests/examples/example4.pfx b/pkcs12/tests/examples/example4.pfx new file mode 100644 index 000000000..7e40eec38 Binary files /dev/null and b/pkcs12/tests/examples/example4.pfx differ diff --git a/pkcs12/tests/examples/example5.pfx b/pkcs12/tests/examples/example5.pfx new file mode 100644 index 000000000..a2755e149 Binary files /dev/null and b/pkcs12/tests/examples/example5.pfx differ diff --git a/pkcs12/tests/examples/example6.pfx b/pkcs12/tests/examples/example6.pfx new file mode 100644 index 000000000..67b578845 Binary files /dev/null and b/pkcs12/tests/examples/example6.pfx differ diff --git a/pkcs12/tests/examples/example7.pfx b/pkcs12/tests/examples/example7.pfx new file mode 100644 index 000000000..2f5b733a5 Binary files /dev/null and b/pkcs12/tests/examples/example7.pfx differ diff --git a/pkcs12/tests/examples/example8.pfx b/pkcs12/tests/examples/example8.pfx new file mode 100644 index 000000000..fd5a5fa29 Binary files /dev/null and b/pkcs12/tests/examples/example8.pfx differ diff --git a/pkcs12/tests/examples/example9.pfx b/pkcs12/tests/examples/example9.pfx new file mode 100644 index 000000000..0ef7a63b7 Binary files /dev/null and b/pkcs12/tests/examples/example9.pfx differ diff --git a/pkcs12/tests/examples/gen.sh b/pkcs12/tests/examples/gen.sh new file mode 100644 index 000000000..02b71df7d --- /dev/null +++ b/pkcs12/tests/examples/gen.sh @@ -0,0 +1,3 @@ +openssl req -x509 -newkey rsa:1024 -keyout key.pem -out cert.pem -sha256 -days 365 -noenc -subj "/C=DK/ST=Hovedstaden/L=København/O=.../OU=.../CN=.../emailAddress=..." +openssl pkcs12 -export -out example.pfx -inkey key.pem -in cert.pem -passout pass: +openssl pkcs12 -export -out example2.pfx -in cert.pem -inkey key.pem -certpbe NONE -passout pass:1234 \ No newline at end of file diff --git a/pkcs12/tests/examples/key.der b/pkcs12/tests/examples/key.der new file mode 100644 index 000000000..ed0701158 Binary files /dev/null and b/pkcs12/tests/examples/key.der differ diff --git a/pkcs12/tests/examples/key.pem b/pkcs12/tests/examples/key.pem new file mode 100644 index 000000000..2e4e9f85f --- /dev/null +++ b/pkcs12/tests/examples/key.pem @@ -0,0 +1,16 @@ +-----BEGIN PRIVATE KEY----- +MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBALFxLL2rx1ilbfXi +I3iMIrjIenu3ucHysMYh0t1f6mTyAqDsg7C5VEh5CESFbGEc10vu5ZrGfx3iREpF +yuK/sMf4DJ+JHNw5nemMBcRyedHccx2qLDqeTmtwRQCPaSJm6D1pGACRRjpDMl/s ++FFkxPUBeGGerkJlbow+rC5AnZS3AgMBAAECgYBoT+8MZbKgI0hcVx+hG0jCNmEC +4AQcx04ye+nZaCyEQV1YOxJDzv+ER1qb5Y/MG0daBUwHTA+ogr7ApvzZhfUm7qB/ +ISf57QmoJc+60x8u45VXxOSMPuTHXWAwY56kSLglFbDFyy0dA02vsXo3PZ/DLa8Q +sEaGmZUMJYgWUGBX+QJBAN1EQE7jiPs3tOizuCNrw8LIxkMPjrm7FU0BTA3CcmqA +K5FXh6WDTeMvp+fstjscpWrg9buSUTBWHR8uO0AUKBUCQQDNS846s57CtFbcldOL +UMfvEkZ73HuaXF6wPb8SoaUPR/9AhQaWCfQuBkzi4rW8ZGPigxl4hS6BA2zkqIk8 +SBCbAkEA0Na6W7smbvYFKh12jvgHrLETb/gfHe4WDLhMsC/3Dc4rUOLshKuJuAQi +1iP1W5WOC3KIfKF9P8IHeoaIJdLggQJBALQeuoZOahCyYTOQUNZ+vaxIAIdT3y6D +tKA0zJvwLv3FUXKuRCUH/rES3gqClqj/+5MVKxfO4gpXkwbbx+yX3dkCQQDaQrrB +HvJ3l5F5SY5jFOsQY27dfXqdhbTRTQtE+uqAd3lwOix0mjROAfiXXXJ6I95cXUFb +EtKC5DoanfxFWn49 +-----END PRIVATE KEY-----