Closed vanitasvitae closed 1 month ago
Update: Some thing that's odd to me: I'm only able to produce "bad" signatures if using the Cleartext Signature Framework. If I generate Inline-signatures or detached signatures at the same time, I'd expect "bad" signatures to show up with the same frequency...
It's doubtful that there are any issues with the low-level ed25519 signing/verification, but I guess we should first exclude that.
BcImplProvider
uses org.bouncycastle.crypto.signers.Ed25519Signer
; you could modify Ed25519Signer.Buffer.generateSignature
to immediately verify all generated signatures:
synchronized byte[] generateSignature(Ed25519PrivateKeyParameters privateKey)
{
byte[] signature = new byte[Ed25519PrivateKeyParameters.SIGNATURE_SIZE];
privateKey.sign(Ed25519.Algorithm.Ed25519, null, buf, 0, count, signature, 0);
// begin check
Ed25519PublicKeyParameters publicKey = privateKey.generatePublicKey();
if (!publicKey.verify(Ed25519.Algorithm.Ed25519, null, buf, 0, count, signature, 0))
{
throw new IllegalStateException();
}
// end check
reset();
return signature;
}
You didn't include the code for (intermittently?) generating "broken signatures", but using the above change during that process should reveal any problems with the low-level verification.
Assuming the low-level is working fine, it will then be a matter of determining which one or more of the input message, signature and/or public key are inconsistent with the signature generation values. Ed25519Signer.Buffer.verifySignature
is a convenient place to capture the values that the PGP verification is sending to the low-level implementation, for comparison with what are appearing in Ed25519Signer.Buffer.generateSignature
.
Awesome, I will use your hints to do some more digging! Thanks!
My bad, I found the issue. I was using the wrong method to update the signature with the salt value. This caused modifications to the salt value in some cases. Dejavu?
Hey! While playing with Ed25519, I noticed that some signatures I generate do not verify - while others which were generated the same way do verify successfully (see
GOOD_SIG
below).First I thought this was an issue during signature generation, but I was able to successfully verify the same signature using both gopenpgp (via gosop) and rpgp (via rsop), so this is an indicator that the signature is good and that the bug is in the verification code.
I was able to isolate a failing signature (
BROKEN_SIG
) and step through the verification process (see test case below).Compared to a "good" signature, in Ed25519.normalizeToNeutralElementVar the return value is false. Digging deeper, it turns out that
F.isZeroVar(p.x)
returns false, while "good" signatures would return true.So my suspicion (which I cannot prove because I'm no cryptographer and not deep enough into the maths) is, that there might be a bug in scalarMultStraus128Var, as for "good" sigs, the final values of
r.x
andr.u
would be zeros, while for the "broken" sig they are non-zero values.What do you think?
Here is a test case: