Page MenuHome GnuPG

The warning "lower 3 bits of the secret key are not cleared" keeps showing even cv25519 key was generated by GnuPG
Closed, ResolvedPublic

Description

Sorry for my poor English first, I have some problems when using Curve25519.

I have created a new key pair using default option Curve 25519. It has generated a master ed25519 key (Sign and Certify) and a subkey cv25519 (Encrypt only) automaticly. Exports the key, deletes all private & public keys from GnuPG, imports back, and then I get a message: warning: lower 3 bits of the secret key are not cleared.

I found this warning message was added in T5464. I'm not very clear to understand the detailed working process and algorithm in GnuPG which was talking in T5464, but it seems the warning message shows even the key was exported by GnuPG itself. There are some questions I'm worry about:

  1. When I exporting or importing cv25519 key, does the warning message mean the existing key pair is already "broken"?
  2. Is there any parameters or commands in gpg which can avoid the situation? (for example, clean the lower 3 bits and set the highest bit before exporting or importing)
  3. Is it safe to modify existing private keys manually? (seems difficult, not sure if the secret key file in disk was protected by password)

Below is the output, the key pair is for test and no need to keep secret.

My platform is Windows 11 22H2 and Gpg4win 4.1.0.

Hope this can help, thanks a lot.

> gpg --full-generate-key
gpg (GnuPG) 2.4.0; Copyright (C) 2021 g10 Code GmbH
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Please select what kind of key you want:
   (1) RSA and RSA
   (2) DSA and Elgamal
   (3) DSA (sign only)
   (4) RSA (sign only)
   (9) ECC (sign and encrypt) *default*
  (10) ECC (sign only)
  (14) Existing key from card
Your selection?
Please select which elliptic curve you want:
   (1) Curve 25519 *default*
   (4) NIST P-384
   (6) Brainpool P-256
Your selection?
Please specify how long the key should be valid.
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
Key is valid for? (0) 28
Key expires at 2023-01-27 23:43:58 Taipei Standard Time
Is this correct? (y/N) y

GnuPG needs to construct a user ID to identify your key.

Real name: test
Email address: test@test.com
Comment:
You selected this USER-ID:
    "test <test@test.com>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
gpg: directory 'C:\\Users\\<hidden>\\AppData\\Roaming\\gnupg\\openpgp-revocs.d' created
gpg: revocation certificate stored as 'C:\\Users\\<hidden>\\AppData\\Roaming\\gnupg\\openpgp-revocs.d\\B40B253D65E7B1A6DD596005AD081E365A435428.rev'
public and secret key created and signed.

pub   ed25519 2022-12-30 [SC] [expires: 2023-01-27]
      B40B253D65E7B1A6DD596005AD081E365A435428
uid                      test <test@test.com>
sub   cv25519 2022-12-30 [E] [expires: 2023-01-27]

> gpg --list-secret-keys --keyid-format LONG
gpg: checking the trustdb
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: depth: 0  valid:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 1u
gpg: next trustdb check due at 2023-01-27
C:\Users\<hidden>\AppData\Roaming\gnupg\pubring.kbx
---------------------------------------------
sec   ed25519/AD081E365A435428 2022-12-30 [SC] [expires: 2023-01-27]
      B40B253D65E7B1A6DD596005AD081E365A435428
uid                 [ultimate] test <test@test.com>
ssb   cv25519/BDDF38C10B2D8577 2022-12-30 [E] [expires: 2023-01-27]

> gpg --output test.sec --armor --export-secret-keys B40B253D65E7B1A6DD596005AD081E365A435428

> gpg --delete-secret-keys B40B253D65E7B1A6DD596005AD081E365A435428
gpg (GnuPG) 2.4.0; Copyright (C) 2021 g10 Code GmbH
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.


sec  ed25519/AD081E365A435428 2022-12-30 test <test@test.com>

Delete this key from the keyring? (y/N) y
This is a secret key! - really delete? (y/N) y

> gpg --delete-keys B40B253D65E7B1A6DD596005AD081E365A435428
gpg (GnuPG) 2.4.0; Copyright (C) 2021 g10 Code GmbH
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.


pub  ed25519/AD081E365A435428 2022-12-30 test <test@test.com>

Delete this key from the keyring? (y/N) y

> gpg --list-secret-keys --keyid-format LONG
gpg: checking the trustdb
gpg: no ultimately trusted keys found

> gpg --import test.sec
gpg: key AD081E365A435428: public key "test <test@test.com>" imported
gpg: warning: lower 3 bits of the secret key are not cleared
gpg: key AD081E365A435428: secret key imported
gpg: Total number processed: 1
gpg:               imported: 1
gpg:       secret keys read: 1
gpg:   secret keys imported: 1

> gpg --list-secret-keys --keyid-format LONG
C:\Users\<hidden>\AppData\Roaming\gnupg\pubring.kbx
---------------------------------------------
sec   ed25519/AD081E365A435428 2022-12-30 [SC] [expires: 2023-01-27]
      B40B253D65E7B1A6DD596005AD081E365A435428
uid                 [ unknown] test <test@test.com>
ssb   cv25519/BDDF38C10B2D8577 2022-12-30 [E] [expires: 2023-01-27]

Details

Version
2.4.0

Event Timeline

werner added a project: gnupg24.
gniibe added a subscriber: gniibe.

Sorry, it took time (for me) to understand the issue, as this is not 100%-reproducible bug. And it was not clear (for me) that how passphrase were offered in the interaction, so, I was not possible to see if it's encrypted or not.

The problem is that the fix (which emits the warning) was wrong: rGdbfb7f809b89: gpg: Print a warning when importing a bad cv25519 secret key.
When the private key is encrypted by phassphrase, the secret material may have non-cleared lower 3-bit (7 out of 8 possibility).

To report the lower-3-bit thing to user correctly, it should be gpg-agent to notify gpg about this kind of warning for private key material (and then gpg emits the warning to user).

For simpler change (for now), I am going to add a condition, so that gpg can emit the warning when secret material is not encrypted.

gniibe changed the task status from Open to Testing.Apr 6 2023, 4:35 AM

The fix is in 2.4.1.
It's not perfect fix, but it catches the problem when it's not encrypted secret key.

Hi,i try to reproduce the problem, my platform is linux and gnupg2-2.2.32-3, but i can't find “gpg: warning: lower 3 bits of the secret key are not cleared". Excuse me, is this a platform-specific or version-specific problem, or is it my operation wrong.

[root@localhost gpg]# gpg --list-secret-keys --keyid-format LONG
gpg: checking the trustdb
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: depth: 0  valid:   2  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 2u
gpg: next trustdb check due at 2025-05-26
/root/.gnupg/pubring.kbx
------------------------
sec   ed25519/4155BD7C59DDEEA1 2023-05-27 [SC]
      D880C276FD760905F492AFA84155BD7C59DDEEA1
uid                 [ultimate] zhanga (qwerty) <zhanga@test.com>
ssb   cv25519/3A4597288DE0666C 2023-05-27 [E]

[root@localhost gpg]#  gpg --output zhanga.sec --armor --export-secret-keys D880C276FD760905F492AFA84155BD7C59DDEEA1
[root@localhost gpg]# 
[root@localhost gpg]# gpg --delete-secret-keys D880C276FD760905F492AFA84155BD7C59DDEEA1
gpg (GnuPG) 2.2.32; Copyright (C) 2021 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.


sec  ed25519/4155BD7C59DDEEA1 2023-05-27 zhanga (qwerty) <zhanga@test.com>

Delete this key from the keyring? (y/N) y
This is a secret key! - really delete? (y/N) y
[root@localhost gpg]#                         
[root@localhost gpg]# gpg --delete-keys D880C276FD760905F492AFA84155BD7C59DDEEA1
gpg (GnuPG) 2.2.32; Copyright (C) 2021 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.


pub  ed25519/4155BD7C59DDEEA1 2023-05-27 zhanga (qwerty) <zhanga@test.com>

Delete this key from the keyring? (y/N) y
[root@localhost gpg]#                    
[root@localhost gpg]# 
[root@localhost gpg]# gpg --list-secret-keys --keyid-format LONG
gpg: checking the trustdb
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: depth: 0  valid:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 1u
gpg: next trustdb check due at 2025-05-26
[root@localhost gpg]# gpg --import zhanga.sec 
gpg: key 4155BD7C59DDEEA1: public key "zhanga (qwerty) <zhanga@test.com>" imported
gpg: key 4155BD7C59DDEEA1: secret key imported
gpg: Total number processed: 1
gpg:               imported: 1
gpg:       secret keys read: 1
gpg:   secret keys imported: 1
[root@localhost gpg]#

Hi zhangguangzhi, I think that it's version-specific problem.
I traced the chain and this warning message was added in release 2.3.3 T5565.
The problem should be able to reproduce between 2.3.3 and 2.4.0.

And thanks gniibe! I have tested 2.4.1 several times in this month (including existing and new keys), the warning was never shown again.