PKI Misc

Generate Private Keys

You can use openssl and certtool to generate a private key. Both support RSA, DSA or ECC (ECDSA) for the algorithm underlying the key. And they optionally encrypt a key with a passphrase. For clarity and consistency, the examples below adopt filenames mysite-clear.pem and mysite-crypt.pem for their plaintext and encrypted keys, respectively.

You'll want to secure a real-world key. Taking cues from the ArchLinux Wiki, these notes put mysite-clear.pem and mysite-crypt.pem in directory private like so:

-> mkdir --mode 0700 private
-> cd private
-> touch mysite-clear.pem mysite-crypt.pem
-> chmod 0600 mysite-clear.pem mysite-crypt.pem
-> ls -og mysite-clear.pem mysite-crypt.pem
-rw-------. 1 0 Sep 11 12:08 mysite-crypt.pem
-rw-------. 1 0 Sep 11 12:08 mysite-clear.pem

The commands generating the actual private keys will overwrite the files but retain the permissions. You'll need to determine what's right for your security needs, of course.

Here's how to generate an RSA private key using OpenSSL's genpkey command:

-> openssl genpkey -out mysite-clear.pem -algorithm rsa -pkeyopt rsa_keygen_bits:2048

The final argument specifies the size of the key, which for RSA is the number of bits in the modulus. The command prints an esoteric progress report in periods, plus symbols, and new lines. You can direct stderr to /dev/null if you've no interest in that.

The private key is not itself encrypted and thus potentially exposed. You can tell genpkey to encrypt the key with a passphrase of your choosing:

-> openssl genpkey -out mysite-crypt.pem -aes128 -algorithm rsa -pkeyopt rsa_keygen_bits:2048 2> /dev/null
Enter PEM pass phrase: not echoed
Verifying - Enter PEM pass phrase:  not echoed

Here option -aes128 orders encryption using AES with 128 bits. OpenSSL offers several other encryption algorithms and a few other ways to enter the password. For example, this command uses AES-256 with password 'demo':

-> openssl genpkey -out mysite-crypt.pem -aes256 -pass pass:demo -algorithm rsa -pkeyopt rsa_keygen_bits:2048 2> /dev/null

The file created by genpkey consists of a PEM block encoding and optionally encrypting the private key. For a plaintext key:

-> cat mysite-clear.pem 
base64 rendition of key's binary data stream goes here

For an encrypted key:

 -> cat mysite-crypt.pem 
 base64 rendition of key's encrypted data stream goes here

If you include option -text, genpkey reports readable values of the modulus, exponents, prime numbers, and coefficients constituting the private key and its public partner. It writes these after the key's PEM block. This information always appears in plaintext—regardless encryption for the PEM block—and thus exposes the private key to anyone who can read the file.

See man page genpkey for more details and options.

You can alternatively use OpenSSL's command genrsa to generate an RSA private key:

-> openssl genrsa -out mysite-clear.pem 2048
Generating RSA private key, 2048 bit long modulus
e is 65537 (0x10001)

You can encrypt the key, too:

-> openssl genrsa -out mysite-crypt.pem -aes128 2048 2> /dev/null

Man page openssl says that genpkey supersedes genrsa and a few analogous commands for other encryption algorithms. Man page genpkey elaborates, a little, by noting that genpkey offers additional options.

Here's how to create an RSA private key using certtool:

-> certtool --generate-privkey --outfile mysite-clear.pem
Generating a 2048 bit RSA private key...

The key is not encrypted. This allows certtool to prepend information about the private key and its matching public key to the PEM block encoding the private key. You can thus view mysite-clear.pem with cat, less, or any text editor to get an idea of the components (modulus, exponents, primes) of the keys.

You can adjust the key's level of security with option --sec-params:

-> certtool --generate-privkey --sec-param low --outfile mysite-clear.pem
Generating a 1024 bit RSA private key...
-> certtool --generate-privkey --sec-param medium --outfile mysite-clear.pem
Generating a 2048 bit RSA private key...
-> certtool --generate-privkey --sec-param high --outfile mysite-clear.pem
Generating a 3072 bit RSA private key...

You can instead use option --bits, but then certtool will urge you to use --sec-params anyway.

You can create an encrypted private key by specifying PKCS #8 format:

-> certtool --generate-privkey --pkcs8 --outfile mysite-crypt.pem
Generating a 2048 bit RSA private key...
Enter password: 

