A walk outside the sandbox

Home Blog Cheat Sheets MacOS Tips Area 51 About

Using Tokens in Ubuntu with PGP



In this tutorial we’ll see how to use an eToken in Ubuntu with PGP for signing documents and also encryption/decryption. We’ll use the Aladdin eToken Pro, a very popular token with good support for Linux. The goal is to be able to correctly initialise the token, generate key pairs and certificates and integrate the token with GPG and PKCS11. This was inspired and adapted from eToken Pro 72k and Linux

While these instructions should work with other Linux distributions as well, your mileage may very. I did spend a good amount of time searching for fixes and workarounds. It was successfully tested on the following versions:

  • Token version: 2.7.195
  • Ubuntu: 14.04.5 x86_64
  • gpg (GnuPG) 2.0.22
  • SafenetAuthenticationClient 9.0.43
  • gnupg-pkcs11-scd 0.7.3-1
  • libengine-pkcs11-openssl 0.1.8-3


This post is part of the Security Bricks tutorials - simple methods and habits to build a deliberately secure operational environment, for personal and business use. The other parts below:

1. System configuration

  • First install all packages required:
$ sudo apt-get install opensc libpcsclite1 pcsc-tools pcscd
$ sudo apt-get install libengine-pkcs11-openssl 
$ sudo apt-get install gnupg-pkcs11-scd 
$ sudo apt-get install gnupg2
  • Install HAL:
$ sudo add-apt-repository ppa:mjblenner/ppa-hal
$ sudo apt-get update
$ sudo apt-get install libhal1 libhal-storage1
  • Install SafeNet client:
$ sudo dpkg -i SafenetAuthenticationClient-9.0.43-0_amd64.deb
  • Verify that you can access the token:
$ pkcs11-tool --module /usr/lib/ --show-info
Cryptoki version 2.20
Manufacturer     SafeNet, Inc.
Library          SafeNet eToken PKCS#11 (ver 9.0)
Using slot 0 with a present token (0x0) 
$ pkcs11-tool --module /usr/lib/ --list-slots
Available slots:
Slot 0 (0x0): AKS ifdh 00 00
  token label        : mytoken3
  token manufacturer : SafeNet, Inc.
  token model        : eToken
  token flags        : rng, login required, PIN initialized, token initialized, other flags=0x500200
  hardware version   : 4.28
  firmware version   : 2.7
  serial num         : 0947afab
If you have multiple tokens or card reader slots, you'll have to use the --slot 0 parameter with all pkcs11-tool commands.

2. Token initialisation

  • Create Security Office (SO) PIN (PUK):
$ pkcs11-tool --module /usr/lib/ --init-token --label mytoken3
  • Create a user PIN:
$ pkcs11-tool --module /usr/lib/ --init-pin --login
For both PUK and PIN, no complexity requirements are enforced, allowing for weak pins. The only requirement is that its length should be greater than 3. Supposedly brute-forcing the token should be impossible.
  • Change the current user PIN:
$ pkcs11-tool --module /usr/lib/ --change-pin
  • Create an RSA public and private key pair - This will be generated on the token and will not leave the device:
$ pkcs11-tool --module /usr/lib/ --login --keypairgen --key-type RSA:2048 --id 1 --label ""
  • Verify that the key was correctly generated - You should see two key objects, public and private:
$ pkcs11-tool --module /usr/lib/ --login --list-objects
Using slot 0 with a present token (0x0)
Logging in to "mytoken3".
Please enter User PIN: 
Public Key Object; RSA 2048 bits
  ID:         01
  Usage:      encrypt, verify, wrap
Private Key Object; RSA 
  ID:         01
  Usage:      decrypt, sign, unwrap
  • Delete objects from the token - If for any reason we want to delete objects, we need their id and type. Examples of type are cert, privkey and pubkey:
$ pkcs11-tool --module /usr/lib/ --login --delete-object --type pubkey --id 1
  • Create an X509 certificate - We’ll create a self-signed certificate for the keypair we just generated. This eToken only accepts certificates in DER format, so we need to convert it to DER. We can do this from within OpenSSL prompt:
OpenSSL> engine dynamic -pre SO_PATH:/usr/lib/engines/ -pre ID:pkcs11 -pre LIST_ADD:1 -pre LOAD -pre
(dynamic) Dynamic engine loading support
[Success]: SO_PATH:/usr/lib/engines/
[Success]: ID:pkcs11
[Success]: LIST_ADD:1
[Success]: LOAD
Loaded: (pkcs11) pkcs11 engine
OpenSSL> req -engine pkcs11 -new -key slot_0-id_01 -keyform engine -x509 -out my.pem -text
PKCS#11 token PIN: ****
OpenSSL> x509 -in my.pem -out my.der -outform der
  • Write the certificate to the token:
$ pkcs11-tool --module /usr/lib/ --login --write-object my.der --type cert --id 01 --label ""
  • Verify that it was correctly written - you should see a new X.509 certificate object.
pkcs11-tool --module /usr/lib/ --login --list-objects
Using slot 0 with a present token (0x0)
Logging in to "mytoken3".
Please enter User PIN: 
Certificate Object, type = X.509 cert
  ID:         01

3. GPG configuration

  • Configure gpg-agent - add the following to ~/.gnupg/gpg-agent.conf (create the file if it doesn’t exist):
scdaemon-program /usr/bin/gnupg-pkcs11-scd
pinentry-program /usr/bin/pinentry-x11
  • Configure the smart-card daemon - add the following to ~/.gnupg/gnupg-pkcs11-scd.conf (create the file if it doesn’t exist):
providers p1
provider-p1-library /usr/lib/
openpgp-sign <FRIENDLY-HASH>
openpgp-encr <FRIENDLY-HASH>
openpgp-auth <FRIENDLY-HASH>
The emulate-openpgp line is needed for gnupg to be able to work with the token. It can be removed after importing the key into the keyring. If you get the error message "gpg: not an OpenPGP card" then probably you didn't enable openpgp emulation!
  • Get the FRIEDNLY hash of the key - replace the hash above with the one obtained as below:
$ gnupg-pkcs11-scd --daemon
$ gpg-agent --daemon
$ gpg-agent --server
OK Pleased to meet you
gnupg-pkcs11-scd[9701.3922175808]: Listening to socket '/tmp/gnupg-pkcs11-scd.3UDcGR/agent.S'
[. . .]
gnupg-pkcs11-scd[9701]: chan_5 -> S KEY-FRIEDNLY 2DDDBA9C916270E59F69DAFF836FB811EE7B2D12 /C=UK/ST=Some-State/L=London/O=Internet Widgits Pty Ltd on mytoken3
  • Generate the PGP key - Finally we’ll generate the PGP key, sign it and import it into the keyring:
$ sudo gpg2 --card-edit
gpg/card> admin
Admin commands are allowed
gpg/card> geneate
Replace existing keys? (y/N) y
Please specify how long the key should be valid.
[. . .]
gpg: key 8463F3B0 marked as ultimately trusted
public and secret key created and signed.
gpg: selecting openpgp failed: Unsupported certificate
gpg: OpenPGP card not available: Unsupported certificate
On certain GnuPG versions, hthe smart card is only available to the root user and the above error messages would be generated If gpg2 is not run as root!
  • Verify the key has been imported correctly:
$ sudo gpg2 --list-secret-keys
gpg: WARNING: unsafe ownership on configuration file `/home/m/.gnupg/gpg.conf'
sec>  2048R/8463F3B0 2017-07-26 [expires: 2019-07-26]
      Card serial no. = 1111 11111111
uid                  John Snow <>
ssb>  2048R/8463F3B0 2017-07-26 [expires: 2019-07-26]
ssb>  2048R/8463F3B0 2017-07-26 [expires: 2019-07-26]
  • Adjust PIN caching timeout - The key above can now be used a normal PGP key. GnuPG will ask you for your user PIN on all operations. The default cache period for the PIN is infinite, but it can be adjusted in ~/.gnupg/gnupg-pkcs11-scd.conf:
# Pin cache period in seconds; default is infinite.
pin-cache 5

4. Usage

4.1 Sign and verify

  • Sign a document - This will compress the document, sign it and the output will be in binary format. Signing will require the private key, so we’re prompted for the token PIN:
$ echo hello > test
$ sudo gpg2 --output test.sig -u --sign test 

The content of the file is not encrypted. The option would need to be combined with –enrypt flag.

  • Generate a clear text signature:
$ sudo gpg2 --output test.sig -u --clearsign test
$ cat test.sig 
Hash: SHA1
Version: GnuPG v2.0.22 (GNU/Linux)
[. . .]
  • Verify the signature:
$ sudo gpg2 --verify test.sig 
gpg: WARNING: unsafe ownership on configuration file `/home/m/.gnupg/gpg.conf'
gpg: Signature made Wed 26 Jul 2017 04:19:48 PM BST using RSA key ID 8463F3B0
gpg: Good signature from "John Snow <>"
  • Verify the signature and recover the document:
$ sudo gpg2 --output test.out --decrypt test.sig
  • Sign with a detached signature - Remember, in this case you’ll need both the original document and the detached signature in order to verify it!
$ sudo gpg2 --output test.sig -u --detach-sig test

4.2 Encrypt and decrypt

  • Encrypt a file for the user using his public key - the token is obviously not required at this point:
$ sudo gpg2 --output test.pgp --encrypt --armour --recipient test
$ cat test.pgp 
Version: GnuPG v1
[. . .]
  • Decrypt using private key - token PIN IS needed now:
$ sudo gpg2 --output test.plain --decrypt test.pgp

4.3 Export and import keys

  • Exporting keys - If you want to use the PGP key on a different machine, you can export it, then import it in another key chain. Of course, you’ll need the same token to use it:
$ sudo gpg --armor --export >
$ sudo gpg --armor --export-secret-keys > my.sec
  • Import the private key:
$ sudo gpg2 --import my.sec


Smart-card daemon security

All communication between components is currently unprotected and in plain text (that’s how the Assuan protocol operates). It is trivial to trace (using e.g. the strace(1) program) individual components (e.g. pinentry) and steal sensitive data (such as the smart-card PIN) or even change it (e.g. the hash to be signed) (gnupg-pkcs11-scd man page)


Congratulations for reading that far!

There are a lot more things we can do with an eToken and some of these will hopefully be materialised in other tutorials. For example we can integrate it with Thunderbird in order to sign and encrypt emails, with PAM for user login, use it for SSH authentication and of course VPN.