I have a Yubikey Neo and is running GPGTools (GnuPG/MacGPG2 2.0.28) on OS X (10.11.2). I have generated a master key with SC abilities and separate signing and encryption keys which I have moved to the Yubikey via the keytocard command. These are done on a separate offline computer.

On my day to day computer, I have only imported my public key. When I insert my Yubikey, and run gpg --card-status, as expected it shows two secret subkeys. However, once the Yubikey is removed, I can run gpg --list-secret-keys and it will show both my signing and encrypting secret subkeys. Furthermore, I can gpg --export-secret-key and also reimport them, although these secrets keys are unable to perform any signatures or decrypt any files (again, with the Yubikey removed from the computer). This is very strange behaviour as seems like the computer is reading private keys from the Yubikey and storing it locally (even though these private keys are invalid).

Steps to reproduce:

  1. Start with empty GPG keychain, verify by gpg --list-keys.
  2. Insert Yubikey with subkeys on it, verify these subkeys by gpg --card-status.
  3. Remove the Yubikey.
  4. Run gpg --list-secret-key and the subkeys from the Yubikey will appear.
  5. You may also run gpg --armor --export-secret-key <key> and a private key will be printed (this private key does not seem to be able to perform any actions).

Am I misinterpreting any information?


After the private keys are on the Yubikey, they are not exportable. What you can export are secret key stubs, which practically only say this key is on a smartcard. They were the main method of making the key work on a different computer (with the smartcard), but these days, as there is sufficient information stored about the key, all you need is to use --card-status to fetch the same stub from the hardware key, and import the public key.

You can try to see what information is in the exported stub with

% gpg --list-packets --verbose <exported-stub.bin

# off=1796 ctb=9d tag=7 hlen=3 plen=294
:secret sub key packet:
    version 4, algo 1, created NNNNNNNNN, expires 0
    pkey[0]: [2048 bits]
    pkey[1]: [17 bits]
    gnu-divert-to-card S2K, algo: 0, simple checksum, hash: 0
    serial-number:  <ELIDED>
    keyid: <KEYID>
# off=2093 ctb=89 tag=2 hlen=3 plen=293
:signature packet: algo 1, keyid <KEYID>
    version 4, created NNNNNNNNNN, md5len 0, sigclass 0x18
    digest algo 8, begin of digest 7c 79
    hashed subpkt 2 len 4 (sig created <YYYY-MM-DD>)
    hashed subpkt 27 len 1 (key flags: 20)
    hashed subpkt 9 len 4 (key expires after <TIME>)
    subpkt 16 len 8 (issuer key ID <KEYID>)
    data: [2048 bits]

While it looks like the "secret key sub packet" does have a pkey, but the gnu-diver-to-card entry signifies that there's no secret key present. The signature is the signature of the key, which is to ensure it can be verified with the public key, and does not contain the private key.

Another hint that everything is safe that gpg does not ask for a passphrase to export secret keys in this case.

Update: confirmed via the source that pkey is indeed referring to the public key, not the private key - those are called skeys inside gnupg. A packet containing the passphrase protected skey would look like:

off=557 ctb=9c tag=7 hlen=2 plen=134
:secret sub key packet:
    version 4, algo 22, created NNNNNNNNNN, expires 0
    pkey[0]: [80 bits] ed25519 (
    pkey[1]: [263 bits]
    iter+salt S2K, algo: 7, SHA1 protection, hash: 2, salt: HHHHHHHHHHHHHHHH
    protect count: NNNNNNN (NNN)
    protect IV:  <IV>
 >> skey[2]: [v4 protected] <<
    keyid: <KEYID>

So in conclusion, the private key is safe, the cryptographic content is not exported the way shown above when using a smartcard such as the Yubikey.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.