Documentation ¶
Overview ¶
Package pkcs12 implements some of PKCS#12 (also known as P12 or PFX). It is intended for decoding DER-encoded P12/PFX files for use with the crypto/tls package, and for encoding P12/PFX files for use by legacy applications which do not support newer formats. Since PKCS#12 uses weak encryption primitives, it SHOULD NOT be used for new applications.
Note that only DER-encoded PKCS#12 files are supported, even though PKCS#12 allows BER encoding. This is because encoding/asn1 only supports DER.
This package is forked from golang.org/x/crypto/pkcs12, which is frozen. The implementation is distilled from https://tools.ietf.org/html/rfc7292 and referenced documents.
Index ¶
- Constants
- Variables
- func Decode(pfxData []byte, password string) (privateKey interface{}, certificate *x509.Certificate, err error)
- func DecodeChain(pfxData []byte, password string) (privateKey interface{}, certificate *x509.Certificate, ...)
- func DecodeTrustStore(pfxData []byte, password string) (certs []*x509.Certificate, err error)
- func Encode(rand io.Reader, privateKey interface{}, certificate *x509.Certificate, ...) (pfxData []byte, err error)deprecated
- func EncodeTrustStore(rand io.Reader, certs []*x509.Certificate, password string) (pfxData []byte, err error)deprecated
- func EncodeTrustStoreEntries(rand io.Reader, entries []TrustStoreEntry, password string) (pfxData []byte, err error)deprecated
- func ToPEM(pfxData []byte, password string) ([]*pem.Block, error)deprecated
- type Encoder
- func (enc *Encoder) Encode(privateKey interface{}, certificate *x509.Certificate, ...) (pfxData []byte, err error)
- func (enc *Encoder) EncodeTrustStore(certs []*x509.Certificate, password string) (pfxData []byte, err error)
- func (enc *Encoder) EncodeTrustStoreEntries(entries []TrustStoreEntry, password string) (pfxData []byte, err error)
- func (enc *Encoder) EncodeWithAttributes(privateKey interface{}, certificate *x509.Certificate, ...) (pfxData []byte, err error)
- func (enc *Encoder) WithIterations(iterations int) *Encoder
- func (enc *Encoder) WithRand(rand io.Reader) *Encoder
- type NotImplementedError
- type TrustStoreEntry
Constants ¶
const DefaultPassword = "changeit"
DefaultPassword is the string "changeit", a commonly-used password for PKCS#12 files.
Variables ¶
var ( // ErrDecryption represents a failure to decrypt the input. ErrDecryption = errors.New("pkcs12: decryption error, incorrect padding") // ErrIncorrectPassword is returned when an incorrect password is detected. // Usually, P12/PFX data is signed to be able to verify the password. ErrIncorrectPassword = errors.New("pkcs12: decryption password incorrect") )
var Legacy = LegacyDES
Legacy encodes PKCS#12 files using weak, legacy parameters that work in a wide variety of software.
Currently, this encoder is the same as LegacyDES, but this may change in the future if another encoder is found to provide better compatibility.
Due to the weak encryption, it is STRONGLY RECOMMENDED that you use DefaultPassword when encoding PKCS#12 files using this encoder, and protect the PKCS#12 files using other means.
var LegacyDES = &Encoder{ macAlgorithm: oidSHA1, certAlgorithm: oidPBEWithSHAAnd3KeyTripleDESCBC, keyAlgorithm: oidPBEWithSHAAnd3KeyTripleDESCBC, macIterations: 1, encryptionIterations: 2048, saltLen: 8, rand: rand.Reader, }
LegacyDES encodes PKCS#12 files using weak algorithms that are supported by a wide variety of software. Certificates and keys are encrypted using PBE with 3DES using keys derived with 2048 iterations of HMAC-SHA-1. MACs use HMAC-SHA-1 with keys derived with 1 iteration of HMAC-SHA-1. These are the same parameters used by OpenSSL's -descert option. As of 2023, this encoder is likely to produce files that can be read by the most software.
Due to the weak encryption, it is STRONGLY RECOMMENDED that you use DefaultPassword when encoding PKCS#12 files using this encoder, and protect the PKCS#12 files using other means. To create more secure PKCS#12 files, use Modern2023.
var LegacyRC2 = &Encoder{ macAlgorithm: oidSHA1, certAlgorithm: oidPBEWithSHAAnd40BitRC2CBC, keyAlgorithm: oidPBEWithSHAAnd3KeyTripleDESCBC, macIterations: 1, encryptionIterations: 2048, saltLen: 8, rand: rand.Reader, }
LegacyRC2 encodes PKCS#12 files using weak algorithms that were traditionally used in PKCS#12 files, including those produced by OpenSSL before 3.0.0, go-pkcs12 before 0.3.0, and Java when keystore.pkcs12.legacy is defined. Specifically, certificates are encrypted using PBE with RC2, and keys are encrypted using PBE with 3DES, using keys derived with 2048 iterations of HMAC-SHA-1. MACs use HMAC-SHA-1 with keys derived with 1 iteration of HMAC-SHA-1.
Due to the weak encryption, it is STRONGLY RECOMMENDED that you use DefaultPassword when encoding PKCS#12 files using this encoder, and protect the PKCS#12 files using other means.
By default, OpenSSL 3 can't decode PKCS#12 files created using this encoder. For better compatibility, use LegacyDES. For better security, use Modern2023.
var Modern = Modern2023
Modern encodes PKCS#12 files using modern, robust parameters.
Currently, this encoder is the same as Modern2023, but this may change in the future to keep up with modern practices.
var Modern2023 = &Encoder{ macAlgorithm: oidSHA256, certAlgorithm: oidPBES2, keyAlgorithm: oidPBES2, macIterations: 2048, encryptionIterations: 2048, saltLen: 16, rand: rand.Reader, }
Modern2023 encodes PKCS#12 files using algorithms that are considered modern as of 2023. Private keys and certificates are encrypted using PBES2 with PBKDF2-HMAC-SHA-256 and AES-256-CBC. The MAC algorithm is HMAC-SHA-2. These are the same algorithms used by OpenSSL 3 (by default), Java 20 (by default), and Windows Server 2019 (when "stronger" is used).
Files produced with this encoder can be read by OpenSSL 1.1.1 and higher, Java 12 and higher, and Windows Server 2019 and higher.
For passwords, it is RECOMMENDED that you do one of the following: 1) Use DefaultPassword and protect the file using other means, or 2) Use a high-entropy password, such as one generated with `openssl rand -hex 16`.
You SHOULD NOT use a lower-entropy password with this encoder because the number of KDF iterations is only 2048 and doesn't provide meaningful protection against brute-forcing. You can increase the number of iterations using Encoder.WithIterations, but as https://neilmadden.blog/2023/01/09/on-pbkdf2-iterations/ explains, this doesn't help as much as you think.
var Passwordless = &Encoder{ macAlgorithm: nil, certAlgorithm: nil, keyAlgorithm: nil, rand: rand.Reader, }
Passwordless encodes PKCS#12 files without any encryption or MACs. A lot of software has trouble reading such files, so it's probably only useful for creating Java trust stores using Encoder.EncodeTrustStore or Encoder.EncodeTrustStoreEntries.
When using this encoder, you MUST specify an empty password.
Functions ¶
func Decode ¶
func Decode(pfxData []byte, password string) (privateKey interface{}, certificate *x509.Certificate, err error)
Decode extracts a certificate and private key from pfxData, which must be a DER-encoded PKCS#12 file. This function assumes that there is only one certificate and only one private key in the pfxData. Since PKCS#12 files often contain more than one certificate, you probably want to use DecodeChain instead.
func DecodeChain ¶
func DecodeChain(pfxData []byte, password string) (privateKey interface{}, certificate *x509.Certificate, caCerts []*x509.Certificate, err error)
DecodeChain extracts a certificate, a CA certificate chain, and private key from pfxData, which must be a DER-encoded PKCS#12 file. This function assumes that there is at least one certificate and only one private key in the pfxData. The first certificate is assumed to be the leaf certificate, and subsequent certificates, if any, are assumed to comprise the CA certificate chain.
func DecodeTrustStore ¶
func DecodeTrustStore(pfxData []byte, password string) (certs []*x509.Certificate, err error)
DecodeTrustStore extracts the certificates from pfxData, which must be a DER-encoded PKCS#12 file containing exclusively certificates with attribute 2.16.840.1.113894.746875.1.1, which is used by Java to designate a trust anchor.
If the password argument is empty, DecodeTrustStore will decode either password-less PKCS#12 files (i.e. those without encryption) or files with a literal empty password.
func Encode
deprecated
func Encode(rand io.Reader, privateKey interface{}, certificate *x509.Certificate, caCerts []*x509.Certificate, password string) (pfxData []byte, err error)
Encode is equivalent to LegacyRC2.WithRand(rand).Encode. See Encoder.Encode and LegacyRC2 for details.
Deprecated: for the same behavior, use LegacyRC2.Encode; for better compatibility, use Legacy.Encode; for better security, use Modern.Encode.
func EncodeTrustStore
deprecated
func EncodeTrustStore(rand io.Reader, certs []*x509.Certificate, password string) (pfxData []byte, err error)
EncodeTrustStore is equivalent to LegacyRC2.WithRand(rand).EncodeTrustStore. See Encoder.EncodeTrustStore and LegacyRC2 for details.
Deprecated: for the same behavior, use LegacyRC2.EncodeTrustStore; to generate passwordless trust stores, use Passwordless.EncodeTrustStore.
func EncodeTrustStoreEntries
deprecated
func EncodeTrustStoreEntries(rand io.Reader, entries []TrustStoreEntry, password string) (pfxData []byte, err error)
EncodeTrustStoreEntries is equivalent to LegacyRC2.WithRand(rand).EncodeTrustStoreEntries. See Encoder.EncodeTrustStoreEntries and LegacyRC2 for details.
Deprecated: for the same behavior, use LegacyRC2.EncodeTrustStoreEntries; to generate passwordless trust stores, use Passwordless.EncodeTrustStoreEntries.
func ToPEM
deprecated
ToPEM converts all "safe bags" contained in pfxData to PEM blocks.
Deprecated: ToPEM creates invalid PEM blocks (private keys are encoded as raw RSA or EC private keys rather than PKCS#8 despite being labeled "PRIVATE KEY"). To decode a PKCS#12 file, use DecodeChain instead, and use the encoding/pem package to convert to PEM if necessary.
Types ¶
type Encoder ¶
type Encoder struct {
// contains filtered or unexported fields
}
An Encoder contains methods for encoding PKCS#12 files. This package defines several different Encoders with different parameters.
func (*Encoder) Encode ¶
func (enc *Encoder) Encode(privateKey interface{}, certificate *x509.Certificate, caCerts []*x509.Certificate, password string) (pfxData []byte, err error)
Encode produces pfxData containing one private key (privateKey), an end-entity certificate (certificate), and any number of CA certificates (caCerts).
The pfxData is encrypted and authenticated with keys derived from the provided password.
Encode emulates the behavior of OpenSSL's PKCS12_create: it creates two SafeContents: one that's encrypted with the certificate encryption algorithm and contains the certificates, and another that is unencrypted and contains the private key shrouded with the key encryption algorithm. The private key bag and the end-entity certificate bag have the LocalKeyId attribute set to the SHA-1 fingerprint of the end-entity certificate.
func (*Encoder) EncodeTrustStore ¶
func (enc *Encoder) EncodeTrustStore(certs []*x509.Certificate, password string) (pfxData []byte, err error)
EncodeTrustStore produces pfxData containing any number of CA certificates (certs) to be trusted. The certificates will be marked with a special OID that allow it to be used as a Java TrustStore in Java 1.8 and newer.
EncodeTrustStore creates a single SafeContents that's optionally encrypted and contains the certificates.
The Subject of the certificates are used as the Friendly Names (Aliases) within the resulting pfxData. If certificates share a Subject, then the resulting Friendly Names (Aliases) will be identical, which Java may treat as the same entry when used as a Java TrustStore, e.g. with `keytool`. To customize the Friendly Names, use EncodeTrustStoreEntries.
func (*Encoder) EncodeTrustStoreEntries ¶
func (enc *Encoder) EncodeTrustStoreEntries(entries []TrustStoreEntry, password string) (pfxData []byte, err error)
EncodeTrustStoreEntries produces pfxData containing any number of CA certificates (entries) to be trusted. The certificates will be marked with a special OID that allow it to be used as a Java TrustStore in Java 1.8 and newer.
This is identical to Encoder.EncodeTrustStore, but also allows for setting specific Friendly Names (Aliases) to be used per certificate, by specifying a slice of TrustStoreEntry.
If the same Friendly Name is used for more than one certificate, then the resulting Friendly Names (Aliases) in the pfxData will be identical, which Java may treat as the same entry when used as a Java TrustStore, e.g. with `keytool`.
EncodeTrustStoreEntries creates a single SafeContents that's optionally encrypted and contains the certificates.
func (*Encoder) EncodeWithAttributes ¶
func (enc *Encoder) EncodeWithAttributes(privateKey interface{}, certificate *x509.Certificate, caCerts []*x509.Certificate, password, friendlyName, cspName string) (pfxData []byte, err error)
EncodeWithAttributes produces pfxData containing one private key (privateKey), an end-entity certificate (certificate), any number of CA certificates (caCerts), as well as supplementary attributes (friendlyName and cspName).
The pfxData is encrypted and authenticated with keys derived from the provided password.
EncodeWithAttributes emulates the behavior of OpenSSL's PKCS12_create: it creates two SafeContents: one that's encrypted with the certificate encryption algorithm and contains the certificates, and another that is unencrypted and contains the private key shrouded with the key encryption algorithm. The private key bag and the end-entity certificate bag have the LocalKeyId attribute set to the SHA-1 fingerprint of the end-entity certificate.
func (*Encoder) WithIterations ¶
WithIterations creates a new Encoder identical to enc except that it will use the given number of KDF iterations for deriving the MAC and encryption keys.
Note that even with a large number of iterations, a weak password can still be brute-forced in much less time than it would take to brute-force a high-entropy encrytion key. For the best security, don't worry about the number of iterations and just use a high-entropy password (e.g. one generated with `openssl rand -hex 16`). See https://neilmadden.blog/2023/01/09/on-pbkdf2-iterations/ for more detail.
Panics if iterations is less than 1.
type NotImplementedError ¶
type NotImplementedError string
NotImplementedError indicates that the input is not currently supported.
func (NotImplementedError) Error ¶
func (e NotImplementedError) Error() string
type TrustStoreEntry ¶
type TrustStoreEntry struct { Cert *x509.Certificate FriendlyName string }
TrustStoreEntry represents an entry in a Java TrustStore.