2

I am following this tutorial to sign data with SHA-256withECDSA.

Using the same private key and message, it generated different signature result every time. The only change I made is return Base64 encoded string instead of Base58

Is it supposed to be the same signature every time?

public static string GetSignature(string privateKey, string message)

{

    var curve = SecNamedCurves.GetByName("secp256k1");

    var domain = new ECDomainParameters(curve.Curve, curve.G, curve.N, curve.H);
    var keyParameters = new

            BC.Crypto.Parameters.ECPrivateKeyParameters(new BC.Math.BigInteger(privateKey),

            domain);

    ISigner signer = SignerUtilities.GetSigner("SHA-256withECDSA");

    signer.Init(true, keyParameters);

    signer.BlockUpdate(Encoding.ASCII.GetBytes(message), 0, Encoding.ASCII.GetBytes(message).Length);

    var signature = signer.GenerateSignature();

    return Convert.ToBase64String(signature);

}

Example result

MEQCIB0rqb8Dbrh+e2akoCVJaUS4tyJYqfRf8vdz/W2fUOomAiB3D2BaMYjwSgKRQyTd/W+YEn+wT0I4dq1hmgBfe/Sh7g==

MEUCIQDsWxG8Zr7MCemgGylAN+Y32qJYuDmqZMpaPwxTKosJ3AIgE3oSsBjcua/aCvfNXiMfcUM9U92p9aRlAIEopw/wvd0=

MEYCIQCjQ0EDHVFhASuUSPnCGjCb0O1sq3Op+aAl01afjIVviQIhAOnGyGN9cKswFn97de0o/Im9Hswo6AdnLhKIZSUcYbDY

MEYCIQCAqcHyhRcbLtuyimJ4XCHvJcz0p0Wd7FgJ1+07sOsC/gIhAKYwlhRv98C/3XeZE1TujkB9qMn2C99GaguJoWng9+2y

MEUCIQD7ObA0n0JpRNQDe+3udpeKGEk79KsrjHsjv/4Wlj2bigIgZERRSQBEN91HTJHqn+prlwSCKUT4AJx061Gi0tv8Xuw=
Bo Hu
  • 327
  • 1
  • 3
  • 13
  • 1
    Possible duplicate of [Different output while using openssl\_sign() in PHP](https://stackoverflow.com/questions/43213932/different-output-while-using-openssl-sign-in-php) – bartonjs Apr 18 '18 at 17:11
  • Short answer from the other question: Different every time is correct. – bartonjs Apr 18 '18 at 17:12

2 Answers2

4

So the answer is: it should be non deterministic - everytime is different

https://en.wikipedia.org/wiki/Nondeterministic_algorithm

Bo Hu
  • 327
  • 1
  • 3
  • 13
0

If you want Deterministic you can try this

public string GetSignature(string privateKey, string message)
{
    var curve = SecNamedCurves.GetByName("secp256k1");
    var domain = new ECDomainParameters(curve.Curve, curve.G, curve.N, curve.H);
    var keyParameters = new ECPrivateKeyParameters(new BigInteger(privateKey, 16), domain);

    var signer = new ECDsaSigner(new HMacDsaKCalculator(new Sha256Digest()));
    signer.Init(true, keyParameters);

    var signature = signer.GenerateSignature(Encoding.UTF8.GetBytes(message));

    var r = signature[0];
    var s = signature[1];

    var otherS = curve.Curve.Order.Subtract(s);

    if (s.CompareTo(otherS) == 1)
    {
        s = otherS;
    }

    var derSignature = new DerSequence
    (
        new DerInteger(new BigInteger(1, r.ToByteArray())), 
        new DerInteger(new BigInteger(1, s.ToByteArray()))
    )
    .GetDerEncoded();

    return Convert(derSignature);
}

public bool VerifySignature(string message, string publicKey, string signature)
{
    var curve = SecNamedCurves.GetByName("secp256k1");
    var domain = new ECDomainParameters(curve.Curve, curve.G, curve.N, curve.H);
    var publicKeyBytes = Convert(publicKey);
    var q = curve.Curve.DecodePoint(publicKeyBytes);
    var keyParameters = new ECPublicKeyParameters(q, domain);

    var verifier = new ECDsaSigner();
    verifier.Init(false, keyParameters);

    Asn1InputStream decoder = new Asn1InputStream(Convert(signature));
    DerInteger r, s;
    try
    {
        DerSequence seq = (DerSequence)decoder.ReadObject();
        r = (DerInteger)seq[0];
        s = (DerInteger)seq[1];
    }
    finally
    {
        decoder.Close();
    }

    var rp = r.PositiveValue;
    var sp = s.PositiveValue;

    return verifier.VerifySignature(Encoding.UTF8.GetBytes(message), rp, sp);
}

public string Convert(byte[] input)
{
    return string.Concat(input.Select(x => x.ToString("x2")));
}

public byte[] Convert(string input)
{
    if (input.StartsWith("0x")) input = input.Remove(0, 2);

    return Enumerable.Range(0, input.Length / 2).Select(x => System.Convert.ToByte(input.Substring(x * 2, 2), 16)).ToArray();
}
Atif Rehman
  • 417
  • 6
  • 6