One main purpose of OpenPGP CA is issuing certifications. To issue certifications, the CA uses a private key. This private key must be accessible to the CA.
The simplest way to handle the CA private key is to store it in the CA database, and use it from there. This is what the “softkey” backend does (it uses a “software-based” key). The softkey backend has the benefit that it is easy to use and doesn’t require additional hardware. However, it exposes the CA’s private key material to the risk of exfiltration (or malicious use by an attacker).
The OpenPGP card backend is an alternative to the softkey backend. It uses a hardware device to store the CA’s private key. Such devices are designed to keep private key material safe. Operations that require the CA key are performed directly on the OpenPGP card device.
The OpenPGP card backend is intended for use cases with higher security needs.
About OpenPGP cards
OpenPGP cards are a type of hardware security device. They follow a published standard1. Many devices2, from a range of vendors, implement this standard.
OpenPGP card devices are relatively inexpensive (tens of EUR/USD).
Card models and features
Different card models support different sets of cryptographic algorithms. Most modern cards support the algorithms that OpenPGP CA uses3.
There are other optional features that only some card models support. Of these, you should particularly consider if your CA instance should make use of the “touch confirmation” feature.
Some cards can be configured to require manual (“touch”) confirmation for each cryptographic operation.
In the context of OpenPGP CA, this means that whenever the CA admin wants to issue a certification, the OpenPGP card device requires manual confirmation (usually given by touching a button on the device).
Requiring touch confirmation has the advantage that even if a remote attacker gains control of the computer that runs the CA, they cannot easily issue malicious certifications (they’d need to trick the CA operator into pressing the confirmation button).
However, requiring touch confirmation is not possible when a CA is supposed to issue certifications automatically, without manual intervention (for example when running a web-portal, where users can upload their public keys and instantly receive certifications).
Custom use of key slots by OpenPGP CA
An OpenPGP key usually consists of multiple cryptographic (sub)keys, internally. The different subkeys are used for different types of operations.
OpenPGP CA keys usually consist of two such cryptographic (sub)keys:
- A “primary” key, which is used to issue certifications.
- A signing-capable subkey (which is used when exporting the CA database in the “Keylist” format).
OpenPGP cards have three slots for individual cryptographic keys. Those slots are labeled SIG, DEC and AUT (short for signing, decryption and authentication).
OpenPGP CA uses the “AUT” slot for the certification capable primary key and the “SIG” slot for the signing-capable subkey.
(This, incidentally, means that when used with OpenPGP CA, the fingerprint shown in a card’s “AUT” slot is the primary fingerprint of your CA’s key.)
To make cards that are used for a CA easily recognizable, OpenPGP CA sets the Cardholder Name field on the card to the string “OpenPGP CA”4.
Interaction with GnuPG’s scdaemon
If you’re running GnuPG (and its Smartcard daemon scdaemon), you might see unexpected errors that cards are not connected to your system, like this:
$ oca -d example.oca ca init --domain example.org card Error: No blank OpenPGP card found
If so, this is probably caused by scdaemon’s default behavior of permanently opening cards with exclusive access rights.
To work around this, you can configure GnuPG’s scdaemon subsystem to open
cards in shared mode by adding a line
pcsc-shared to the file
Running a CA with the OpenPGP card backend
Initializing a card-backed CA instance
Initializing a new card-backed OpenPGP CA instance requires a blank OpenPGP card (a new card will work, or any card after a factory reset).
The card must support RSA 4096 (this is currently the default algorithm for the CA’s key). Most modern cards support RSA 4096.
To specify which card to use with OpenPGP CA, you can provide the card’s “ident”6 as a parameter. However, usually you can omit this parameter: as long as there is exactly one blank card connected to the system, OpenPGP CA will automatically select that one.
Let’s say you’ve plugged in the blank card
Then you can initialize a new CA instance using that card, without explicitly
specifying its identity, like this:
$ oca -d example.oca ca init --domain example.org card Initializing OpenPGP CA on card FFFE:43194240. Generated new CA key: -----BEGIN PGP PRIVATE KEY BLOCK----- Comment: 4E42 D830 8863 526A 1B6F 63A9 7B3D E60F CC7C 2B78 Comment: OpenPGP CA <firstname.lastname@example.org> xcZYBGPNo8IBEACyqBmZ6r81T5D3HE6Md/i+l+n4YffRPiQYzKnEFPYMDV8dllDE BwPRkrIVW1LlVj+4XtalKG/Uhr706nw2Bp6RD43zvIdfCUuSZjym6B5rC5XhEcoi [..] 4pghvR5XTisnuVuy5DHR5NUy6JAT8ioujItSK8ts2pM0GyEhDknNgDQMbXwgAJB1 aCY= =7BSJ -----END PGP PRIVATE KEY BLOCK----- Initialized OpenPGP CA instance: CA Domain: example.org Fingerprint: 4E42D8308863526A1B6F63A97B3DE60FCC7C2B78 Creation time: 2023-01-22 20:59:46 UTC CA Backend: OpenPGP card FFFE:01234567 [User PIN 30186864]
By default, the new CA key gets generated on the host computer, and uploaded to the card.
Note that the output shows that your new CA instance uses the “OpenPGP card” backend. It also shows the card ident and a newly set PIN for the card.
Explicitly selecting a card
If multiple blank cards are connected to your system, and you don’t explicitly select one, ‘ca init’ will return an error like this:
$ oca -d /tmp/example.oca ca init --domain example.org card Error: Multiple blank OpenPGP cards found: FFFE:11111111 FFFE:22222222
In this case, you can initialize a CA by explicitly specifying one of these cards, like this:
$ oca -d /tmp/example.oca ca init --domain example.org card FFFE:11111111 [..]
During initialization, OpenPGP CA sets both the User and Admin PIN of your
card to a random 8 digit value (both PINs are set to the same value).
This new PIN is stored in the CA database (you can inspect it in the output
ca show command).
This PIN protects you against attackers that have physical access to your OpenPGP card, but no access to the CA database (which contains the PIN):
If someone gets access to your OpenPGP card, and tries to use it on their own computer, they can’t use your CA’s key, as long as they don’t know the PIN (cards only allow 3 attempts at providing the PIN, so a brute-force attack on the PIN is not possible).
During normal operation, the CA will automatically provide the User PIN (as stored in the CA database) to the card, whenever it is needed. Thus, you never need to enter the card PIN while using OpenPGP CA7.
Changing the Admin PIN
You can optionally change the Admin PIN of your card to a different value.
After initialization, OpenPGP CA only accesses the card with user privileges (to perform cryptographic operations). No access with admin privileges is required by OpenPGP CA.
Whether changing the Admin PIN has any benefits depends on details of
your setup8. If you want to change it,
opgpcard is one tool
you can use to do so.
Safekeeping the CA private key
With a softkey-backed CA instance, the private CA key is stored in the database.
By contrast, with card-backed CA instances, the CA system doesn’t have direct access to the CA private key material. The private key material is stored on the card, not in the CA database.
When initializing a card-backed CA, the CA private key is printed to stdout, but not stored.
You will want to keep a copy of this private key for potential future use! For example, you could copy the private key from the terminal into a text file on a USB storage device (an encrypted USB storage device is good practice).
The goal is that you can access the private key material, in the future, but until then keep the key out of reach from potential attackers.
If you don’t make a copy of the private key material (as printed after CA initialization), there is no way you can obtain a copy of your CA private key in the future. You are limited to using the key material via the OpenPGP card. If that card is lost (or breaks), you will need to generate a new CA key, and all users of your CA will need to manually confirm that they want to rely on that new CA key.
Initialization on an air-gapped system
You may want to perform the CA initialization step on an air-gapped computer (possibly running a system like Tails).
When you perform the initialization on an air-gapped system, the CA private key is only handled on that system, and copied to an offline medium (such as encrypted USB storage) from there.
The goal is that no trace of the CA private key material touches any storage that an attacker might gain access to (to prevent any possibility of exfiltration).
After initialization, you can copy the new CA database to the system that you want to run your CA from. A card-backed CA’s database does not contain the CA private key material.
Using the OpenPGP card backend protects the CA private key against exfiltration
The main purpose of using the OpenPGP card backend is that the computer that runs your CA has no direct access to the CA’s private key material.
Using the card backend (after following safe procedures when initializing your CA, and keeping the backup of the CA key safe, as described above), makes exfiltration of the CA key exceedingly unlikely.
However, note that there is still the adjacent risk that an attacker who gains control of the computer that runs your CA could (possibly secretly) use the CA key, on the card, e.g. to issue malicious certifications9.
How to use touch confirmation
If you’re running a CA instance that is operated interactively by the CA admin (that is: every certification is generated by the admin, explicitly), then enabling touch confirmation on your OpenPGP card might be useful (see the discussion about the touch confirmation feature, above).
Configuring the touch confirmation setting
Configuring touch confirmation is possible with some vendor-specific tools, or with the opgpcard tool.
Let’s say we have just initialized an OpenPGP CA instance on a card that supports touch confirmation:
$ oca -dexample.oca ca show CA Domain: example.org Fingerprint: BF7D78A8BBFACB690F28220DBFB857FE24A06CCE Creation time: 2023-01-23 13:21:31 UTC CA Backend: OpenPGP card 0006:01234567 [User PIN 38343522]
We can inspect the card’s status with
opgpcard like this (the
is required to show the touch policy configuration):
$ opgpcard status -v OpenPGP card 0006:01234567 (card version 3.4) Cardholder: OpenPGP CA Signature key: Fingerprint: 2928 3F29 3D75 0039 DD39 F87F 7688 3780 C658 5491 Creation Time: 2023-01-23 13:21:31 UTC Algorithm: RSA 4096 [e 17] Touch policy: Off (features: Button) Key Status: imported User PIN presentation is valid for unlimited signatures Signatures made: 0 Decryption key: Algorithm: RSA 2048 [e 17] Touch policy: Off (features: Button) Key Status: not present Authentication key: Fingerprint: BF7D 78A8 BBFA CB69 0F28 220D BFB8 57FE 24A0 6CCE Creation Time: 2023-01-23 13:21:31 UTC Algorithm: RSA 4096 [e 17] Touch policy: Off (features: Button) Key Status: imported Attestation key: Algorithm: RSA 2048 [e 17] Touch policy: Fixed (features: Button) Remaining PIN attempts: User: 3, Admin: 3, Reset Code: 0 Key status (#129): imported
Note that the “Touch policy” for the Signature and Authentication keys is set to “Off”.
We can change these settings to a different value, such as “On” or “Fixed”
(note that the Admin PIN has been set to
38343522 during CA
initialization, as shown above in the output for
ca show, so that is
the PIN we need to present to change the configuration of the card):
$ opgpcard admin --card 0006:01234567 touch --key SIG --policy Fixed Enter Admin PIN: $ opgpcard admin --card 0006:01234567 touch --key AUT --policy Fixed Enter Admin PIN:
Please check the documentation of your card model to learn which touch confirmation settings it supports. If the “Fixed” setting is available, and if you’re sure that you will always use your CA key interactively, this setting is a good defensive choice10.
Touch confirmation while operating a CA
After configuring touch confirmation to be required for the “AUT” slot, when you run an OpenPGP CA command that issues a certification, the operation blocks - and you see a message that tells you to confirm the operation:
$ oca -d example.oca user add --email email@example.com Touch confirmation needed for certification
Once you give the confirmation, the operation completes. If you don’t confirm the operation, the operation times out (and fails) after a while.
If your command certifies multiple identities, you see the confirmation message multiple times and need to confirm repeatedly (once for each operation).
Migrating a softkey instance to the card-backend
If you have been operating a softkey-based OpenPGP CA instance (let’s -
again - say in the CA database file
and you want to continue operating this CA backed by an OpenPGP card,
you can easily migrate your instance as follows.
First: Backup the CA private key
Before you perform the migration, make sure that you have a backup of your CA’s private key! You can either export the CA private key as an armored text file:
$ oca -d example.oca ca private > ca.priv
Or you can store a copy of the full CA database file (pre-migration) in a safe location.
(You will want to store this CA key backup in a safe place. For example: offline, encrypted USB storage.)
Then: Migrate the CA onto an OpenPGP card
Now that a copy of the CA private key material is safely stashed away, let’s
migrate our (softkey) CA to the (blank, or factory reset) OpenPGP card
$ oca -d example.oca ca migrate card Migrating OpenPGP CA instance to card FFFE:01234567. Caution: After migration is performed, the CA private key material will not be available in the CA database anymore! Make sure you have a backup of your CA key before continuing! Are you sure? (type 'yes' to continue) yes Migrated OpenPGP CA instance: CA Domain: example.org Fingerprint: F149D16EEB76F03059B7280DCA237D22A365F63B Creation time: 2023-01-23 22:55:50 UTC CA Backend: OpenPGP card FFFE:01234567 [User PIN 62013356]
With that, your CA instance is now backed by the OpenPGP card FFFE:01234567. At this point, the CA database does not contain the CA’s private key material anymore11.
Your CA’s private key material has been imported into the AUT and SIG slots of your OpenPGP card. Cryptographic operations using the CA key will from now on be performed on the card.
Like above, the User and Admin PIN of the card have been set to a new 8-digit random value.
Using a secondary OpenPGP card as backup
If you run a card-backed OpenPGP CA instance, you might want to prepare for loss or breakage of the card that contains your CA’s key. Or, similarly, you may want to set up a second card after the first one has become unavailable.
Let’s say you’re already running a CA, using the database file
on the card
FFFE:11111111 (see section “Initializing a card-backed CA
instance” for details on initializing a card-backed CA), and you have the
CA private key available in the file
Let’s inspect this CA:
$ oca -d example.oca ca show CA Domain: example.org Fingerprint: 23AC66B369EE135149C8BB1DCF53BCF0714B598A Creation time: 2023-01-31 18:40:02 UTC CA Backend: OpenPGP card FFFE:11111111 [User PIN 33991107]
Importing the key material onto a secondary card
Given the CA private key in a file, you can easily import the key onto a second card.
As discussed above (in the section “Initialization on an air-gapped system”) depending on your security requirements, you might want to only handle the CA private key material on an air-gapped machine, possibly running a system like Tails.
Here, we’re using an example card ident
FFFE:22222222 for the second card.
As long as there is exactly one blank card connected to your system,
OpenPGP CA will automatically select it:
$ oca -d tmp.oca ca init --domain example.org card --import ca.priv Initializing OpenPGP CA from existing key, on card FFFE:22222222. Initialized OpenPGP CA instance: CA Domain: example.org Fingerprint: 23AC66B369EE135149C8BB1DCF53BCF0714B598A Creation time: 2023-01-31 18:40:02 UTC CA Backend: OpenPGP card FFFE:22222222 [User PIN 86998755]
This command imports the key material from
ca.priv onto the blank card
As a side effect, this command sets up a new OpenPGP CA instance (in the
There’s no strong reason to keep that database file around, but you can.
Either way, you should make very sure to keep the PIN for your secondary
CA card available (in the example above, the PIN is set to
Without that PIN, you can not use that OpenPGP card.
Both cards (
FFFE:22222222) now contain the same CA
key material and can be used interchangeably. However, note that - as OpenPGP
CA sets a random PIN for each card during initialization - the PINs differ
between the two cards.
You can supply the identifier for your secondary card, if you like (or if necessary):
$ oca -d tmp.oca ca init --domain example.org card FFFE:22222222 --import ca.priv [..]
Switching a CA instance to using a different card
Now let’s imagine we lost access to the card
FFFE:11111111 and want to
switch the operation of our
example.oca CA to the card
After plugging in the card
FFFE:22222222, we can switch the CA to using it,
like this (again, you can explicitly specify the card ident, but you don’t
need to, as long as exactly one card is connected to the system that matches
your CA’s key):
$ oca -d tmp.oca ca set-backend card Enter User PIN for OpenPGP card FFFE:22222222: CA backend configuration is changed.
Note that User PIN entry for the new card is required.
Recall that the PIN for the card
FFFE:22222222 was set
Inspecting the CA database
example.oca now shows the changed backend
configuration (including the PIN):
$ oca -d example.oca ca show CA Domain: example.org Fingerprint: 23AC66B369EE135149C8BB1DCF53BCF0714B598A Creation time: 2023-01-31 18:40:02 UTC CA Backend: OpenPGP card FFFE:22222222 [User PIN 86998755]
Initializing a CA with on-card key generation
In some contexts, a user may prefer to run a CA with key material that was generated on the OpenPGP card device. This approach has the disadvantage that it is - by definition - not possible to make a backup of the CA private key material. If the card is lost or breaks, the CA key is not available anymore.
Also, when generating key material on the card, you are relying on the card to generate a strong key.
If these tradeoffs are acceptable, generating the key material on the card is an easy way to create a CA key that has never been accessible to the computer your CA runs on.
To generate the CA key on your card, add the parameter
(as usual, you can specify the card ident, but you don’t have to, as long as
exactly one blank card is connected to the system):
$ oca -d example.oca ca init --domain example.org card --generate-on-card Generate new OpenPGP CA key on card 0006:01234567. Note: 1) The private CA key will only exist on the card (you can't make a backup) 2) The randomness your OpenPGP card generates could be worse than your host computer's Are you sure? (type 'yes' to continue) yes Generating RSA4k key material on the card, this might take a while. [..] Initialized OpenPGP CA instance: CA Domain: example.org Fingerprint: 82A6B8E3CA9FC5597DE4C9E2469CC9C649F96106 Creation time: 2023-01-23 16:13:39 UTC CA Backend: OpenPGP card 0006:01234567 [User PIN 96659737]
As the output warns, key generation on a card takes some time. For the RSA 4096 keys that OpenPGP CA generated, you should expect key generation on the card to take a minute or two.
- OpenPGP card devices are cheap and easy to source.
- Using the OpenPGP card backend protects the CA key from exfiltration.
- However, without requiring touch confirmation, there is still a risk that an attacker may secretly issue additional certifications with the CA key.
- Putting aside touch confirmation: once initialized, operation of a card-backed OpenPGP CA instance works exactly like a softkey-backed CA instance.
The OpenPGP card standard aims to be patent-free and is designed for free usage under the GPL. ↩︎
Vendors that build devices with OpenPGP card support include Nitrokey and YubiKey.
The Gnuk project offers a Free Software implementation of the standard that can be run on different hardware, including the FST-01SZ and the Nitrokey Start.
The SmartPGP project offers a JavaCard implementation of the standard, it is also published as Free Software. ↩︎
By default, OpenPGP CA uses an RSA 4096 key. Most current OpenPGP card models support this algorithm. ↩︎
As a precaution, OpenPGP CA won’t attempt to use cards that are set to a different cardholder name. ↩︎
However, be aware that GnuPG’s documentation warns that “Scdaemon assumes exclusive access to the card and for example caches certain information from the card”.
If you plan to access a card via both GnuPG and different software (e.g. OpenPGP CA), you might want to strategically restart
scdaemonafter modifying a card’s state from outside GnuPG. ↩︎
Technically speaking, the “ident” is a short identifier for an OpenPGP card that consists of the manufacturer id and the card serial number, separated by a colon.
One way to learn this identifier of your OpenPGP card is by running the command
opgpcard list, while the card is plugged in (the
opgpcardcommand is supplied by the
In the future, pin-pad entry of the PIN for the CA card will be supported. In that mode of operation, the CA system will not have access to the card PIN. Instead, the operator is required to enter the PIN on the pin-pad of an external card-reader for each cryptographic operation. This provides an additional layer of defense, but at some cost to convenience. ↩︎
Changing the Admin PIN to a value that is not known to the computer that runs the CA is useful if your setup can be undermined with the Admin PIN.
E.g.: if you rely on a “touch confirmation” requirement, and the configuration for touch requirement is set to “On”, then knowledge of the Admin PIN allows an attacker to temporarily disable touch confirmation. This might be a problem.
In such cases, you don’t want the computer that runs the CA to have access to the Admin PIN.
On the other hand, if touch confirmation is either disabled, or configured as permanently required (“Fixed”), then access to the Admin PIN doesn’t have a practical impact (a “Fixed” touch requirement cannot be lifted, short of factory resetting the card, which destroys the key material).
Aside from the touch confirmation configuration, the Admin PIN does not give meaningful security benefits in the context of an OpenPGP CA instance (recall that the User PIN is readily available via the database). ↩︎
As described in the sections about “touch confirmation”, to make this kind of attack harder, some OpenPGP card devices allow a configuration where each cryptographic operation requires manual (“touch”) confirmation.
Requiring touch confirmation is a good practice for interactively operated CAs. However, for automated CAs, requiring touch-confirmation is not an option. ↩︎
If the computer that runs the CA has no access to the Admin PIN, configuring touch confirmation to “On” offers a comparable defense. See the discussion in the section “Changing the Admin PIN”. ↩︎
The migration procedure runs the SQLite “VACUUM” command at the end, to dispose of any potentially remaining copies of (parts of) the CA private key material.
If you don’t want to rely on the Sqlite VACUUM command, you can additionally “.dump” the data from your migrated CA database into text format, optionally inspect the dump, and re-import this dump into a fresh database file.
You should also consider if any other traces of the private key material might remain on your system (e.g. copies of the CA database, including on the block device that stores the CA database). This may be a non-trivial problem, that we can only hint at, here. ↩︎