Botan 3.13.0
Crypto and TLS for C&
Botan::PKCS12 Class Referencefinal

#include <pkcs12.h>

Public Member Functions

void add_certificate (X509_Certificate cert)
void add_key (std::shared_ptr< Private_Key > key)
 Add a private key. PKCS#12 supports multiple keys per file.
std::vector< X509_Certificateca_certificates () const
const std::vector< X509_Certificate > & certificates () const
void clear_friendly_name ()
 Clear the friendly-name attribute.
void clear_local_key_id ()
 Clear the localKeyId attribute.
std::optional< X509_Certificateend_entity_certificate () const
std::vector< uint8_t > export_to (const PKCS12_Export_Options &options, RandomNumberGenerator &rng) const
const std::optional< std::string > & friendly_name () const
const std::optional< std::vector< uint8_t > > & local_key_id () const
 PKCS12 ()=default
 Construct an empty bundle.
 PKCS12 (std::span< const uint8_t > data, std::string_view password)
const std::vector< std::shared_ptr< Private_Key > > & private_keys () const
void set_friendly_name (std::string name)
 Set (or replace) the friendly-name attribute.
void set_local_key_id (std::vector< uint8_t > id)
 Set (or replace) the localKeyId attribute.
const std::vector< OID > & unknown_bag_types () const

Detailed Description

PKCS#12/PFX bundle: parsed contents, mutable container, and exporter.

PKCS#12 is a file format for storing cryptographic objects (private keys and X.509 certificates) together, typically protected by a password.

The class can be used both to inspect an existing PFX and to build a new one. Construction from bytes parses an existing file; the default constructor produces an empty bundle that the caller populates with mutators (add_key, add_certificate, ...) before calling export_to to serialize.

