【问题标题】:Verifying ECDSA signature with Bouncy Castle in C#在 C# 中使用 Bouncy Castle 验证 ECDSA 签名
【发布时间】:2016-10-01 00:52:48
【问题描述】:

当我尝试在 C# 中验证 Bouncy Castle 中的 ECDSA 签名时遇到问题。该代码是从我拥有的 Java 示例中采用的,因此我 100% 确定公钥和签名是正确的。但是 C# 实现总是返回签名无效。我检查了曲线参数,它们是正确的。我尝试使用 DER 和“原始”签名,但它再次不起作用。

谁能发现我做错了什么:

namespace TestECDSA
{
    class Program
    {
    static void Main(string[] args)
    {
        byte[] b = new byte[] { 0x2B, 0xA1, 0x41, 0x00 };

        string pubKey = "044F6D3F294DEA5737F0F46FFEE88A356EED95695DD7E0C27A591E6F6F65962BAF";
        string signature = "AAD03D3D38CE53B673CF8F1C016C8D3B67EA98CBCF72627788368C7C54AA2FC4";

        X9ECParameters curve = SecNamedCurves.GetByName("secp128r1");
        ECDomainParameters curveSpec = new ECDomainParameters(curve.Curve, curve.G, curve.N, curve.H, curve.GetSeed());

        ECPublicKeyParameters key = new ECPublicKeyParameters("ECDSA", curve.Curve.DecodePoint(Hex.Decode(pubKey)), curveSpec);

        ISigner signer = SignerUtilities.GetSigner("NONEwithECDSA");             

        signer.Init(false, key);

        signer.BlockUpdate(b, 0, b.Length);

        if (signer.VerifySignature(derEncodeSignature(Hex.Decode(signature))))
            System.Console.WriteLine("Verified Signature");
        else
            System.Console.WriteLine("Not Verified Signature");
    }

    public static byte[] derEncodeSignature(byte[] signature)
    {
        byte[] encoded = new byte[6 + signature.Length];

        byte[] r = RangeSubset(signature, 0, 16);
        byte[] s = RangeSubset(signature, 16, 16);

        encoded[0] = 0x30;
        encoded[1] = 0x24;
        encoded[2] = 0x02;
        encoded[3] = 0x10;

        encoded[4 + r.Length] = 0x02;
        encoded[5 + r.Length] = 0x10;

        Array.Copy(r, 0, encoded, 4, r.Length);
        Array.Copy(s, 0, encoded, 6 + r.Length, r.Length);

        return encoded;
    }

    public static T[] RangeSubset<T>(T[] array, int startIndex, int length)
    {
        T[] subset = new T[length];
        Array.Copy(array, startIndex, subset, 0, length);
        return subset;
    }
}
}

【问题讨论】:

  • NONEwithECDSA?你确定吗? ECDSA 需要一个哈希值! NONEwithECDSA 我想只有在你自己预先计算的情况下才应该使用。
  • B 包含哈希,所以这是正确的。
  • 4 个字节的哈希?或者那是一个缩短的样本?顺便说一句,secp128r1 位太短(与 64 位对称密钥大小相当)。
  • 您确定 derEncodeSignature 工作正常吗?
  • @dbugger 在我看来,静态密钥大小乍一看还可以。您可以随时将结果粘贴到here

标签: c# encryption bouncycastle ecdsa


【解决方案1】:

您可以像这样使用signer.GenerateSignature(),而不是自己对签名进行DER编码:

        var signerAlgorithm = "SHA256withECDSA";

        ISigner signer = SignerUtilities.GetSigner(signerAlgorithm);
        signer.Init(true, privateSigningKey);
        signer.BlockUpdate(data, 0, data.Length);
        byte[] signature = signer.GenerateSignature();

        return signature;

【讨论】:

    【解决方案2】:

    调试器是对的。 DER 编码错误。有问题的代码应替换为:

        private static byte[] derEncodeSignature(byte[] signature)
        {
            byte[] r = signature.RangeSubset(0, (signature.Length / 2));
            byte[] s = signature.RangeSubset((signature.Length / 2), (signature.Length / 2));
    
            MemoryStream stream = new MemoryStream();
            DerOutputStream der = new DerOutputStream(stream);
    
            Asn1EncodableVector v = new Asn1EncodableVector();
            v.Add(new DerInteger(new BigInteger(1, r)));
            v.Add(new DerInteger(new BigInteger(1, s)));
            der.WriteObject(new DerSequence(v));
    
            return stream.ToArray();
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-12-04
      • 2018-02-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-17
      • 1970-01-01
      相关资源
      最近更新 更多