Page MenuHome GnuPG

GnuPG: Deletion of kyber key fails
Open, NormalPublic

Description

Deleting a kyber key currently fails with the error "Ungültiger Wert":

C:\Users\g10>gpg --version
gpg (GnuPG) 2.5.13
libgcrypt 1.11.2

C:\Users\g10>gpg --full-gen-key
[... 16: ecc and kyber ...]
pub   brainpoolP256r1 2025-10-27 [SC]
      20C8E01A8C25E1F9367DBBCD5BD18ED025C98841
uid                      kyber
sub   ky768_bp256 2025-10-27 [E]
      13E62ACECD2692E4A4461A9FE21562E30709C99E106FDD476F88B0FDAC8AB23A

C:\Users\g10>gpg -v --delete-secret-and-public-keys 20C8E01A8C25E1F9367DBBCD5BD18ED025C98841
[...]
gpg: enabled compatibility flags:

sec  brainpoolP256r1/5BD18ED025C98841 2025-10-27 kyber

Diesen Schlüssel aus dem Schlüsselbund löschen? (j/N) j
Dies ist ein privater Schlüssel! - Wirklich löschen? (j/N) j
gpg: pinentry launched (4868 qt 1.3.2 - - - - 0/0 -)
gpg: Fehler beim Löschen des privaten Unterschlüssels: Ungültiger Wert
gpg: 20C8E01A8C25E1F9367DBBCD5BD18ED025C98841: delete key failed: Ungültiger Wert

Details

Version
gpg4win-5.0.0-beta395 @ win11

Event Timeline

timegrid created this object with edit policy "Contributor (Project)".
werner edited projects, added gnupg26, PQC, Bug Report; removed gnupg.

Workaround is to use --with-keygrip and delete both <keygrip>.key files. Problem here is that one part may be on a smartcard or one part might be shared (although not allowed) with other keys.

Note that currently Kleopatra (gpg4win 5 beta) fails to delete the key, which might impact other operations. I'm currently trying to figure out, if some other bugs/quirks are a subsequent error or not.

gniibe mentioned this in Unknown Object (Maniphest Task).Mon, Feb 9, 7:37 AM

Here is an attempt of mine this week:

diff --git a/g10/call-agent.c b/g10/call-agent.c
index 5e13a3e52..8949fad17 100644
--- a/g10/call-agent.c
+++ b/g10/call-agent.c
@@ -3290,13 +3290,14 @@ confirm_status_cb (void *opaque, const char *line)
    message.  If FORCE is true the agent is advised not to ask for
    confirmation. */
 gpg_error_t
-agent_delete_key (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
+agent_delete_key (ctrl_t ctrl, const char *keygrip, const char *desc,
                   int force)
 {
   gpg_error_t err;
   char line[ASSUAN_LINELENGTH];
   struct default_inq_parm_s dfltparm;
   struct confirm_parm_s confirm_parm;
+  const char *keygrip2 = NULL;
 
   memset (&confirm_parm, 0, sizeof confirm_parm);
   memset (&dfltparm, 0, sizeof dfltparm);
@@ -3308,9 +3309,22 @@ agent_delete_key (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
     return err;
   dfltparm.ctx = agent_ctx;
 
-  if (!hexkeygrip || strlen (hexkeygrip) != 40)
+  if (!keygrip)
     return gpg_error (GPG_ERR_INV_VALUE);
 
+  /* Parse the keygrip in case of a composite key.  */
+  keygrip2 = strchr (keygrip, ',');
+  if (!keygrip2)
+    keygrip2 = keygrip + strlen (keygrip);
+  if (keygrip2 - keygrip != 40)
+    return gpg_error (GPG_ERR_INV_VALUE);
+  if (*keygrip2)
+    {
+      keygrip2++;
+      if (strlen (keygrip2) != 40)
+        return gpg_error (GPG_ERR_INV_VALUE);
+    }
+
   if (desc)
     {
       snprintf (line, DIM(line), "SETKEYDESC %s", desc);
@@ -3320,12 +3334,19 @@ agent_delete_key (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
         return err;
     }
 
-  /* FIXME: Shall we add support to DELETE_KEY for composite keys?  */
-  snprintf (line, DIM(line), "DELETE_KEY%s %s",
-            force? " --force":"", hexkeygrip);
+  snprintf (line, DIM(line), "DELETE_KEY%s %.40s",
+            force? " --force":"", keygrip);
   err = assuan_transact (agent_ctx, line, NULL, NULL,
                          default_inq_cb, &dfltparm,
                          confirm_status_cb, &confirm_parm);
+  if (!err && *keygrip2)
+    {
+      snprintf (line, DIM(line), "DELETE_KEY%s %.40s",
+                force? " --force":"", keygrip2);
+      err = assuan_transact (agent_ctx, line, NULL, NULL,
+                             default_inq_cb, &dfltparm,
+                             confirm_status_cb, &confirm_parm);
+    }
   xfree (confirm_parm.desc);
   xfree (confirm_parm.ok);
   xfree (confirm_parm.notok);