gefvert.org

PKCS Standards

Sunday, 09 October 2022 - 3 minutes to read

Standard RFC Description
PKCS#1 8017 RSA key format (in PEM form "-----BEGIN RSA PRIVATE KEY-----"); not that common because PKCS #8 describes a generic format
PKCS#2 Withdrawn
PKCS#3 DH key agreement thingy
PKCS#4 Withdrawn
PKCS#5 8018 Describes PBKDF2 key derivation algorithm
PKCS#6 Obsolete - X.509 extensions
PKCS#7 2315 Cryptographic message syntax standard. For signing/encrypting PKI data. Formed the basis of S/MIME - see RFC 5652
PKCS#8 5958 Private key format (in PEM form "-----BEGIN PRIVATE KEY-----"). Used by OpenSSL for private keys in DER or PEM form. Can be encrypted or not.
PKCS#9 2985 Selected attribute types for PKCS #6, #7, #8, and #10.
PKCS#10 2986 Certification request standard.
PKCS#11 Cryptographic token interface ("Cryptoki"). API for tokens, like HSM's and stuff.
PKCS#12 7292 PFX files.
PKCS#13 Abandoned - Elliptic keys.
PKCS#14 Abandoned - PRNG stuff.
PKCS#15 Something about cryptographic tokens and identifications.

  • OpenSSL creates certificates in X.509 format along with a PKCS#8 private key. Mostly in PEM form.
  • There are two formats:
    • DER, which is an ASN.1 binary format (also referred to as BER, the difference is insignificant)
    • PEM, which is base64-encoded DER and sandwiched between headers that look like "-----BEGIN PRIVATE KEY-----" and "-----END PRIVATE KEY-----"

There are three different ways certificates can be represented:

  1. As a .cer file that starts with -----BEGIN CERTIFICATE----- - this is a PEM-encoded (base64) X.509 certificate. It may or may not have the chain of intermeditate and root CA certificates in it. Apache servers usually prefer this format.
  2. As a .p7b/.p7s file that starts with -----BEGIN PKCS7----- - this is a PKCS#7 format mostly used for Windows and Java servers; and typically includes the CA chain embedded in it.
  3. As a binary .pfx/.p12 file - this is the PKCS#12 format that contains all the certificates and the chain, as well as the private key, in encrypted format. This can easily be adopted into a Windows certificate store for further protection.

You can generate new self-signed X.509 keys, for SAML purposes, by using the following command. (Note: The password-file.txt file defines the password for the resulting key. Do not include a CRLF in the file unless you really want your password to contain a CRLF.)

openssl req -x509 -sha512 -days 3650 -newkey rsa:2048 \ 
    -out mycompany.cer -keyout mycompany.key \
    [ -nodes /or/ -passout file:password-file.txt ] \
    -subj "/C=SE/L=City/O=MyCompany/CN=www.my-company.com"

Generate a .PFX file from these by using the following command. (Note: There are two identical password files, because the password file gets locked when the -passin command runs and then the -passout command can't read the password file. Silly.)

openssl pkcs12 \
    -in mycompany.cer -inkey mycompany.key \
    -export -out mycompany.pfx \
    -name "My Company Key Pair" \
    -passin file:password-file.txt -passout file:password-file2.txt
    
(**Note to self:** Does this include the CA certificates?)        

You can also programmatically convert the .cer and .key files to PKCS#12 format in C# by doing this:

using var cert = new X509Certificate2("mycompany.cer");
using var key = RSA.Create();

var keyText = string.Join("", File.ReadAllLines("mycompany.key")
    .Where(x => !x.StartsWith("---"))
    .Select(x => x.Trim())
    .Where(x => !string.IsNullOrEmpty(x)));

var keyData = Convert.FromBase64String(data2);
key.ImportPkcs8PrivateKey(keyData, out _);

using var outputCert = cert.CopyWithPrivateKey(key);
var outputData = outputCert.Export(X509ContentType.Pfx);

File.WriteAllBytes("mycompany.pfx", outputData);

This does not encrypt the certificate or password, but adding encryption is trivial with key.ImportEncryptedPkcs8PrivateKey and a parameter to outputCert.Export().


Add a comment

  to leave a comment. It's quick and painless.