5

I have a public key and signature generated in Java which I would like to verify in C# using ECDsaCng. The public key is MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAExeg15CVOUcspdO0Pm27hPVx50thn0CGk3/3NLl08qcK+0U7cesOUUwxQetMgtUHrh0lNao5XRAAurhcBtZpo6w==

which I convert into a key that can be used by C# ECDsaCng by taking the last 64 bytes and prepending 0x45, 0x43, 0x53, 0x31,... to it.

The signature is generated in Java using SHA256. Funny thing is if I test the signature using the tool here https://kjur.github.io/jsrsasign/sample/sample-ecdsa.html, it says it is a valid signature.

I have been scouring through the net and still no joy.

Code is as below

static void VerifySignature()
{
  var publicKey = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAExeg15CVOUcspdO0Pm27hPVx50thn0CGk3/3NLl08qcK+0U7cesOUUwxQetMgtUHrh0lNao5XRAAurhcBtZpo6w==";
  byte[] publicKeyBytes = Convert.FromBase64String(publicKey);

  var keyType = new byte[] { 0x45, 0x43, 0x53, 0x31 };
  var keyLength = new byte[] { 0x20, 0x00, 0x00, 0x00 };
  var key = keyType.Concat(keyLength).Concat(publicKeyBytes.TakeLast(64)).ToArray(); // 4543533120000000c5e835e4254e51cb2974ed0f9b6ee13d5c79d2d867d021a4dffdcd2e5d3ca9c2bed14edc7ac394530c507ad320b541eb87494d6a8e5744002eae1701b59a68eb

  // For testing in online tool
  Debug.WriteLine(ByteArrayToString(publicKeyBytes.TakeLast(65).ToArray())); //04c5e835e4254e51cb2974ed0f9b6ee13d5c79d2d867d021a4dffdcd2e5d3ca9c2bed14edc7ac394530c507ad320b541eb87494d6a8e5744002eae1701b59a68eb


  var signature = "MEQCIFNEZQRzIrvr6dtJ4j4HP8nXHSts3w3qsRt8cFXBaOGAAiAJO/EjzCZlNLQSvKBinVHfSvTEmor0dc3YX7FPMnnYCg==";
            var signatureBytes = Convert.FromBase64String(signature); // 30440220534465047322bbebe9db49e23e073fc9d71d2b6cdf0deab11b7c7055c168e1800220093bf123cc266534b412bca0629d51df4af4c49a8af475cdd85fb14f3279d80a

  var data = Encoding.UTF8.GetBytes("ABCDEFGH");

  CngKey cngKey = CngKey.Import(key, CngKeyBlobFormat.EccPublicBlob);
  ECDsaCng eCDsaCng = new ECDsaCng(cngKey);

  bool result = eCDsaCng.VerifyData(data, signatureBytes); // result is false

  string ByteArrayToString(byte[] ba)
  {
    StringBuilder hex = new StringBuilder(ba.Length * 2);
    foreach (byte b in ba)
      hex.AppendFormat("{0:x2}", b);

    return hex.ToString();
  }
}


1 Answer 1

11

The cause is a different format. Microsoft expects the format r|s while your signature is specified in the ASN.1-format (which is explained in the context of ECDSA here):

0x30|b1|0x02|b2|r|0x02|b3|s
b1 = Length of remaining data
b2 = Length of r
b3 = Length of s 

Your signature

30440220534465047322bbebe9db49e23e073fc9d71d2b6cdf0deab11b7c7055c168e1800220093bf123cc266534b412bca0629d51df4af4c49a8af475cdd85fb14f3279d80a

can be separated in the following portions

30 44 02 20 534465047322bbebe9db49e23e073fc9d71d2b6cdf0deab11b7c7055c168e180 02 20 093bf123cc266534b412bca0629d51df4af4c49a8af475cdd85fb14f3279d80a

so that the individual portions can be easily identified:

b1 = 0x44
b2 = 0x20
r  = 0x534465047322bbebe9db49e23e073fc9d71d2b6cdf0deab11b7c7055c168e180 
b3 = 0x20
s  = 0x093bf123cc266534b412bca0629d51df4af4c49a8af475cdd85fb14f3279d80a

Thus

r|s = 534465047322bbebe9db49e23e073fc9d71d2b6cdf0deab11b7c7055c168e180093bf123cc266534b412bca0629d51df4af4c49a8af475cdd85fb14f3279d80a

If you run your code using this format, verification is successful.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.