Because the key is encrypted, certtool does not prepend information to the PEM block, as it does for unencrypted keys. Tools like cat and less find only the that chunk of junk to display. You can use option --pkcs-cipher to select a different cipher.

You can alternatively create a DSA or an ECC (ECDSA) key with option --dsa or --ecc, respectively:

-> certtool --generate-privkey --dsa --sec-param low  --outfile mysite-clear.pem
Generating a 1024 bit DSA private key...
-> certtool --generate-privkey --ecc --sec-param high --outfile mysite-clear.pem
Generating a 256 bit EC private key...

Note the difference in the number of bits. For ECC, a 256-bit key is considered high security. For RSA and DSA, a 1024-bit key is considered low security.

Examine Private Keys

The PEM block of a private key encodes the mathematical components of both the key and its public counterpart. You can use OpenSSL's pkey command or GnuTLS's certtool command to decode the PEM block and report these components in a simple, readable format. Even so, what you get is a lot of hex numbers for the bit strings representing these components.

Your key file may aready report the mathematical components outside of the PEM block—depending on how you generated the file. This is the case if you ran genpkey with option -text or if you ran certtool without encryption. Just open the file in a text browser or editor. If you generated your private key using certtool with encryption, however, the key file does not reveal these components.

Here's how to list the components of the private and public keys encoded in file mysite-clear.pem, for example.

Using pkey:

-> openssl pkey -in mysite-clear.pem -text -noout

Private-Key: (2048 bit)
publicExponent: 65537 (0x10001)

Option -noout stops pkey from showing the PEM block.

Or using certtool:

-> certtool --infile mysite-clear.pem --key-info

The report additionally prints the ID and ASCII art for the public key, and it includes the private key's PEM block.

If your private key is encrypted, both commands prompt for the password. Or you can invoke either command with the password included:

-> openssl pkey -in mysite-crypt.pem -text -noout -passin pass:demo
-> certtool --load-privkey mysite-crypt.pem --pubkey-info --password demo

But you expose the password this way.

If you are just interested in the modulus and exponent forming the public key, use option -text_pub instead of -text with pkey:

-> openssl pkey -in mysite-clear.pem -text_pub -noout
Public-Key: (2048 bit)
Exponent: 65537 (0x10001)

Or with certtool use option --pubkey-info instead of --key-info

-> certtool --load-privkey mysite-clear.pem --pubkey-info

In addition to the modulus and exponent, certtool reports the algorithm (e.g., RSA, DSA, etc), usage, ID, and PEM block for the public key.

Extract & Examine Public Keys

A private-key file also holds the components for its public-key partner. You can use OpenSSL's pkey command or GnuTLS's certtool command to extract the public key for distribution or review.

Here's how to extract the public key from the private key in file mysite-clear.pem, for example.

Using pkey:

-> openssl pkey -in private/mysite-clear.pem -pubout -out mysite.pem
-> cat mysite.pem 
base64 rendition of public key's binary data stream goes here
-----END PUBLIC KEY-----

Option -pubout tells pkey to extract the public key only. If you add option -text_pub, then pkey appends a report of the key's components. Do not use option -text because the appended report would include the components of the private key.

Or use certtool:

-> certtool --load-privkey private/mysite-clear.pem --pubkey-info --outfile mysite.pem

The output file includes a report of the key's components, in addition to the key's PEM block.

If the private key is encrypted, you'll be prompted for its passphrase whatever command you choose. The data stream of a public key is not encrypted.

Here's how to list the components of the public key encoded in file mysite.pem, for example.

Using pkey:

-> openssl pkey -in mysite.pem -pubin -text -noout
Public-Key: (2048 bit)
Exponent: 65537 (0x10001)

Option -pubin lets pkey know that it's looking at a public key. Options -text and -text_pub are interchangeable for a public key.

Or using certtool:

-> certtool --load-pubkey mysite.pem --pubkey-info

The report additionally prints the ID and ASCII art for the public key, and it includes the private key's PEM block.

If you extracted your public key with certtool, the output file already includes the key's components in a readable format outside of the PEM block.


Cryptoki is an API between applications requiring cryptographic functionality and devices providing cryptographic services. A cryptographic device stores information or performs operations pertaining to cryptography. Information includes public-key/private-key pairs, secret encryption/decryption keys, certificates, etc. Operations run the usual crypto gamut—encryption, decryption, key generation, digests, signatures and MACs, key management, RNG. For example, a device might safeguard a private key. When an application needs to sign a messages with that private key, it delegates the job to the device, which does the computations without revealing its secret. Or perhaps a device has dedicated circuitry for accelerating computations in comparison to the host system's CPU.

