EdDSA Verification Bug - Clarification on Format 2 Verification Failure
NIIBE Yutaka
gniibe at fsij.org
Fri Jan 16 06:45:56 CET 2026
Hello,
Zachary Fogg wrote:
> thanks for your time. you say you don't see the bug, but did you run my
> test programs? they show the bug.
Your program is wrong. If you have time, please read:
https://lists.gnupg.org/pipermail/gcrypt-devel/2025-October/005982.html
I repeat.
[...]
> // Generate Ed25519 keypair
> err = gcry_sexp_build(&keypair, NULL, "(genkey (ecc (curve Ed25519)))");
Here, the key should have the flags with eddsa (as I wrote last year).
So, for the key generation, it should be like:
err = gcry_sexp_build(&keypair, NULL, "(genkey (ecc (flags eddsa) (curve Ed25519)))");
Ed25519 in libgcrypt is a bit difficult to use. With its history in
libgcrypt, it can be used with ECDSA (!= EdDSA) for some reason, and its
semantics are not well defined other than the code itself. I never know
the real use cases of ECDSA with the curve Ed25519 except examples
within libgcrypt. When using for EdDSA, we need to have the eddsa flag
in its key.
When using a key with no eddsa flag for EdDSA, the behaviour is
undefined. Specifically, when the key is generated with no eddsa flag,
the public key is computed for non-EdDSA use case, it won't work well
with EdDSA.
It could be kind enough if libgcrypt rejected wrong use case, like the
modification of below.
==========================
diff --git a/cipher/ecc.c b/cipher/ecc.c
index 51364b64..74683bf4 100644
--- a/cipher/ecc.c
+++ b/cipher/ecc.c
@@ -1040,6 +1040,12 @@ ecc_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms)
sig_s = mpi_new (0);
if ((ctx.flags & PUBKEY_FLAG_EDDSA))
{
+ if (!(flags & PUBKEY_FLAG_EDDSA) && ec->dialect != ECC_DIALECT_SAFECURVE)
+ {
+ rc = GPG_ERR_INV_FLAG;
+ goto leave;
+ }
+
/* EdDSA requires the public key. */
rc = _gcry_ecc_eddsa_sign (data, ec, sig_r, sig_s, &ctx);
if (!rc)
@@ -1236,6 +1242,12 @@ ecc_verify (gcry_sexp_t s_sig, gcry_sexp_t s_data, gcry_sexp_t s_keyparms)
*/
if ((sigflags & PUBKEY_FLAG_EDDSA))
{
+ if (!(flags & PUBKEY_FLAG_EDDSA) && ec->dialect != ECC_DIALECT_SAFECURVE)
+ {
+ rc = GPG_ERR_INV_FLAG;
+ goto leave;
+ }
+
rc = _gcry_ecc_eddsa_verify (data, ec, sig_r, sig_s, &ctx);
}
else if ((sigflags & PUBKEY_FLAG_GOST))
==========================
... but, I don't know if it's worth to apply.
SEXP is lax format and use of SEXP in libgcrypt is not strict, only
specific use cases of flags and values make sense.
--
More information about the Gcrypt-devel
mailing list