// Parse
Botan::PKCS12 p12(pfx_bytes, "password");
if(!p12.private_keys().empty()) {
const auto& key = p12.private_keys().front();
// ...
}
if(auto ee = p12.end_entity_certificate()) {
// ...
}
// Build
out.set_friendly_name("My Bundle");
out.add_key(my_key);
out.add_certificate(my_cert);
for(const auto& ca : ca_chain) {
out.add_certificate(ca);
}
const auto blob = out.export_to(
static PKCS12_Export_Options modern(std::string_view password, std::optional< std::string > friendly_name={})
Definition pkcs12.cpp:401
std::vector< uint8_t > export_to(const PKCS12_Export_Options &options, RandomNumberGenerator &rng) const
Definition pkcs12.cpp:682
void add_certificate(X509_Certificate cert)
Definition pkcs12.cpp:662
void set_friendly_name(std::string name)
Set (or replace) the friendly-name attribute.
Definition pkcs12.cpp:666
void add_key(std::shared_ptr< Private_Key > key)
Add a private key. PKCS#12 supports multiple keys per file.
Definition pkcs12.cpp:655

Definition at line 146 of file pkcs12.h.

Constructor & Destructor Documentation

◆ PKCS12() [1/2]

Botan::PKCS12::PKCS12 ( )
default

Construct an empty bundle.

References PKCS12().

Referenced by PKCS12().

◆ PKCS12() [2/2]

Botan::PKCS12::PKCS12 ( std::span< const uint8_t > data,
std::string_view password )

Parse a PKCS#12/PFX file.

Parameters
datathe PFX file contents
passwordthe password to decrypt the file
Exceptions
Decoding_Errorif parsing fails
Invalid_Authentication_Tagif MAC verification fails

Definition at line 449 of file pkcs12.cpp.

449 {
450 std::vector<ParsedCert> cert_entries;
451 std::vector<ParsedKey> key_entries;
452
453 BER_Decoder pfx(data);
454 BER_Decoder pfx_seq = pfx.start_sequence();
455
456 size_t version = 0;
457 pfx_seq.decode(version);
458 if(version != 3) {
459 throw Decoding_Error(fmt("Unsupported PKCS#12 version: {}", version));
460 }
461
462 OID auth_safe_type;
463 std::vector<uint8_t> auth_safe_content;
464
465 BER_Decoder auth_safe_info = pfx_seq.start_sequence();
466 auth_safe_info.decode(auth_safe_type);
467
468 const OID pkcs7_data_oid = OID::from_string("PKCS7.Data");
469 if(auth_safe_type != pkcs7_data_oid) {
470 throw Decoding_Error("PKCS#12 authSafe must be of type Data");
471 }
472
473 BER_Decoder auth_safe_content_wrapper = auth_safe_info.start_context_specific(0);
474 auth_safe_content_wrapper.decode(auth_safe_content, ASN1_Type::OctetString);
475 auth_safe_content_wrapper.verify_end();
476 auth_safe_info.verify_end();
477
478 // Tracks whether MAC verification succeeded with OpenSSL's non-conforming
479 // empty-password encoding; if so, the same convention is used for any
480 // subsequent EncryptedData / PKCS8ShroudedKeyBag decryption.
481 bool openssl_empty_pwd_compat = false;
482
483 if(pfx_seq.more_items()) {
484 BER_Decoder mac_data = pfx_seq.start_sequence();
485
486 BER_Decoder digest_info = mac_data.start_sequence();
487 AlgorithmIdentifier digest_algo;
488 std::vector<uint8_t> mac_value;
489 digest_info.decode(digest_algo);
490 digest_info.decode(mac_value, ASN1_Type::OctetString);
491 digest_info.verify_end();
492
493 std::vector<uint8_t> mac_salt;
494 size_t iterations = 1;
495 mac_data.decode(mac_salt, ASN1_Type::OctetString);
496 if(mac_data.more_items()) {
497 mac_data.decode(iterations);
498 }
499 mac_data.verify_end();
500 if(iterations == 0 || iterations > PKCS12_MAX_ITERATIONS) {
501 throw Decoding_Error(fmt("PKCS#12 MAC has invalid iteration count: {}", iterations));
502 }
503
504 const std::string hash_name = resolve_mac_hash(digest_algo.oid());
505 // Try RFC 7292 password encoding first. If MAC verification fails and
506 // the password is empty, retry with OpenSSL's non-conforming empty
507 // encoding (some OpenSSL releases pass an empty byte string to the KDF
508 // instead of the RFC {0x00,0x00} form when the password is empty).
509 // Propagate the chosen convention to any subsequent PBE decryption.
510 try {
511 verify_mac(auth_safe_content, mac_value, mac_salt, iterations, hash_name, password, false);
512 } catch(const Invalid_Authentication_Tag&) {
513 if(!password.empty()) {
514 throw;
515 }
516 verify_mac(auth_safe_content, mac_value, mac_salt, iterations, hash_name, password, true);
517 openssl_empty_pwd_compat = true;
518 }
519 }
520
521 parse_authenticated_safe(
522 auth_safe_content, password, cert_entries, key_entries, m_unknown_bag_types, openssl_empty_pwd_compat);
523
524 // Move all parsed keys into storage.
525 m_private_keys.reserve(key_entries.size());
526 for(auto& ke : key_entries) {
527 m_private_keys.push_back(std::move(ke.key));
528 }
529
530 // Capture bundle-level attributes from the first key (if any), or from
531 // the end-entity certificate (if found below).
532 if(!key_entries.empty()) {
533 if(!key_entries.front().friendly_name.empty()) {
534 m_friendly_name = key_entries.front().friendly_name;
535 }
536 if(!key_entries.front().local_key_id.empty()) {
537 m_local_key_id = key_entries.front().local_key_id;
538 }
539 }
540
541 // Reorder certificates so the end-entity (cert matching the first key)
542 // comes first; rest follow in original order. Match prefers localKeyId,
543 // falls back to subjectPublicKeyInfo comparison.
544 std::optional<size_t> end_entity_idx;
545 if(!cert_entries.empty() && !m_private_keys.empty()) {
546 const auto& first_key = m_private_keys.front();
547 const auto& first_key_id = key_entries.empty() ? std::vector<uint8_t>{} : key_entries.front().local_key_id;
548
549 if(!first_key_id.empty()) {
550 for(size_t i = 0; i < cert_entries.size(); ++i) {
551 if(cert_entries[i].local_key_id == first_key_id) {
552 end_entity_idx = i;
553 break;
554 }
555 }
556 }
557 if(!end_entity_idx) {
558 const auto key_spki = first_key->subject_public_key();
559 for(size_t i = 0; i < cert_entries.size(); ++i) {
560 try {
561 if(cert_entries[i].cert.subject_public_key_info() == key_spki) {
562 end_entity_idx = i;
563 break;
564 }
565 } catch(const Decoding_Error&) {
566 // Certificate with unsupported key algorithm - skip
567 }
568 }
569 }
570 }
571
572 m_certificates.reserve(cert_entries.size());
573 if(end_entity_idx) {
574 m_certificates.push_back(std::move(cert_entries[*end_entity_idx].cert));
575 if(!m_friendly_name && !cert_entries[*end_entity_idx].friendly_name.empty()) {
576 m_friendly_name = cert_entries[*end_entity_idx].friendly_name;
577 }
578 if(!m_local_key_id && !cert_entries[*end_entity_idx].local_key_id.empty()) {
579 m_local_key_id = cert_entries[*end_entity_idx].local_key_id;
580 }
581 for(size_t i = 0; i < cert_entries.size(); ++i) {
582 if(i != *end_entity_idx) {
583 // Still surface any friendly name found on non-end-entity certs
584 // when the bundle doesn't have one yet (some producers attach the
585 // attribute to the CA bag instead of the end-entity bag).
586 if(!m_friendly_name && !cert_entries[i].friendly_name.empty()) {
587 m_friendly_name = cert_entries[i].friendly_name;
588 }
589 m_certificates.push_back(std::move(cert_entries[i].cert));
590 }
591 }
592 } else {
593 for(auto& ce : cert_entries) {
594 if(!m_friendly_name && !ce.friendly_name.empty()) {
595 m_friendly_name = ce.friendly_name;
596 }
597 m_certificates.push_back(std::move(ce.cert));
598 }
599 }
600
601 pfx_seq.verify_end();
602 pfx_seq.end_cons();
603 pfx.verify_end("PKCS#12: trailing data after PFX");
604}
static OID from_string(std::string_view str)
Definition asn1_oid.cpp:80
const std::optional< std::vector< uint8_t > > & local_key_id() const
Definition pkcs12.h:200
const std::optional< std::string > & friendly_name() const
Definition pkcs12.h:194
std::string fmt(std::string_view format, const T &... args)
Definition fmt.h:53
constexpr size_t PKCS12_MAX_ITERATIONS
Definition pkcs12_pbe.h:25

References Botan::BER_Decoder::decode(), Botan::BER_Decoder::end_cons(), Botan::fmt(), friendly_name(), Botan::OID::from_string(), local_key_id(), Botan::BER_Decoder::more_items(), Botan::OctetString, Botan::AlgorithmIdentifier::oid(), Botan::PKCS12_MAX_ITERATIONS, Botan::BER_Decoder::start_context_specific(), Botan::BER_Decoder::start_sequence(), and Botan::BER_Decoder::verify_end().

Member Function Documentation

◆ add_certificate()

void Botan::PKCS12::add_certificate ( X509_Certificate cert)

Add a certificate. End-entity vs CA is determined at export time by matching against stored keys.

Definition at line 662 of file pkcs12.cpp.

662 {
663 m_certificates.push_back(std::move(cert));
664}

◆ add_key()

void Botan::PKCS12::add_key ( std::shared_ptr< Private_Key > key)

Add a private key. PKCS#12 supports multiple keys per file.

Definition at line 655 of file pkcs12.cpp.

655 {
656 if(!key) {
657 throw Invalid_Argument("PKCS12::add_key: key must not be null");
658 }
659 m_private_keys.push_back(std::move(key));
660}

◆ ca_certificates()

std::vector< X509_Certificate > Botan::PKCS12::ca_certificates ( ) const

Convenience helper: every certificate except the one returned by end_entity_certificate. Returned in storage order.

Definition at line 606 of file pkcs12.cpp.

606 {
607 if(m_certificates.size() < 2) {
608 return {};
609 }
610 const auto ee = end_entity_certificate();
611 std::vector<X509_Certificate> result;
612 result.reserve(m_certificates.size() - 1);
613 if(ee) {
614 // Skip the first certificate matching the end-entity (only one, in case
615 // the bundle contains multiple certs signed for the same key, e.g. an
616 // old leaf still kept alongside a renewed one).
617 const auto ee_spki = ee->subject_public_key_info();
618 bool skipped = false;
619 for(const auto& c : m_certificates) {
620 if(!skipped && c.subject_public_key_info() == ee_spki) {
621 skipped = true;
622 continue;
623 }
624 result.push_back(c);
625 }
626 } else {
627 // No end-entity (e.g. key-less bundle): treat the first stored cert as
628 // the "primary" and surface the rest as CA / chain certs. This matches
629 // the storage order used by parsing.
630 for(size_t i = 1; i < m_certificates.size(); ++i) {
631 result.push_back(m_certificates[i]);
632 }
633 }
634 return result;
635}
std::optional< X509_Certificate > end_entity_certificate() const
Definition pkcs12.cpp:637

References end_entity_certificate().

◆ certificates()

const std::vector< X509_Certificate > & Botan::PKCS12::certificates ( ) const
inline

Certificates stored in the bundle, in the order they appear in the PFX or in insertion order. The end-entity certificate (if any) is not separated from CA/intermediate certificates at storage level; use end_entity_certificate to obtain it.

Definition at line 175 of file pkcs12.h.

175{ return m_certificates; }

◆ clear_friendly_name()

void Botan::PKCS12::clear_friendly_name ( )

Clear the friendly-name attribute.

Definition at line 670 of file pkcs12.cpp.

670 {
671 m_friendly_name.reset();
672}

◆ clear_local_key_id()

void Botan::PKCS12::clear_local_key_id ( )

Clear the localKeyId attribute.

Definition at line 678 of file pkcs12.cpp.

678 {
679 m_local_key_id.reset();
680}

◆ end_entity_certificate()

std::optional< X509_Certificate > Botan::PKCS12::end_entity_certificate ( ) const
Returns
the first certificate whose subjectPublicKeyInfo matches one of the stored private keys, or nullopt if none match (e.g. a certificate-only or key-only bundle).

Definition at line 637 of file pkcs12.cpp.

637 {
638 if(m_certificates.empty() || m_private_keys.empty()) {
639 return std::nullopt;
640 }
641 const auto& first_key = m_private_keys.front();
642 const auto key_spki = first_key->subject_public_key();
643 for(const auto& c : m_certificates) {
644 try {
645 if(c.subject_public_key_info() == key_spki) {
646 return c;
647 }
648 } catch(const Decoding_Error&) {
649 // Skip certificates with unsupported algorithms
650 }
651 }
652 return std::nullopt;
653}

Referenced by ca_certificates().

◆ export_to()

std::vector< uint8_t > Botan::PKCS12::export_to ( const PKCS12_Export_Options & options,
RandomNumberGenerator & rng ) const

Serialize the bundle as a PKCS#12/PFX file.

Parameters
optionsexport options (password, algorithms, ...).
Random Number GeneratorsRNG used to generate salts, IVs and (if requested) the localKeyId when none is set explicitly.
Exceptions
Invalid_Argumentif options is internally inconsistent (e.g. an unsupported algorithm is requested).
Invalid_Argumentif a stored private key does not match any stored certificate (this implementation requires the end-entity cert to be present when a key is exported).

Definition at line 682 of file pkcs12.cpp.

682 {
683 if(m_private_keys.empty() && m_certificates.empty()) {
684 throw Invalid_Argument("PKCS#12::export_to requires at least a key or certificate");
685 }
686
687 validate_options(options);
688
689 // Determine end-entity certificate(s). With a single key we pair it
690 // against a cert matching its SPKI; that pair gets the
691 // friendly_name/localKeyId from options or the bundle.
692 std::optional<size_t> end_entity_idx;
693 if(!m_private_keys.empty() && !m_certificates.empty()) {
694 const auto& first_key = m_private_keys.front();
695 const auto key_spki = first_key->subject_public_key();
696 for(size_t i = 0; i < m_certificates.size(); ++i) {
697 try {
698 if(m_certificates[i].subject_public_key_info() == key_spki) {
699 end_entity_idx = i;
700 break;
701 }
702 } catch(const Decoding_Error&) {
703 // skip
704 }
705 }
706 if(!end_entity_idx) {
707 throw Invalid_Argument("PKCS#12::export_to: private key does not match any certificate");
708 }
709 }
710
711 const OID cert_bag_oid = OID::from_string("PKCS12.CertBag");
712 const OID shrouded_key_oid = OID::from_string("PKCS12.PKCS8ShroudedKeyBag");
713 const OID x509_cert_oid = OID::from_string("PKCS9.X509Certificate");
714 const OID friendly_name_oid = OID::from_string("PKCS9.FriendlyName");
715 const OID local_key_id_oid = OID::from_string("PKCS9.LocalKeyId");
716 const OID pkcs7_data_oid = OID::from_string("PKCS7.Data");
717 const OID pkcs7_enc_data_oid = OID::from_string("PKCS7.EncryptedData");
718
719 // Pick the friendly-name and local-key-id used by attribute encoding.
720 // Options take precedence over the bundle-level fields.
721 const std::optional<std::string>& friendly_name =
722 options.friendly_name().has_value() ? options.friendly_name() : m_friendly_name;
723
724 std::vector<uint8_t> local_key_id;
725 if(m_local_key_id) {
726 local_key_id = *m_local_key_id;
727 } else if(end_entity_idx) {
728 local_key_id = m_certificates[*end_entity_idx].subject_public_key_bitstring_sha1();
729 } else if(!m_private_keys.empty()) {
730 // Key-only bundle: derive from SHA-1 of the public key bits (matching the
731 // convention used by X509_Certificate::subject_public_key_bitstring_sha1).
732 auto sha1 = HashFunction::create_or_throw("SHA-1");
733 const auto pub_bits = m_private_keys.front()->public_key_bits();
734 sha1->update(pub_bits);
735 local_key_id = unlock(sha1->final());
736 }
737
738 auto write_attributes = [&](DER_Encoder& enc) {
739 const bool has_fn = friendly_name.has_value() && !friendly_name->empty();
740 const bool has_id = !local_key_id.empty();
741 if(!has_fn && !has_id) {
742 return;
743 }
744 enc.start_set();
745 if(has_fn) {
746 enc.start_sequence();
747 enc.encode(friendly_name_oid);
748 enc.start_set();
749 encode_bmpstring(enc, *friendly_name);
750 enc.end_cons();
751 enc.end_cons();
752 }
753 if(has_id) {
754 enc.start_sequence();
755 enc.encode(local_key_id_oid);
756 enc.start_set();
758 enc.end_cons();
759 enc.end_cons();
760 }
761 enc.end_cons();
762 };
763
764 // CertBags
765 std::vector<uint8_t> cert_safe_contents;
766 if(!m_certificates.empty()) {
767 DER_Encoder cert_bags(cert_safe_contents);
768 cert_bags.start_sequence();
769
770 auto add_cert_bag = [&](const X509_Certificate& c, bool add_attrs) {
771 cert_bags.start_sequence();
772 cert_bags.encode(cert_bag_oid);
773
774 cert_bags.start_context_specific(0);
775 cert_bags.start_sequence();
776 cert_bags.encode(x509_cert_oid);
777 cert_bags.start_context_specific(0);
778 cert_bags.encode(c.BER_encode(), ASN1_Type::OctetString);
779 cert_bags.end_cons();
780 cert_bags.end_cons();
781 cert_bags.end_cons();
782
783 if(add_attrs) {
784 write_attributes(cert_bags);
785 }
786
787 cert_bags.end_cons();
788 };
789
790 // End-entity first (so the file is read in the typical order), then
791 // the rest in their stored order.
792 if(end_entity_idx) {
793 add_cert_bag(m_certificates[*end_entity_idx], true);
794 for(size_t i = 0; i < m_certificates.size(); ++i) {
795 if(i != *end_entity_idx) {
796 add_cert_bag(m_certificates[i], false);
797 }
798 }
799 } else {
800 for(const auto& c : m_certificates) {
801 add_cert_bag(c, false);
802 }
803 }
804
805 cert_bags.end_cons();
806 }
807
808 // Key SafeBag(s)
809 std::vector<uint8_t> key_safe_contents;
810 if(!m_private_keys.empty()) {
811 DER_Encoder key_bags(key_safe_contents);
812 key_bags.start_sequence();
813
814 for(size_t i = 0; i < m_private_keys.size(); ++i) {
815 const Private_Key& key = *m_private_keys[i];
816
817 key_bags.start_sequence();
818 key_bags.encode(shrouded_key_oid);
819
821 auto [enc_algo, enc_key] =
822 pkcs12_pbe_encrypt(pkcs8_key, options.password(), options.key_encryption_algo(), options.iterations(), rng);
823
824 key_bags.start_context_specific(0);
825 key_bags.start_sequence();
826 key_bags.encode(enc_algo);
827 key_bags.encode(enc_key, ASN1_Type::OctetString);
828 key_bags.end_cons();
829 key_bags.end_cons();
830
831 // Only the first key carries the bundle-level attributes (preserves
832 // the historical single-key behavior).
833 if(i == 0) {
834 write_attributes(key_bags);
835 }
836
837 key_bags.end_cons();
838 }
839 key_bags.end_cons();
840 }
841
842 // AuthenticatedSafe
843 std::vector<uint8_t> auth_safe_content;
844 DER_Encoder auth_safe(auth_safe_content);
845 auth_safe.start_sequence();
846
847 if(!cert_safe_contents.empty()) {
848 if(!options.cert_encryption_algo().empty()) {
849 auto [enc_algo, enc_data] = pkcs12_pbe_encrypt(
850 cert_safe_contents, options.password(), options.cert_encryption_algo(), options.iterations(), rng);
851
852 auth_safe.start_sequence();
853 auth_safe.encode(pkcs7_enc_data_oid);
854 auth_safe.start_context_specific(0);
855 auth_safe.start_sequence();
856 auth_safe.encode(size_t(0));
857 auth_safe.start_sequence();
858 auth_safe.encode(pkcs7_data_oid);
859 auth_safe.encode(enc_algo);
860 auth_safe.add_object(ASN1_Type(0), ASN1_Class::ContextSpecific, enc_data);
861 auth_safe.end_cons();
862 auth_safe.end_cons();
863 auth_safe.end_cons();
864 auth_safe.end_cons();
865 } else {
866 auth_safe.start_sequence();
867 auth_safe.encode(pkcs7_data_oid);
868 auth_safe.start_context_specific(0);
869 auth_safe.encode(cert_safe_contents, ASN1_Type::OctetString);
870 auth_safe.end_cons();
871 auth_safe.end_cons();
872 }
873 }
874
875 if(!key_safe_contents.empty()) {
876 auth_safe.start_sequence();
877 auth_safe.encode(pkcs7_data_oid);
878 auth_safe.start_context_specific(0);
879 auth_safe.encode(key_safe_contents, ASN1_Type::OctetString);
880 auth_safe.end_cons();
881 auth_safe.end_cons();
882 }
883
884 auth_safe.end_cons();
885
886 // PFX
887 std::vector<uint8_t> pfx_data;
888 DER_Encoder pfx(pfx_data);
889 pfx.start_sequence();
890 pfx.encode(size_t(3));
891
892 pfx.start_sequence();
893 pfx.encode(pkcs7_data_oid);
894 pfx.start_context_specific(0);
895 pfx.encode(auth_safe_content, ASN1_Type::OctetString);
896 pfx.end_cons();
897 pfx.end_cons();
898
899 if(options.include_mac()) {
900 const std::string& mac_hash = options.mac_digest();
901
902 auto hmac = MessageAuthenticationCode::create_or_throw(fmt("HMAC({})", mac_hash));
903
904 std::vector<uint8_t> mac_salt(hmac->output_length());
905 rng.randomize(mac_salt.data(), mac_salt.size());
906 const size_t mac_key_len = hmac->output_length();
907 secure_vector<uint8_t> mac_key(mac_key_len);
908 const PKCS12_KDF kdf(HashFunction::create_or_throw(mac_hash), 3, options.iterations());
909 kdf.derive_key(mac_key.data(),
910 mac_key_len,
911 options.password().data(),
912 options.password().size(),
913 mac_salt.data(),
914 mac_salt.size());
915
916 hmac->set_key(mac_key);
917 hmac->update(auth_safe_content);
918 const secure_vector<uint8_t> mac_value = hmac->final();
919
920 pfx.start_sequence();
921 pfx.start_sequence();
922 const auto param_encoding =
923 (mac_hash == "SHA-1") ? AlgorithmIdentifier::USE_NULL_PARAM : AlgorithmIdentifier::USE_EMPTY_PARAM;
924 pfx.encode(AlgorithmIdentifier(OID::from_string(mac_hash), param_encoding));
925 pfx.encode(mac_value, ASN1_Type::OctetString);
926 pfx.end_cons();
927 pfx.encode(mac_salt, ASN1_Type::OctetString);
928 if(options.iterations() != 1) {
929 pfx.encode(options.iterations());
930 }
931 pfx.end_cons();
932 }
933
934 pfx.end_cons();
935
936 return pfx_data;
937}
static std::unique_ptr< HashFunction > create_or_throw(std::string_view algo_spec, std::string_view provider="")
Definition hash.cpp:308
static std::unique_ptr< MessageAuthenticationCode > create_or_throw(std::string_view algo_spec, std::string_view provider="")
Definition mac.cpp:149
std::vector< uint8_t > BER_encode(const Private_Key &key, RandomNumberGenerator &rng, std::string_view pass, std::chrono::milliseconds msec, std::string_view pbe_algo)
Definition pkcs8.cpp:167
ASN1_Type
Definition asn1_obj.h:47
std::vector< T > unlock(const secure_vector< T > &in)
Definition secmem.h:155
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:128
std::pair< AlgorithmIdentifier, std::vector< uint8_t > > pkcs12_pbe_encrypt(std::span< const uint8_t > plaintext, std::string_view password, std::string_view algo, size_t iterations, RandomNumberGenerator &rng)

References Botan::DER_Encoder::add_object(), Botan::ASN1_Object::BER_encode(), Botan::PKCS8::BER_encode(), Botan::PKCS12_Export_Options::cert_encryption_algo(), Botan::ContextSpecific, Botan::HashFunction::create_or_throw(), Botan::MessageAuthenticationCode::create_or_throw(), Botan::PKCS12_KDF::derive_key(), Botan::DER_Encoder::encode(), Botan::DER_Encoder::end_cons(), Botan::fmt(), friendly_name(), Botan::PKCS12_Export_Options::friendly_name(), Botan::OID::from_string(), Botan::PKCS12_Export_Options::include_mac(), Botan::PKCS12_Export_Options::iterations(), Botan::PKCS12_Export_Options::key_encryption_algo(), local_key_id(), Botan::PKCS12_Export_Options::mac_digest(), Botan::OctetString, Botan::PKCS12_Export_Options::password(), Botan::pkcs12_pbe_encrypt(), Botan::RandomNumberGenerator::randomize(), Botan::DER_Encoder::start_context_specific(), Botan::DER_Encoder::start_sequence(), Botan::unlock(), Botan::AlgorithmIdentifier::USE_EMPTY_PARAM, and Botan::AlgorithmIdentifier::USE_NULL_PARAM.

◆ friendly_name()

const std::optional< std::string > & Botan::PKCS12::friendly_name ( ) const
inline

Friendly-name attribute attached to the private key / end-entity certificate bag, if present.

Definition at line 194 of file pkcs12.h.

194{ return m_friendly_name; }

Referenced by export_to(), and PKCS12().

◆ local_key_id()

const std::optional< std::vector< uint8_t > > & Botan::PKCS12::local_key_id ( ) const
inline

localKeyId attribute attached to the private key / end-entity certificate bag, if present.

Definition at line 200 of file pkcs12.h.

200{ return m_local_key_id; }

Referenced by export_to(), and PKCS12().

◆ private_keys()

const std::vector< std::shared_ptr< Private_Key > > & Botan::PKCS12::private_keys ( ) const
inline

Private keys stored in the bundle, in the order they appear in the PFX (for a parsed file) or in insertion order (for a built one). PKCS#12 allows multiple keys per file; parsing currently surfaces all KeyBag / PKCS8ShroudedKeyBag entries.

Definition at line 167 of file pkcs12.h.

167{ return m_private_keys; }

◆ set_friendly_name()

void Botan::PKCS12::set_friendly_name ( std::string name)

Set (or replace) the friendly-name attribute.

Definition at line 666 of file pkcs12.cpp.

666 {
667 m_friendly_name = std::move(name);
668}

◆ set_local_key_id()

void Botan::PKCS12::set_local_key_id ( std::vector< uint8_t > id)

Set (or replace) the localKeyId attribute.

Definition at line 674 of file pkcs12.cpp.

674 {
675 m_local_key_id = std::move(id);
676}

◆ unknown_bag_types()

const std::vector< OID > & Botan::PKCS12::unknown_bag_types ( ) const
inline

OIDs of bag types encountered during parsing but not handled by this implementation (e.g. SecretBag). Empty for normal files and for bundles constructed in-memory.

Definition at line 207 of file pkcs12.h.

207{ return m_unknown_bag_types; }

The documentation for this class was generated from the following files: