Search code examples
c#.netecdsa.net-standard-1.6.net-4.7

ECDSA signature - Is a conclusion to the used key possible?


I noticed that if I used the ECDsa.SignData Method I always get different ECDSA signature.

So I wonder if it is possible to conclude from the ECDSA signature to the used key?

If Alice sends a message to Bob1 and Bob2, can Eve determine without the public from Alice that the signatures are from the same sender?

public static byte[] SignData(KeyPair privateKeyPair, byte[] data)
{
    var ecDsa = ECDsa.Create(ECCurve.NamedCurves.brainpoolP320r1);
    ecDsa.ImportParameters(privateKeyPair.CreateECParameters());
    return ecDsa.SignData(data, HashAlgorithmName.SHA512);
}

public static bool VerifyData(KeyPair signedKeyPair, byte[] data, byte[] signature)
{
    var ecDsa = ECDsa.Create(ECCurve.NamedCurves.brainpoolP320r1);
    ecDsa.ImportParameters(signedKeyPair.CreateECParameters());
    return ecDsa.VerifyData(data,signature, HashAlgorithmName.SHA512);
}

var plainMsg = Encoding.UTF8.GetBytes("Hello World");
var keyPair = BrainpoolKeyGenerator.CreateKeyPair(true);

var signature1 = SignData(keyPair, plainMsg);
var signature2 = SignData(keyPair, plainMsg);

Assert.That(signature1,Is.Not.EquivalentTo(signature2), "Signature #1 and #2 are NOT equal");

Assert.That(VerifyData(keyPair.ExportPublicKey(), plainMsg, signature1), "Signature of #1 is valid");
Assert.That(VerifyData(keyPair.ExportPublicKey(), plainMsg, signature2), "Signature of #2 is valid");

Solution

  • No, having two ECDSA signatures over the same data doesn't reveal if it was signed by the same party twice or two different parties.

    In order to talk about how ECDSA works we need some quick (loosely defined) terms:

    • G, the Generator, is a point on the curve.
      • The public key associated with a private key (d) for a curve is d * G, using curve math we won't talk about here.
      • For brainpoolP320r1 the G value is broken down as x and y in RFC5639, section 3.5.
    • n, the curve Order, is the biggest legal value for d given G.
      • RFC5639 calls this value q, but most everything else calls it n.

    There's a breakdown of ECDSA on Wikipedia, but the gist of the formula is:

    • Create a random number k such that 0 < k < n
    • r is an integer equal to the X coordinate of the EC Point k * G
    • Let z be the message digest interpreted as a number (with some trimming/extension)
    • Let kInv be the inverse of k modulo n (see also the Extended Euclidean Algorithm).
    • Let s be kInv * (z + (r * d)) mod n
    • The signature is (r, s).
      • In .NET the (r, s) value is represented in the IEEE P1363 format, which means the first half is r and the second half is s, their lengths determined by the curve.

    So, the first half of the signature is effectively a random number. Elliptic Curve Cryptography is based on the fact that it's hard to compute Q / G (where Q is the public key, aka a point on the curve), so recovering k from r is hard.

    The second half of the signature (s) is the only part where the signer key is involved, but it gets beat up a lot by k.

    The signature verification algorithm then checks if Q and z' (the verifier's version of z), combined with r and s make a formula balance. If it doesn't, there's no indication of whether it was because the hash/digest was wrong or the public key was wrong.