Cryptoki calls devices tokens; "Cryptoki" derives from "CRYP tographic TOKen Interface". Tokens provide mechanisms, which comprise data and algorithms underlying the offered cryptographic operations (more or less). Cryptoki takes a logical view of devices that covers software-only components as well as actual-hardware gizmos. The PKCS#11 standard defines the API, and thus "Cryptoki" and "PKCS#11" are often interchanged.

Ultimately, a Cryptoki provider comes down to a library that an application links into memory, either dynamically or statically. For example, library supports smart cards, and library provides a CA database. Manual pages often refer to these libraries as modules. A module can support multiple tokens. Generally, a module provides one or more slots to which tokens attach, physically or logically, one token per slot.

A module, through its supported tokens, implements whatever subset of Cryptoki it is designed to offer; it need not implement the full functionality of the API. For example, the PKCS#11 Kit Trust Module provides a Fedora system's CA database as two tokens, and that's all it does.

You can use pkcs11-tool (package opensc) to get some basic information about a module. For example, library is the PKCS#11 Kit Trust Module:

-> pkcs11-tool --module /usr/lib64/ --show-info --list-slots
Cryptoki version 2.40
Manufacturer     PKCS#11 Kit
Library          PKCS#11 Kit Trust Module (ver 0.23)
Available slots:
Slot 0 (0x12): /etc/pki/ca-trust/source
  token label        : System Trust
  token manufacturer : PKCS#11 Kit
  token model        : p11-kit-trust
  token flags        : token initialized, readonly
  hardware version   : 0.23
  firmware version   : 0.0
  serial num         : 1
  pin min/max        : 0/0
Slot 1 (0x13): /usr/share/pki/ca-trust-source
  token label        : Default Trust
  token manufacturer : PKCS#11 Kit
  token model        : p11-kit-trust
  token flags        : token initialized, readonly
  hardware version   : 0.23
  firmware version   : 0.0
  serial num         : 1
  pin min/max        : 0/0
Using slot 0 with a present token (0x12)

You can also use pkcs11-dump (eponymous package) to get some basic information about a module. For example:

-> pkcs11-dump info /usr/lib64/ 2>/dev/null
Provider Information:
               cryptokiVersion: 2.40
                manufacturerID: PKCS#11 Kit                     
                         flags: 00000000
                libraryVersion: 0.23
            libraryDescription: PKCS#11 Kit Trust Module        

(pkcs11-dump prints copyright information to stderr, which the above redirection discards.) You can see how many slots the module offeres and what tokens are attached:

-> pkcs11-dump slotlist /usr/lib64/ 2>/dev/null
18	/etc/pki/ca-trust/source                                        
19	/usr/share/pki/ca-trust-source    

Finally, you can see information on a token. For example, in slot 18:

-> pkcs11-dump dump /usr/lib64/ 2>/dev/null 18 -
Please enter PIN: any key
Token Information:
                         label: System Trust                    
                manufacturerID: PKCS#11 Kit                     
                         model: p11-kit-trust   
                  serialNumber: 1               
                         flags: CKF_WRITE_PROTECTED,CKF_TOKEN_INITIALIZED
⋮ details omitted

Since the module's CA database is a repository of certificates open to all comers, this token does not use a PIN; pressing any key will do.

Cryptoki is a C-language API consisting of functions, typedef declarations, etc. The base specification has a synopsis of these 68 functions, organized into categories (§5 Functions). A module must define a look-up table (i.e., struct) giving a function pointer to each of these functions:

typedef struct CK_FUNCTION_LIST {
  CK_C_Initialize C_Initialize
  CK_C_Finalize C_Finalize
  CK_C_GetInfo C_GetInfo
  CK_C_GetFunctionList C_GetFunctionList

If a module does not support the nominal service of a function, it simply points the corresponding table entry to a stub function that returns a special value saying so. An application calls a Cryptoki function by looking up that function's pointer by name in the table. The table is returned by function C_GetFuntionList, which every module must provide.

Module adopts the same names as the API. A look inside gives the flavor of the API:

-> readelf --syms --wide /usr/lib64/ | grep -P ' C_' | wc --lines
-> readelf --syms --wide /usr/lib64/  | cut --bytes 60- | grep -P '^C_' 

But this nano-hack won't work for all libraries; for example:

-> readelf --syms --wide /usr/lib64/pkcs11/  | cut --bytes 60- | grep -P '^C_'

And that's because a module can name API functions however it sees fit as long as it politely points them out to a visitor.

p11-glue & p11-kit

The umbrella project p11-glue from seeks to promote and facilitate Cryptoki/PKCS#11 as the glue between security-cognizant applications and cryptographic devices (hardware and software). It currently encompasses two projects, namely p11-kit and Trust Storage Module.

Project p11-kit (package p11-kit) allows applications to discover, load, and examine Cryptoki devices furnished by other libraries, which it calls modules. A module implements one or more tokens. The project's chief products are library, which manages loading and initializing modules, and utility p11-kit, which lets end-users interactively examine those modules. (Applications link to the library.)

The Trust Storage Module (package p11-kit-trust) represents the system's CA store as two tokens. Its main products are module, which implements the CA database as tokens, and utility trust, which lets end-users query these tokens. For more about this module, see notes PKCS#11 Kit Trust Module.

Use p11-kit to list modules known to p11-kit on your system:

-> p11-kit list-modules
    library-description: PKCS#11 Kit Trust Module
    library-manufacturer: PKCS#11 Kit
    library-version: 0.23
    token: System Trust
        manufacturer: PKCS#11 Kit
        model: p11-kit-trust
        serial-number: 1
        hardware-version: 0.23
    token: Default Trust
        manufacturer: PKCS#11 Kit
        model: p11-kit-trust
        serial-number: 1
        hardware-version: 0.23
    library-description: GNOME Keyring (without daemon)
    library-manufacturer: GNOME Keyring
    library-version: 1.1
    library-description: OpenSC smartcard framework
    library-manufacturer: OpenSC Project
    library-version: 0.17

Library gathers run-time configuration and modules from multiple files. Man page pkcs11.conf has the details. Its default locations for these files differ from those of the Fedora build, however. Here's the run-down inferred from Fedora's installation.

Each module has its own configuration file in directory /usr/share/p11-kit/modules: For example:

-> pkgconf p11-kit-1 --variable p11_module_configs
-> ls /usr/share/p11-kit/modules
gnome-keyring.module  opensc.module  p11-kit-trust.module

The library also looks for a system configuration file, which is optional. The man page names /etc/pkcs11/pkcs11.conf, but no file pkcs11.conf is installed:

=> rpm --query --list p11-kit | grep -P 'pkcs11.conf$'
no output
-> locate --basename '\pkcs11.conf'
no output

It looks like the Fedora build may expect /usr/share/p11-kit/pkcs11.conf, though:

-> pkgconf p11-kit-1 --variable p11_system_config_modules

But that's not confirmed (by me).

Each configuration file identifies its actual Cryptoki library. For example:

-> grep module: /usr/share/p11-kit/modules/opensc.module 

When a module's configuration file names the library file without a proper path, as here, assumes directory /usr/lib64/pkcs11:

-> pkgconf p11-kit-1 --variable p11_module_path

Library may permit users to adjust system configurations in file ~/.config/pkcs11/pkcs11.conf and to add modules of their own choosing in ~/.config/pkcs11/modules. See setting user-config.

By the way, to get results from pkgconf, you'll need to install package p11-kit-devel. It provides file /usr/lib64/pkgconfig/p11-kit-1.pc required by pkgconf. See also Packaging PKCS#11 module configs.

Package p11-kit also installs symbolic link /usr/lib64/libnssckbi, which provides a drop-in replacement for the synonomous library from NSS:

-> file /usr/lib64/
/usr/lib64/ symbolic link to /etc/alternatives/

-> alternatives --display - status is auto.
 link currently points to /usr/lib64/pkcs11/
/usr/lib64/pkcs11/ - priority 30
/usr/lib64/nss/ - priority 10
Current `best' version is /usr/lib64/pkcs11/

With this swap, Firefox and other applications using NSS transparently access the system CA database in addition to any certificates in a user's private CA repository.

Network Security Services (NSS)

Package nss ...

=> rpm --query --list nss | grep lib64

TLS applications call into, and S/MIME applications call into; both of these call into defines the default set of trusted root certificates.

The package nss also installs DBM and SQL databases under /etc/pki, although they appear to be unused (on my system, anyway):

=> rpm --query --list nss | grep etc

There is a man page for each of these files.