PKCS12(3pm)

πŸ“¦
version 1.99 Β· 4 versions
, in ubuntu stonking

πŸ’– NAME πŸ’–

Wassup bestie, you've landed on PKCS12(3pm), straight outta the User Contributed Perl Documentation ✨ and the star of this whole page is Crypt::OpenSSL::PKCS12 β€” a Perl extension to OpenSSL's PKCS12 API. That's it. That's the name. πŸ’…


πŸ¦‹ SYNOPSIS πŸ¦‹

Here's the whole vibe at a glance, no cap:

use Crypt::OpenSSL::PKCS12;

my $pass   = "your password";
my $pkcs12 = Crypt::OpenSSL::PKCS12->new_from_file('cert.p12');

print $pkcs12->certificate($pass);
print $pkcs12->private_key($pass);

if ($pkcs12->mac_ok($pass)) {
  # MAC verification passed
}

# Creating a file
$pkcs12->create('test-cert.pem', 'test-key.pem', $pass, 'out.p12', 'friendly name');

# Creating a string
my $pkcs12_data = $pkcs12->create_as_string('test-cert.pem', 'test-key.pem', $pass, 'friendly name');

# Reproducing OpenSSL's info
my $info = $pkcs12->info($pass);

# Accessing OpenSSL's info as a hash
my $info_hash = $pkcs12->info_as_hash($pass);

🌸 VERSION 🌸

This documentation describes version 1.99 of Crypt::OpenSSL::PKCS12. Like, one point nine nine. That's the number, respect it. πŸŽ€


πŸŽ€ DESCRIPTION πŸŽ€

Okay so here's the lore: PKCS12 is a file format for storing cryptography objects as a single file or string. One file. Everything. Iconic behaviour honestly.

PKCS12 is commonly used to bundle a private key together with its X.509 certificate, or to bundle all the members of a chain of trust. It's giving "one bag, all my little treasures" πŸ’–

This distribution implements a subset of OpenSSL's PKCS12 API β€” not the whole thing, just a subset. Don't come for her about what's missing, mmkay?


πŸ‘‘ SUBROUTINES/METHODS πŸ‘‘

