EdDSA Verification Bug - Clarification on Format 2 Verification Failure

Zachary Fogg zach.fogg at gmail.com
Tue Dec 30 08:30:00 CET 2025


**In-Reply-To:** <response from NIIBE Yutaka on Oct 22, 2025>

Hi NIIBE Yutaka,

Thank you for your response on October 22! I apologize for the delay - I am
new to the list and didn't receive your email until I checked the web
archives today.

## Clarifying the Bug

Your response mentioned using `(flags eddsa)` during key generation, which
is good practice. However, I want to clarify that **my bug report concerns
signature verification, not key generation**.

The issue is that **Format 2 S-expressions can successfully SIGN but cannot
VERIFY** Ed25519 signatures, even when keys are properly generated with the
eddsa flag.

### Reproduction

Here's a minimal test case showing the problem:

```c
// Key generation (with proper eddsa flag as you suggested)
gcry_sexp_t keypair;
gcry_sexp_build(&keypair, NULL, "(genkey (ecc (flags eddsa) (curve
Ed25519)))");
gcry_pk_genkey(&keypair, keypair);

// Extract public/private keys...

// TEST: Sign with Format 2 (what GPG agent uses)
gcry_sexp_t data_sexp;
gcry_sexp_build(&data_sexp, NULL,
    "(data (flags eddsa) (hash-algo sha512) (value %b))",
    32, message_hash);

gcry_sexp_t sig;
gcry_pk_sign(&sig, data_sexp, private_key);  // ✓ SUCCEEDS

// TEST: Verify the same signature
gcry_error_t err = gcry_pk_verify(sig, data_sexp, public_key);
// ✗ FAILS with "Bad signature"
```

### Why This Matters

1. **GPG agent uses Format 2** - The failing format `(data (flags eddsa)
(hash-algo sha512) (value %b))` is what GPG agent generates (see
`gnupg/agent/pksign.c`)

2. **GPG agent skips EdDSA verification** - Line 420-425 of
`agent/pksign.c` shows verification is only performed for RSA, not EdDSA.
This hid the bug.

3. **Real-world impact** - Applications using libgcrypt to verify GPG agent
signatures will fail, even though the signatures are valid.

### Root Cause

The bug appears to be in `libgcrypt/cipher/ecc-eddsa.c` where the
`PUBKEY_FLAG_PREHASH` flag causes different hash computations during
signing vs verification:

- **During signing:** Hash is computed once and reused
- **During verification:** Hash is computed differently
- **Result:** Verification fails despite valid signature

### Test Results

| Format | Sign | Verify | Notes |
|--------|------|--------|-------|
| Format 1: `(data (value %b))` | ❌ | N/A | Expected - no hash-algo |
| Format 2: `(data (flags eddsa) (hash-algo sha512) (value %b))` | ✅ | ❌ |
**THE BUG** |
| Format 3: `(data (value %b))` | ✅ | ✅ | Works, but not what GPG uses |

### Proposed Fix

The PUBKEY_FLAG_PREHASH logic needs to be consistent between signing and
verification paths.

## Questions

1. Can you confirm this is a genuine bug in libgcrypt's verification logic?
2. Should I open a formal bug in the dev.gnupg.org tracker?
3. Would a patch fixing the PUBKEY_FLAG_PREHASH handling be acceptable?

Thanks,
Zachary Fogg

---

## Additional Context

- **Issue tracking:** https://github.com/zfogg/ascii-chat/issues/92
- **Test programs:** Available on request
- **Versions tested:** libgcrypt 1.11.2, GnuPG 2.4.8
- **Use case:** Terminal video chat app (ascii-chat) authenticating users
via GitHub GPG keys
-- 

--
🐨 ẔƑ 👾
zfo.gg/
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.gnupg.org/pipermail/gcrypt-devel/attachments/20251230/4307fd02/attachment.html>


More information about the Gcrypt-devel mailing list