ECDSA使用Java的公钥和签名在C#中验证签名 [英] ECDSA Verify Signature in C# using public key and signature from Java

查看:126
本文介绍了ECDSA使用Java的公钥和签名在C#中验证签名的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个用Java生成的公钥和签名,我想使用ECDsaCng在C#中进行验证.公用密钥为 MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAExeg15CVOUcspdO0Pm27hPVx50thn0CGk3/3NLl08qcK + 0U7cesOUUwxQetMgtUHrh0lNao5XRAAurh> =

我将其转换为可以由C#ECDsaCng使用的密钥,方法是获取最后64个字节,并在其前面添加0x45、0x43、0x53、0x31等.

签名是使用SHA256在Java中生成的.有趣的是,如果我在此处 https://kjur使用该工具测试签名.github.io/jsrsasign/sample/sample-ecdsa.html ,它说它是有效的签名.

我一直在网上搜寻,但仍然没有喜悦.

代码如下

 静态无效的VerifySignature(){var publicKey ="MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAExeg15CVOUcspdO0Pm27hPVx50thn0CGk3/3NLl08qcK + 0U7cesOUUwxQetMgtUHrh0lNao5XRAAurhcB;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();//4543533120000000c5e835e4254e51cb2974ed0f9b6ee13d5c79d2d867d021a4dffdcd2e5d3ca9c2bed14edc7ac394530c507ad320b541eb87494d6a8e5744002eae1701bb59a68eb//用于在线工具中的测试Debug.WriteLine(ByteArrayToString(publicKeyBytes.TakeLast(65).ToArray()));//04c5e835e4254e51cb2974ed0f9b6ee13d5c79d2d867d021a4dffdcd2e5d3ca9c2bed14edc7ac394530c507ad320b541eb87494d6a8e5744002eae1701b59a68ebvar signature ="MEQCIFNEZQRzIrvr6dtJ4j4HP8nXHSts3w3qsRt8cFXBaOGAAiAJO/EjzCZlNLQSvKBinVHfSvTEmor0dc3YX7FPMnnYCg ==";var signatureBytes = Convert.FromBase64String(signature);//30440220534465047322bbebe9db49e23e073fc9d71d2b6cdf0deab11b7c7055c168e1800220093bf123cc266534b412bca0629d51df4af4c49a8af475cdd85fb14f3279d80avar data = Encoding.UTF8.GetBytes("ABCDEFGH");CngKey cngKey = CngKey.Import(key,CngKeyBlobFormat.EccPublicBlob);ECDsaCng eCDsaCng =新的ECDsaCng(cngKey);bool结果= eCDsaCng.VerifyData(数据,signatureBytes);//结果为假字符串ByteArrayToString(byte [] ba){StringBuilder hex =新的StringBuilder(ba.Length * 2);foreach(ba中的字节b)hex.AppendFormat("{0:x2}",b);返回hex.ToString();}} 

解决方案

原因是不同的格式.Microsoft希望格式为 r | s ,而您的签名是以 ASN.1 -格式指定的(在ECDSA 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();
  }
}


解决方案

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.

这篇关于ECDSA使用Java的公钥和签名在C#中验证签名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