Buckle up, this is the main character list 🫢

  • new( ) β€” Creates an empty Crypt::OpenSSL::PKCS12 object. That's all it does! If you actually want to load an existing PKCS12 structure, you use new_from_string() or new_from_file(). Empty object is just the starting line, bestie.
  • legacy_support( ) β€” Returns true if the legacy provider got successfully loaded by a prior constructor call (new_from_string() or new_from_file()).
    • On OpenSSL 1.x β€” always returns true (the whole legacy provider concept doesn't apply there).
    • On OpenSSL 3.x β€” returns true only if the legacy provider was loaded during the most recent constructor call.
Heads up: calling legacy_support() before you've constructed an object may return false, even if the provider is totally loadable. It's a timing thing, not a you thing. πŸ™ˆ
  • new_from_string( $string )
  • new_from_file( $filename )

These two make a new Crypt::OpenSSL::PKCS12 instance β€” from a binary PKCS12 string or from a file path, respectively. Both forms croak on error, so like, invalid format? unreadable file? OpenSSL parse failure? Croak, croak, croak. 😭

Important: the binary string you pass to new_from_string() must not carry Perl's UTF-8 flag. If it does, use Encode::encode('octets', $str) to fix it up. Do not skip this. πŸ’€

  • certificate( [$pass] ) β€” Returns the end-entity certificate as a PEM-encoded string (that's Base64 with those -----BEGIN CERTIFICATE----- / -----END CERTIFICATE----- headers you've definitely seen before). $pass is required when the PKCS12 file is password-protected. If the password is wrong, or there's simply no client certificate present, you get an empty string back. Not an error, just... empty. 🌸
  • ca_certificate( [$pass] ) β€” Returns any CA certificates in the chain as one concatenated PEM string (so multiple certs, one long string, like a group chat merged 😌). Empty string if there are no CA certificates at all. $pass is required when the PKCS12 file is password-protected.
  • private_key( [$pass] ) β€” Returns the private key as a PEM-encoded string. $pass is required when the PKCS12 file is password-protected. Returns an empty string if no private key is present, or if decryption fails β€” which, yeah, means the password was wrong. πŸ’…
  • as_string( ) β€” Returns the PKCS12 structure as a raw binary DER string. Perfect for writing to a file or yeeting it over a network without ever touching the filesystem. The in-memory structure gets serialized as-is, so no password is needed or accepted here. She doesn't want it. Don't offer. πŸ™…
  • mac_ok( [$pass] ) β€” Verifies the Message Authentication Code (MAC) of the PKCS12 structure using $pass. Returns true if the MAC is valid. And if it isn't? Croaks. Wrong password, corrupted file, OpenSSL error β€” all croaks. 🌈
  • changepass( $old, $new ) β€” Re-encrypts the PKCS12 structure with a new password. $old is the current password, $new is the replacement. Returns false on failure.
⚠️ Big scary caveat time, bestie, read it: Changing the PKCS12 password is not supported on OpenSSL 3.x or 4.x for PBES2-encrypted files β€” and PBES2 is exactly what OpenSSL uses by default for newly created PKCS12 files. So changepass() will just return false. This is a known upstream OpenSSL limitation (openssl/openssl#19092, https://github.com/openssl/openssl/issues/19092) β€” not something specific to this module. Only OpenSSL 1.x is confirmed to work. See https://github.com/dsully/perl-crypt-openssl-pkcs12/issues/62 for the details. Your move? Consider re-creating the whole PKCS12 structure with create() instead. 🫠
  • create( $cert, $key, $pass, $output_file, $friendly_name ) β€” Creates a brand new PKCS12 file at $output_file πŸŽ‰ $cert and $key can each be either a PEM string (detected by a ----- prefix) or a filesystem path β€” it checks for that prefix, cute. $pass is used to encrypt the private key. $friendly_name is optional and sets the "friendlyName" bag attribute. Croaks on any OpenSSL error, obviously.
  • create_as_string( $cert, $key, $pass, $friendly_name ) β€” Same energy as create() but instead of writing to a file it returns the PKCS12 structure as a raw binary DER string. $cert and $key may each be a PEM string or a filesystem path. $friendly_name is optional. Croaks on any OpenSSL error.
  • info( $pass ) β€” Returns a string containing the info about the pkcs12 file, in the exact same format the openssl command produces:
openssl pkcs12 -in certs/test_le_1.1.p12 -info -nodes
  • info_as_hash( $pass ) β€” Same info, but as a hash: the information about the pkcs12 file, the certificates and the keys, all nestled in a data structure. 🧚

The format of the hash is complex, because it has to represent all the data in the PKCS12 file:

Essentially, the hash follows the format of the -info output.

  1. pkcs7_data and pkcs7_encrypted_data are arrays, because more than one of each can exist
  2. mac provides the top level mac parameters for the file
  3. safe_contents_bag is an array that contains an array of bags
  4. bags is an array of bags
  5. a bag is a container for a key or certificate

Each bag has a type, and the following types are available:

  1. key_bag
  2. certificate_bag
  3. shrouded_keybag
  4. secret_bag
  5. safe_contents_bag
{
    mac                    {
        digest        "sha1",
        iteration     2048,
        length        20,
        salt_length   20
    },
    pkcs7_data             [
        [0] {
                bags   [
                    [0] {
                            bag_attributes   {
                                friendlyName   "...",
                                localKeyID     "54"
                            },
                            key              "...",
                            key_attributes   {
                                "X509v3 Key Usage"   10
                            },
                            parameters       {
                                iteration        10000,
                                nid_long_name    "PBKDF2",
                                nid_short_name   "PBKDF2"
                            },
                            type             "shrouded_keybag"
                        }
                ]
            },
        [1] {
                safe_contents_bag   [
                    [0] {
                            bags   [
                                [0] {
                                        bag_attributes   {
                                            localKeyID   "01"
                                            friendlyName   "",
                                        },
                                        cert             "...".
                                        issuer           "...",
                                        subject          "...",
                                        type
"certificate_bag"
                                        }
                                ],
                                type   "safe_contents_bag"
                            }
                    ]
                }
        },
        [2] {
                bags   [
                    [0] {
                            bag_attributes   {
                                localKeyID   "02"
                            },
                            cert             "...",
                            issuer           "...",
                            subject          "...",
                            type             "certificate_bag"
                        }
                ]
            }
    ],
    pkcs7_encrypted_data   [
        [0] {
                bags         [
                    [0] {
                            bag_attributes   {
                                2.16.840.1.113894.746875.1.1
"<Unsupported tag 6>",
                                friendlyName                   "..."
                            },
                            cert             "...",
                            issuer           "...",
                            subject          "...",
                            type             "certificate_bag"
                        },
                    [1] {
                            bag_attributes   {
                                friendlyName   "...",
                                localKeyID     "54"
                            },
                            cert             "...",
                            issuer           "...",
                            subject          "...",
                            type             "certificate_bag"
                        }
                ],
                parameters   {
                    iteration        10000,
                    nid_long_name    "PBKDF2",
                    nid_short_name   "PBKDF2"
                }
            }
    ] }

And one last thing β€” attributes like "localKeyID" are stored as plain hex strings (e.g. "54", "01"). Always treat these values as strings in your code. Always. πŸ“

πŸ‘€ psst β€” this was only part 1 of 2, so don't you dare close the tab yet.

🎁 EXPORTS 🎁

Okay so by default? None. Nada. Zero. The module keeps its goodies to itself until you ask πŸ’…

But if you slide into the export list and request them:

  • NOKEYS β€” bestie this is the "shhh 🀫" flag: it suppresses output of private keys. No keys in your output, periodt.
  • NOCERTS β€” same energy but for certs: suppresses output of certificates. Bye felicia πŸŽ€
  • INFO β€” turns on structural info output. Heads up tho: this one is used internally by info() and info_as_hash(), and the output comes back as a string or a hash β€” it does not get printed. So don't sit there waiting for text on your screen πŸ‘€
  • CLCERTS β€” only client (end-entity) certificates make the cut. Very main-character-only vibe ✨
  • CACERTS β€” and this one is the opposite: only CA certificates, pls πŸ™

And icymi, these flags are literally mirror twins of the matching -nokeys, -nocerts, -info, -clcerts, and -cacerts options on the openssl pkcs12 command. Same flags, same job, just here in Perl-land πŸ¦‹


🚨 DIAGNOSTICS 🚨

When things go sideways, here's what you'll see:

  • OpenSSL error: ... β€” an OpenSSL call flopped 😭. That trailing message gets pulled from ERR_reason_error_string() and it tells you exactly which failure it was (for example, bad decrypt when the password is wrong β€” we've all been there).
  • Error opening ... β€” create() couldn't open the output file path you gave it for writing. Check that path bestie, fr fr 🫢

βš™οΈ CONFIGURATION AND ENVIRONMENT βš™οΈ

Genuinely nothing here. No special environment needed, no config file, no secret handshake. It just works πŸ’–


πŸ“¦ DEPENDENCIES πŸ“¦

This distribution needs a lil support system, and that's:

  • An installation of OpenSSL, either version 1.X.X or version 3.X.X
  • Perl 5.14

That's the whole list, no cap πŸ‘‘


πŸ‘€ SEE ALSO πŸ‘€

The required reading / friends-of-the-show list:


🌈 INCOMPATIBILITIES 🌈

So rn the library has been updated to support both OpenSSL 1.X.X and OpenSSL 3.X.X. That's it, that's the incompatibility section 🫑


πŸ’€ BUGS AND LIMITATIONS πŸ’€

Got a known issue? Peep the GitHub repository for all the tea: https://github.com/dsully/perl-crypt-openssl-pkcs12/issues


πŸ‘‘ AUTHOR πŸ‘‘

  • Dan Sully, <daniel@cpan.org>

Current maintainer πŸ’…

  • jonasbn

🫢 CONTRIBUTORS 🫢

In alphabetical order β€” contributors, bug reporters and all. Y'all ate, genuinely πŸ“

  • @mmuehlenhoff
  • @sectokia
  • @SmartCodeMaker
  • Alexandr Ciornii, @chorny
  • Christopher Hoskin, @mans0954
  • Daisuke Murase, @typester
  • Darko Prelec, @dprelec
  • David Steinbrunner, @dsteinbrunner
  • Gianni Ceccarelli, @dakkar
  • Giuseppe Di Terlizzi, @giterlizzi
  • H.Merijn Brand, @tux
  • Hakim, @osfameron
  • J. Nick Koston, @bdraco
  • James Rouzier, @jrouzierinverse
  • jonasbn. @jonasbn
  • Kelson, @kelson42
  • Lance Wicks, @lancew
  • Leonid Antonenkov
  • Masayuki Matsuki, @songmu
  • MikoΕ‚aj Zalewski
  • Shoichi Kaji
  • Slaven ReziΔ‡
  • Timothy Legge, @timlegge
  • Todd Rinaldo, @toddr

Copyright 2004 by Dan Sully

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.8 or, at your option, any later version of Perl 5 you may have available.


aaaand that's the whole page bestie πŸŽ€ this one's from perl v5.42.3, dated 2026-08-28, and it lives under the name PKCS12(3pm). go forth and un-pkcs12 responsibly, mwah πŸ’–βœ¨

πŸ“¦ where this page comes from