Page MenuHome GnuPG

Cannot decrypt a message encrypted to a Kyber subkey with AES128
Open, HighPublic

Description

I have added a Kyber768 encryption subkey to my existing primary key. But trying to decrypt a message encrypted to that new subkey yields the following error:

gpg: encrypted with ky768_bp256 key, ID B15C12AEB7588C1F […]
gpg: public key decryption failed: Wrong secret key used
gpg: decryption failed: Wrong secret key used

It seems this is because the session key is a AES128 key, as can be shown when listing the packets of the encrypted message (session key algo: 7):

$ gpg --list-packets test.asc 
gpg: encrypted with ky768_bp256 key, ID B15C12AEB7588C1F […]
gpg: public key decryption failed: Wrong secret key used
gpg: decryption failed: Wrong secret key used
# off=0 ctb=85 tag=1 hlen=3 plen=1195
:pubkey enc packet: version 3, algo 8, keyid B15C12AEB7588C1F
        session key algo: 7
        data: [515 bits]
        data: [8704 bits]
        data: [192 bits]
# off=1198 ctb=d4 tag=20 hlen=2 plen=0 partial new-ctb
:aead encrypted packet: cipher=7 aead=2 cb=16
        length: unknown

while GnuPG is apparently expecting the session key to be a AES256 key – If I force GnuPG to use AES256 as the symmetric algo (--cipher-algo AES256) when encrypting the message, I can decrypt it without issue. (For completeness I also tried forcing it to use a AES192 key – this yields the same “wrong secret key” error.)

The preferences on my existing key (which I have not modified in a while), do place AES128 as the preferred symmetric algorithm, _before_ AES256. If I update those to use the new default preferences (with AES256 as the preferred symmetric algo), then GnuPG will automatically use AES256 by default and decryption will again work without any issue.

So it seems that

A) when encrypting a message to a Kyber key, GnuPG always dutifully selects the symmetric algorithm based on the recipient’s preferences (unless overridden by --cipher-algo), but

B) when decrypting a message encrypted with a Kyber key, GnuPG only expects a AES256 session key and cannot handle a AES128 or AES192 key.

Details

Version
2.5.2

Event Timeline

werner added projects: gnupg26, PQC.
werner added a subscriber: werner.

At gnupg/g10/pubkey-enc.c you will find

if (sk->pubkey_algo == PUBKEY_ALGO_KYBER)
 {
   /* We expect a 32 byte session key.  We should not see this
    * error here because due to the KEM mode the agent_pkdecrypt
    * should have already failed.  */
   if (nframe != 32)
     {
       err = gpg_error (GPG_ERR_WRONG_SECKEY);
       goto leave;
     }
   dek->keylen = nframe;
   dek->algo = enc->d.seskey_algo;

Can you please add a

log_debug ("XXX: keylen=%zu  algo=%d\n", nframe, enc->d.seskey_algo)

Before the leave? I assume the comment above is wrong.

Here you are:

gpg -d test.asc
[... skipping warnings about using a development version and daemons being "older than us"...]
gpg: DBG: XXX: keylen=16  algo=7
gpg: public key decryption failed: Wrong secret key used
gpg: decryption failed: Wrong secret key used

That is what I expected. Meanwhile I re-read the code and history and can tell that the comment is not correct. I wrote it with PQC security level in mind which requires AES256 for the session key as well. However, during the migration phase and as long as --require-pqc-encryption is not enable we should allow an AES-128 session key. This is for the rare case that encryption is also done for non pqc keys which don't have the AES-256 capability set.

Things to do:

  • Allow 16 octet session keys as long as -require-pqc-encryption is not set.
  • If --require-pqc-encryption is not set give a warning here
  • Change the encryption code to only allow 256 bit session keys with Kyber regardless of the preferences, iff --require-pqc-encryption is set.

The latter is not strictly required according to LibrePGP but I think it makes quite some sense. We could as well also encforce AES-256 also without that option.

I wrote it with PQC security level in mind which requires AES256 for the session key as well.

Ah, yes, because the effective key size of symmetric algos is halved if we assume a quantum computer, right? I had completely forgotten about that. ><

So even if GnuPG is made to allow a 128-bit session key, I might as well update my key preferences (which for now I have only done in a “test” setup, not on my real key) to bump AES256 to the top.

Love it! I think I am going to use “post-heffalump crypto” from now on. :D

Change the encryption code to only allow 256 bit session keys with Kyber regardless of the preferences, iff --require-pqc-encryption is set. […] We could as well also encforce AES-256 also without that option.

What if we encrypt to several recipients, only some of them having a Kyber encryption key? Should we still enforce AES-256 in that case regardless of the preferences, and assume that by now everybody should support AES-256?

(I am talking about the case where --require-pqc-encryption is not set. If it is set, the question is moot, as encryption for the recipients that do not have a Kyber key will be impossible anyway.)