How to Generate PKCS12 PFX Files with mkcert for Legacy Applications

Use the -p12 flag when running mkcert to output a PKCS#12 archive instead of separate PEM files, then rename the .p12 extension to .pfx for compatibility with Windows and Java applications.

mkcert, maintained by FiloSottile, is a zero-configuration tool for creating locally-trusted development certificates. While it defaults to outputting separate certificate and key files in PEM format, you can generate PKCS12 PFX files with mkcert to satisfy legacy enterprise applications that require binary certificate containers bundling the private key, leaf certificate, and CA chain into a single file.

Why Legacy Systems Require PKCS12 (PFX) Format

Many enterprise platforms cannot consume raw PEM-encoded certificates and instead mandate the PKCS#12 standard (often stored with a .pfx extension on Windows).

Windows Certificate Stores and IIS

Legacy Windows services such as Internet Information Services (IIS) and older .NET Framework applications rely on the Windows CryptoAPI, which only imports certificates through .pfx or .p12 files into the system certificate store.

Java Keystores and Keytool

Java applications running on Tomcat, Jetty, or Spring Boot typically use the keytool utility to manage keystores. The keytool -importkeystore command can consume a PKCS#12 archive directly to populate a JKS or PKCS12 keystore, making the PFX format essential for Java deployments.

Mobile Development SDKs

Certain iOS and Android build pipelines require a single PFX bundle for code-signing or TLS client authentication during development, as they cannot easily reference separate key and certificate files from the filesystem.

How mkcert Implements PKCS12 Generation

The implementation resides in cert.go, where mkcert handles the -p12 flag and converts the generated PEM material into a binary PKCS#12 archive using Go’s crypto/x509 and the software.sslmate.com/src/go-pkcs12 library.

The -p12 Flag in cert.go

The command-line flag is defined around lines 70–78 of cert.go. When present, it sets an internal boolean that triggers the PKCS#12 export path instead of the default PEM writer.

// Simplified representation from cert.go
p12Flag := flag.Bool("p12", false, "Generate a PKCS#12 file instead of separate PEM files")

The writePKCS12 Function

The actual serialization logic lives in the writePKCS12 helper near lines 220–240 of cert.go. This function bundles the leaf certificate, private key, and any intermediate CA certificates into a single encrypted container.

// Conceptual flow from cert.go#L220-L240
func (m *mkcert) writePKCS12(cert *x509.Certificate, key crypto.PrivateKey, filename string) {
    // Uses software.sslmate.com/src/go-pkcs12 to encode
    p12Data, err := pkcs12.Encode(rand.Reader, key, cert, m.caCert, "")
    // Writes to <filename>.p12
}

Default Password Behavior

By default, mkcert generates unencrypted PKCS#12 files (empty password). This simplifies development workflows but may require post-processing with OpenSSL for environments that mandate password protection.

Step-by-Step: Generate PKCS12 PFX Files with mkcert

Follow these steps to create a locally-trusted PFX archive suitable for IIS, Java, or other legacy platforms.

Install mkcert and Initialize the Local CA

First, install mkcert and create a local certificate authority trusted by your system.


# macOS

brew install mkcert
mkcert -install

# Linux (download latest release)

wget https://github.com/FiloSottile/mkcert/releases/download/v1.4.4/mkcert-v1.4.4-linux-amd64 -O mkcert
chmod +x mkcert
sudo mv mkcert /usr/local/bin/
mkcert -install

Create the PKCS12 Archive

Use the -p12 flag to generate the binary archive. You can specify multiple Subject Alternative Names (SANs) in a single command.

mkcert -p12 "myapp.local" "localhost" "127.0.0.1" "::1"

This creates myapp.local.p12 containing the private key, leaf certificate, and CA chain.

Rename to .pfx Extension

Windows and some Java tools expect the .pfx extension. Simply rename the file:

mv myapp.local.p12 myapp.local.pfx

Add Password Protection with OpenSSL

Since mkcert outputs unencrypted PKCS#12 files by default, use OpenSSL to add a password for environments requiring encryption.

openssl pkcs12 -in myapp.local.pfx -export -out myapp.local-secure.pfx -passout pass:YourSecretPassword

The -export flag ensures the output is a new PKCS#12 archive with the specified password.

Importing PFX Files into Target Systems

Once you generate the PFX file, import it into your legacy application or system store.

Windows IIS Import

  1. Open the Certificate Manager (certmgr.msc) or IIS Manager.
  2. Navigate to Personal > Certificates.
  3. Right-click, select All Tasks > Import.
  4. Browse to your .pfx file and complete the wizard. If prompted for a password, leave it blank (for mkcert defaults) or enter the password you set with OpenSSL.

Java Keytool Import

Import the PFX into a Java KeyStore (JKS) or PKCS12 keystore for Tomcat or Spring Boot:

keytool -importkeystore \
  -srckeystore myapp.local.pfx \
  -srcstoretype PKCS12 \
  -srcstorepass YourSecretPassword \
  -destkeystore myapp.jks \
  -deststoretype JKS \
  -deststorepass changeit

If the mkcert PFX has no password, use -srcstorepass "" (empty string).

Advanced Configuration

Multiple Subject Alternative Names (SANs)

Legacy applications often bind to multiple hostnames or IPs. mkcert automatically embeds all arguments as Subject Alternative Names in the certificate.

mkcert -p12 "app.local" "*.app.local" "192.168.1.50" "localhost"

This generates a single PFX valid for all specified identities.

Certificate Renewal Workflow

When certificates expire, re-run the same command. mkcert maintains the same local CA in your system trust store, so the renewed certificate is automatically trusted without re-importing the CA.


# Re-generate with the same parameters

mkcert -p12 "myapp.local"

Replace the old PFX file in your application configuration.

Summary

  • mkcert generates locally-trusted development certificates and supports PKCS#12 output via the -p12 flag.
  • The implementation in cert.go (lines 70–78 and 220–240) uses the software.sslmate.com/src/go-pkcs12 library to bundle the private key, certificate, and CA chain.
  • By default, mkcert creates unencrypted .p12 files; use OpenSSL to add password protection for legacy systems requiring it.
  • Rename the output from .p12 to .pfx for compatibility with Windows IIS, Java keystores, and other enterprise platforms.
  • Include multiple Subject Alternative Names in a single command to support complex local development environments.

Frequently Asked Questions

What is the difference between .p12 and .pfx files?

There is no technical difference; both extensions refer to the PKCS#12 archive format. The .pfx extension originated with Microsoft and is standard on Windows platforms, while .p12 is more common on macOS and Linux systems. mkcert outputs .p12 by default, but you can safely rename the file to .pfx for Windows compatibility.

Does mkcert support password-protected PKCS12 files by default?

No. As implemented in cert.go, the writePKCS12 function creates unencrypted PKCS#12 archives with an empty password to streamline development workflows. If your legacy application requires a password, you must post-process the file using OpenSSL with the -export and -passout flags to add encryption.

Can I use mkcert-generated PFX files in production?

No. mkcert is explicitly designed for local development only. It creates certificates signed by a locally-installed CA that is not publicly trusted. While the PKCS#12 format itself is production-ready, the trust chain is valid only on your development machine. For production environments, use certificates issued by a public CA or your organization's internal PKI.

How do I import a mkcert PFX into a Java keystore?

Use the keytool utility bundled with the JDK. Since mkcert PFX files typically have no password, specify an empty source store password. Run: keytool -importkeystore -srckeystore myapp.local.pfx -srcstoretype PKCS12 -srcstorepass "" -destkeystore myapp.jks -deststoretype JKS -deststorepass changeit. This converts the PKCS#12 archive into a Java KeyStore (JKS) format suitable for Tomcat or Spring Boot applications.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →