Skip to content

Encryption with GnuPG 2.3 (RFC4880bis) causes compatibility issues with GnuPG 2.2 #896

@cameronkerrnz

Description

@cameronkerrnz

I'm in the unhappy situation of trying to get my GPG keypair from Windows bind-mounted into a Docker container so I can use ksops (Kustomize-SOPS) on Windows (because kustomize+ksops on Windows is not a happy path, although sops works wonderfully well)

If I take a SOPS encrypted file (encrypted with just GPG; haven't tried anything else), and attempt to decrypt it in a container that has GPG but does not have my keypair, then I get a very unhelpful error message.

root@dafc786e620b:/work# sops --decrypt kustomize/overrides/demo/secrets/secrets.py.sops
Error decrypting tree: Error walking tree: Could not decrypt value: crypto/aes: invalid key size 0

The same command works well from outside the container on Windows where my key material is present (but note that this key is not present on any keyserver, as it was generated just for a demonstration purpose).

With debugging:

root@dafc786e620b:/work# sops --verbose --decrypt kustomize/overrides/demo/secrets/secrets.py.sops
[PGP]    INFO[0000] Decryption succeeded                          fingerprint=6CBBBFF08395F8E19F185780222A65AD721294E8
[SOPS]   INFO[0000] Data key recovered successfully
[SOPS]   DEBU[0000] Decrypting tree
Error decrypting tree: Error walking tree: Could not decrypt value: crypto/aes: invalid key size 0

Testing with just some gpg, I see the problem seems to be there, and makes me think that sops suffers from gpg compatibility issues, particularly when a GPG key was generated on a newer (2.3 in my case) version of GPG, and also used on earlier versions (2.2 in my case)

From Windows (where I generated this keypair), encrypting a simple message to myself:

❯ gpg --version
gpg (GnuPG) 2.3.1
libgcrypt 1.9.3
Copyright (C) 2021 g10 Code GmbH
License GNU GPL-3.0-or-later <https://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Home: C:\Users\kerca54p\AppData\Roaming\gnupg
Supported algorithms:
Pubkey: RSA, ELG, DSA, ECDH, ECDSA, EDDSA
Cipher: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH,
        CAMELLIA128, CAMELLIA192, CAMELLIA256
AEAD: EAX, OCB
Hash: SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224
Compression: Uncompressed, ZIP, ZLIB, BZIP2

❯ gpg -k
C:\Users\kerca54p\AppData\Roaming\gnupg\pubring.kbx
---------------------------------------------------
pub   ed25519 2021-06-29 [SC]
      6CBBBFF08395F8E19F185780222A65AD721294E8
uid           [ultimate] SOPS Testing (Throwaway key for testing SOPS/KSOPS) <cameron.kerr.nz+sops-testing@gmail.com>
sub   cv25519 2021-06-29 [E]

❯ gpg --encrypt --recipient 6CBBBFF08395F8E19F185780222A65AD721294E8 --verbose --output test.txt.enc test.txt.in
gpg: Note: RFC4880bis features are enabled.
gpg: using subkey 1B5CBE5831039829 instead of primary key 222A65AD721294E8
gpg: using pgp trust model
gpg: This key belongs to us
gpg: reading from 'test.txt.in'
File 'test.txt.enc' exists. Overwrite? (y/N) y
gpg: writing to 'test.txt.enc'
gpg: ECDH/AES256.OCB encrypted for: "1B5CBE5831039829 SOPS Testing (Throwaway key for testing SOPS/KSOPS) <cameron.kerr.nz+sops-testing@gmail.com>"

Decrypting the same, on the same machine (to test the round-trip)

❯ gpg --decrypt --output test.txt.out test.txt.enc
gpg: encrypted with cv25519 key, ID 1B5CBE5831039829, created 2021-06-29
      "SOPS Testing (Throwaway key for testing SOPS/KSOPS) <cameron.kerr.nz+sops-testing@gmail.com>"

I can verify that text.txt.out matches test.txt.in

This very same file text.txt.enc, being in a directory that is bind-mounted into a Debian Buster container with an earlier version of GPG:

root@dafc786e620b:/work# gpg --version
gpg (GnuPG) 2.2.12
libgcrypt 1.8.4
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Home: /root/.gnupg
Supported algorithms:
Pubkey: RSA, ELG, DSA, ECDH, ECDSA, EDDSA
Cipher: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH,
        CAMELLIA128, CAMELLIA192, CAMELLIA256
Hash: SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224
Compression: Uncompressed, ZIP, ZLIB, BZIP2

root@dafc786e620b:/work# gpg --list-secret-keys
/root/.gnupg/pubring.kbx
------------------------
sec   ed25519 2021-06-29 [SC]
      6CBBBFF08395F8E19F185780222A65AD721294E8
uid           [ultimate] SOPS Testing (Throwaway key for testing SOPS/KSOPS) <cameron.kerr.nz+sops-testing@gmail.com>
ssb   cv25519 2021-06-29 [E]

root@dafc786e620b:/work# gpg --decrypt -vvd --output test.txt.out-buster test.txt.enc
# off=0 ctb=84 tag=1 hlen=2 plen=94
:pubkey enc packet: version 3, algo 18, keyid 1B5CBE5831039829
        data: [263 bits]
        data: [392 bits]
gpg: public key is 1B5CBE5831039829
gpg: no running gpg-agent - starting '/usr/bin/gpg-agent'
gpg: waiting for the agent to come up ... (5s)
gpg: connection to agent established
gpg: using subkey 1B5CBE5831039829 instead of primary key 222A65AD721294E8
gpg: pinentry launched (938 curses 1.1.0 /dev/pts/0 xterm -)
gpg: public key encrypted data: good DEK
# off=96 ctb=d4 tag=20 hlen=2 plen=101 new-ctb
:unknown packet: type 20, length 101
dump: 01 09 02 15 1c 24 82 e3  4b a1 f6 2e 99 b5 4a d3  bc 00 56 76 14 05 7c 06
  24: 5d 1b c1 f9 b3 de bf de  88 6c 1f 93 43 03 e9 ac  9e d9 93 c9 40 93 95 16
  48: 3f 3b 90 d6 f4 17 2f ac  5e 3c e5 e9 aa 01 e5 39  a1 19 69 4b d4 2c 95 b0
  72: 25 64 2a cd dc 82 76 65  95 5e 69 14 8d 3f 38 5b  55 b5 4e 4e d3 17 ff e7
  96: 90 61 53 81 b4

A packet tag of 20 seems new (https://datatracker.ietf.org/doc/html/rfc4880#section-4.3 stops at 19), and tag 20 seems to be https://tools.ietf.org/id/draft-ietf-openpgp-rfc4880bis-06.html#rfc.section.5.16, and this would tally with the Note in the output:

gpg: Note: RFC4880bis features are enabled.

If I encrypt a document in GPG 2.2, then I can happily decrypt it in GPG 2.2 and in GPG 2.3. So its not a matter of where the key is created, but the (implicit) settings used at encrypt-time.

Testing this hypothesis in sops, to evaluate whether encryption by sops (with GPG 2.2) will decrypt with the same version of sops (with GPG 2.3), and I can confirm that it does.

So it seems some consideration needs to be given to how sops should encrypt content with regard to compatibility in decryption, as this could easily lock out team members from decrypting content if it gets encrypted by someone with a newer version.

https://www.gnupg.org/documentation/manuals/gnupg/Compliance-Options.html

... path of least resistance might just be to specify '--rfc4880' if calling out to gpg directly? This makes my problem go away.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions