pkcs12.rs
Overview
The pkcs12.rs file provides a comprehensive implementation of the PKCS#12 (Public-Key Cryptography Standards #12) data structures and cryptographic operations for securely packaging and encrypting private keys, certificates, and related attributes. It supports creating PKCS#12 PFX (Personal Information Exchange) files that include certificates, private keys (optionally encrypted), and certificate authority (CA) certificates, along with associated metadata such as friendly names and local key IDs.
This file primarily handles ASN.1 encoding/decoding via the yasna crate, password-based encryption (PBE) using SHA-1 and symmetric ciphers (RC2 and Triple-DES), message authentication codes (MACs) via HMAC-SHA1, and management of the PKCS#12 safe bags and content info structures.
Key cryptographic algorithms and data types are represented as Rust structs and enums, with encoding methods that produce DER-encoded bytes conforming to the PKCS#12 specification.
Constants and Static OIDs
Object Identifiers (OIDs): The file declares many PKCS#12 and related OIDs as
lazy_staticvariables, such as:OID_DATA_CONTENT_TYPEOID_ENCRYPTED_DATA_CONTENT_TYPEOID_FRIENDLY_NAMEOID_LOCAL_KEY_IDOID_CERT_TYPE_X509_CERTIFICATEOID_KEY_BAG,OID_PKCS8_SHROUDED_KEY_BAG, etc.
ITERATIONS: The number of iterations (2048) used in password-based key derivation functions (PBKDF).
Utility Functions
sha1(bytes: &[u8]) -> Vec<u8>
Computes the SHA-1 digest of the input byte slice.
Parameters:
bytes- input data to hash.Returns: SHA-1 hash as a vector of bytes.
rand() -> Option<[u8; 8]>
Generates 8 random bytes using the system's random number generator.
Returns:
Some([u8;8])if successful, else None.
bmp_string(s: &str) -> Vec<u8>
Encodes a Rust UTF-8 string into a BMPString (UTF-16BE with trailing null terminator) format, as required by PKCS#12 attributes.
Parameters:
s- input UTF-8 string.Returns: Vector of bytes in BMPString format.
Main Data Structures and Their Methods
EncryptedContentInfo
Represents the encrypted content info structure containing the encryption algorithm identifier and the encrypted content bytes.
Fields:
content_encryption_algorithm: AlgorithmIdentifierencrypted_content: Vec<u8>
Methods:
write(&self, w: DERWriter): Writes the ASN.1 DER encoding of the encrypted content info.from_safe_bags(safe_bags: &[SafeBag], password: &[u8]) -> Option<EncryptedContentInfo>: Encrypts a collection of safe bags using password-based encryption (PBE with SHA-1 and RC2-40-CBC) and returns anEncryptedContentInfoinstance.
EncryptedData
Wraps an EncryptedContentInfo instance.
Fields:
encrypted_content_info: EncryptedContentInfo
Methods:
write(&self, w: DERWriter): Encodes the encrypted data ASN.1 structure.from_safe_bags(safe_bags: &[SafeBag], password: &[u8]) -> Option<Self>: Creates anEncryptedDatainstance by encrypting the safe bags.
ContentInfo
Enum representing two content types in PKCS#12:
Data(Vec<u8>): Plain data bytes.EncryptedData(EncryptedData): Encrypted data structure.Methods:
write(&self, w: DERWriter): Writes the ASN.1 encoding of the content info depending on variant.
Pkcs12PbeParams
Parameters for PKCS#12 password-based encryption (PBE) algorithms.
Fields:
salt: Vec<u8>iterations: u64
Methods:
write(&self, w: DERWriter): Writes the ASN.1 structure encoding the salt and iterations.
AlgorithmIdentifier
Enum representing supported cryptographic algorithms:
Sha1PbeWithSHAAnd40BitRC2CBC(Pkcs12PbeParams)PbeWithSHAAnd3KeyTripleDESCBC(Pkcs12PbeParams)Methods:
write(&self, w: DERWriter): Writes the ASN.1 encoding of the algorithm identifier including parameters.
DigestInfo
Holds a digest algorithm and the computed digest bytes.
Fields:
digest_algorithm: AlgorithmIdentifierdigest: Vec<u8>
Methods:
write(&self, w: DERWriter): Writes ASN.1 encoding ofDigestInfo.
MacData
Holds MAC-related data for PKCS#12 integrity checking.
Fields:
mac: DigestInfosalt: Vec<u8>iterations: u32
Methods:
write(&self, w: DERWriter): Writes ASN.1 encoding of the MAC data.new(data: &[u8], password: &[u8]) -> MacData: Creates a MAC over the given data using HMAC-SHA1 with a random salt and the provided password.
Pfx
Represents the top-level PKCS#12 PFX structure.
Fields:
version: u8(typically 3)auth_safe: ContentInfomac_data: Option<MacData>
Methods:
new(cert_der: &[u8], key_der: &[u8], ca_der: Option<&[u8]>, password: &str, name: &str) -> Option<Pfx>: Creates a PFX structure with optional CA certificates.new_with_cas(cert_der: &[u8], key_der: &[u8], ca_der_list: &[&[u8]], password: &str, name: &str) -> Option<Pfx>: More general constructor supporting multiple CA certs.write(&self, w: DERWriter): ASN.1 encoding of PFX.to_der(&self) -> Vec<u8>: Returns DER-encoded PFX bytes.
Usage Example:
let pfx = Pfx::new(cert_der_bytes, key_der_bytes, Some(ca_der_bytes), "password", "friendly_name");
if let Some(pfx) = pfx {
let der_data = pfx.to_der();
// der_data contains the PKCS#12 file bytes
}
CertBag
Represents a certificate bag in PKCS#12.
Variants:
X509(Vec<u8>): Raw DER-encoded X.509 certificate.
Methods:
write(&self, w: DERWriter): Writes ASN.1 encoding of the cert bag.
EncryptedPrivateKeyInfo
Represents an encrypted private key structure.
Fields:
encryption_algorithm: AlgorithmIdentifierencrypted_data: Vec<u8>
Methods:
write(&self, w: DERWriter): ASN.1 encoding of encrypted private key info.
SafeBagKind
Enum representing the types of safe bags that can be stored inside PKCS#12:
Key(Vec<u8>): Plain private key bytes.Pkcs8ShroudedKey(EncryptedPrivateKeyInfo): Encrypted private key.Cert(CertBag): Certificate bag.Methods:
write(&self, w: DERWriter): ASN.1 encoding of the safe bag content.oid(&self) -> ObjectIdentifier: Returns the OID corresponding to the safe bag type.
PKCS12Attribute
Attributes associated with safe bags.
Variants:
FriendlyName(String)LocalKeyId(Vec<u8>)
Methods:
write(&self, w: DERWriter): Writes ASN.1 encoding of the attribute.
SafeBag
Encapsulates a safe bag and its associated attributes.
Fields:
bag: SafeBagKindattributes: Vec<PKCS12Attribute>
Methods:
write(&self, w: DERWriter): Writes ASN.1 encoding of the full safe bag including attributes.
Cryptographic Functions
Password-Based Key Derivation and Encryption
pbepkcs12sha1core(d: &[u8], i: &[u8], a: &mut Vec<u8>, iterations: u64) -> Vec<u8>
Core SHA-1 based derivation loop used in PKCS#12 key derivation.pbepkcs12sha1(pass: &[u8], salt: &[u8], iterations: u64, id: u8, size: u64) -> Vec<u8>
Implements the PKCS#12 key derivation function (KDF) with parameters:pass: password bytessalt: salt bytesiterations: iteration countid: purpose identifier (1 for key, 2 for IV, 3 for MAC)size: desired output size in bytes
pbe_with_sha1_and40_bit_rc2_cbc_encrypt(data, password, salt, iterations)
Encrypts data using PBE with SHA-1 and 40-bit RC2 in CBC mode.pbe_with_sha_and3_key_triple_des_cbc_encrypt(data, password, salt, iterations)
Encrypts data using PBE with SHA-1 and Triple DES (3-key) in CBC mode.
Interaction with Other System Components
Uses
yasnacrate for ASN.1 DER encoding and decoding.Uses
getrandomcrate for secure random number generation.Uses cryptographic crates such as
sha1,hmac,cbc,rc2, anddesfor hash functions, message authentication, and symmetric encryption.Constructs PKCS#12 PFX files following the standard ASN.1 structure, enabling interoperability with other systems using PKCS#12.
Implementation Details and Algorithms
The file implements PKCS#12 password-based encryption using SHA-1 and two symmetric ciphers: RC2 with 40-bit keys and Triple-DES with 3 keys.
Key derivation follows the PKCS#12 specification, deriving keys, IVs, and MAC keys separately using the identifier parameter.
Safe bags encapsulate keys, certificates, and encrypted private keys with their attributes.
The
Pfx::new_with_cas()method demonstrates the packaging of keys and certificates into safe bags, optionally encrypting private keys and certificates based on the presence of a password.MAC data is generated over the entire contents to ensure integrity.
The encoding methods use
yasna's DERWriter to produce ASN.1 DER-encoded output suitable for PKCS#12 files.The BMPString encoding of friendly names ensures compliance with the PKCS#12 attribute formatting.
Visual Diagram: Structure of Main Types and Their Relationships
classDiagram
class Pfx {
+version: u8
+auth_safe: ContentInfo
+mac_data: Option<MacData>
+new()
+write()
+to_der()
}
class ContentInfo {
<<enum>>
+Data(Vec<u8>)
+EncryptedData(EncryptedData)
+write()
}
class EncryptedData {
+encrypted_content_info: EncryptedContentInfo
+write()
+from_safe_bags()
}
class EncryptedContentInfo {
+content_encryption_algorithm: AlgorithmIdentifier
+encrypted_content: Vec<u8>
+write()
+from_safe_bags()
}
class SafeBag {
+bag: SafeBagKind
+attributes: Vec<PKCS12Attribute>
+write()
}
class SafeBagKind {
<<enum>>
+Key(Vec<u8>)
+Pkcs8ShroudedKey(EncryptedPrivateKeyInfo)
+Cert(CertBag)
+write()
+oid()
}
class PKCS12Attribute {
<<enum>>
+FriendlyName(String)
+LocalKeyId(Vec<u8>)
+write()
}
class AlgorithmIdentifier {
<<enum>>
+Sha1
+PbeWithSHAAnd40BitRC2CBC(Pkcs12PbeParams)
+PbeWithSHAAnd3KeyTripleDESCBC(Pkcs12PbeParams)
+write()
}
class Pkcs12PbeParams {
+salt: Vec<u8>
+iterations: u64
+write()
}
class MacData {
+mac: DigestInfo
+salt: Vec<u8>
+iterations: u32
+write()
+new()
}
class DigestInfo {
+digest_algorithm: AlgorithmIdentifier
+digest: Vec<u8>
+write()
}
class CertBag {
<<enum>>
+X509(Vec<u8>)
+write()
}
class EncryptedPrivateKeyInfo {
+encryption_algorithm: AlgorithmIdentifier
+encrypted_data: Vec<u8>
+write()
}
Pfx --> ContentInfo
ContentInfo --> EncryptedData
EncryptedData --> EncryptedContentInfo
EncryptedContentInfo --> AlgorithmIdentifier
SafeBag --> SafeBagKind
SafeBag --> PKCS12Attribute
SafeBagKind --> EncryptedPrivateKeyInfo
SafeBagKind --> CertBag
PKCS12Attribute --> AlgorithmIdentifier
MacData --> DigestInfo
DigestInfo --> AlgorithmIdentifier
EncryptedPrivateKeyInfo --> AlgorithmIdentifier
Pkcs12PbeParams ..> AlgorithmIdentifier : used in
Important Notes
Passwords are encoded as BMPStrings before use in cryptographic operations.
Encryption and MAC generation are performed according to PKCS#12 v1.0 standards.
The file does not include explicit parsing/decoding of PKCS#12 structures, focusing on construction and encoding.
Interaction with external cryptographic libraries is encapsulated in helper functions for encryption and key derivation.
This file is central to the creation and encoding of PKCS#12 bundles, managing the secure packaging of private key material with certificates and associated metadata. For related cryptographic topics, see Password-Based Encryption, ASN.1 Encoding, and PKCS#12 Specification.