当前位置: 首页 > 知识库问答 >
问题:

用BouncyCastle验证ECDSA签名

武嘉祥
2023-03-14

我应该如何更改A方法?任何想法都是好的。提前谢谢。

using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Nist;
using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Math.EC;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities.Encoders;
using System;
using System.Linq;
using System.Security.Cryptography;
using System.Text;

namespace TestMe
{
    class Program
    {

        public static byte[] HexStringToByteArray(string Hex)
        {
            byte[] Bytes = new byte[Hex.Length / 2];
            int[] HexValue = new int[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
                                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x0B, 0x0C, 0x0D,
                                 0x0E, 0x0F };

            for (int x = 0, i = 0; i < Hex.Length; i += 2, x += 1)
            {
                Bytes[x] = (byte)(HexValue[Char.ToUpper(Hex[i + 0]) - '0'] << 4 |
                                  HexValue[Char.ToUpper(Hex[i + 1]) - '0']);
            }

            return Bytes;
        }

        static void Main(string[] args)
        {
            String sig
                = "e1f5cecccedfe5228d9331098e84b69a0675cdd9ac066ecfada7fea761f52a4cde902a0abd362883127230326fb556af14e894d39a3e14437aaa4134a3476c84";

            String msg = "00000000dcb320137ddd6f825660750ab655219fad66951c64f0420be8ac902975197ed2b0da54cd3d502d34dd04c8d74b2958a0b8792ae4730df6d25a6969bcad9f93a7d6229e5a0100000017cf5242732bba21a0b0e7dad7102cf7bdb2c8d7a665045816a886d7";
            String pub = "b679e27513e2fff8fdeb54409c242776f3517f370440d26885de574a0b0e5309a9de4ea055b0bf302d9f00875f80e28cd29bb95a48aa53746d7de9465123dbb7";


            A(HexStringToByteArray(msg), HexStringToByteArray(sig), HexStringToByteArray(pub));
            B(HexStringToByteArray(msg), HexStringToByteArray(sig), HexStringToByteArray(pub));

        }

        //incorrect
        static void A(byte[] message, byte[] signature, byte[] pubkey)
        {            
            BigInteger x = new BigInteger(1, pubkey.Take(32).ToArray());
            BigInteger y = new BigInteger(1, pubkey.Skip(32).ToArray());

            X9ECParameters ecParams = NistNamedCurves.GetByName("P-256");
            ECDomainParameters domainParameters = new ECDomainParameters(ecParams.Curve, ecParams.G, ecParams.N, ecParams.H, ecParams.GetSeed());
            var G = ecParams.G;
            Org.BouncyCastle.Math.EC.ECCurve curve = ecParams.Curve;
            Org.BouncyCastle.Math.EC.ECPoint q = curve.CreatePoint(x, y);

            ECPublicKeyParameters pubkeyParam = new ECPublicKeyParameters(q, domainParameters);

            var verifier = SignerUtilities.GetSigner("SHA-256withECDSA");
            verifier.Init(false, pubkeyParam);
            verifier.BlockUpdate(message, 0, message.Length);
            bool result = verifier.VerifySignature(signature);

            Console.WriteLine("result: "  + result);
        }


        // correct
        static void B(byte[] message, byte[] signature, byte[] pubkey)
        {
            var Q = new System.Security.Cryptography.ECPoint();
            var param = new ECParameters();
            Q.X = pubkey.Take(32).ToArray();
            Q.Y = pubkey.Skip(32).ToArray();
            param.Curve = System.Security.Cryptography.ECCurve.NamedCurves.nistP256;
            param.Q = Q;            

            var ecdsa = ECDsa.Create(param);
            bool result = ecdsa.VerifyData(message, signature, HashAlgorithmName.SHA256);
            Console.WriteLine("result: " + result);
        }


    }
}

共有1个答案

唐麒
2023-03-14

您验证与bouncy castle签名的代码是正确的。问题是签名格式的。

ECDSA签名基本上是两个数字,通常称为RS。在示例中的签名中,这两个数字只是连接在一起的。每个都是32字节,所以您的签名是64字节。

这种格式(串联的数字)是.NET api所期望的,但不是Bouncy Castle所期望的。Bouncy Castle期望签名是DER编码的(就像规范规定的那样)。

// expected format is SEQUENCE {INTEGER r, INTEGER s}
var derSignature = new DerSequence(
    // first 32 bytes is "r" number
    new DerInteger(new BigInteger(1, signature.Take(32).ToArray())),
    // last 32 bytes is "s" number
    new DerInteger(new BigInteger(1, signature.Skip(32).ToArray())))
    .GetDerEncoded();
bool result = verifier.VerifySignature(derSignature);
 类似资料:
  • 现有系统使用Bouncy Castle(.NET)生成签名,我需要使用Microsoft ECDsaCng类验证这些现有签名。 在我尝试用Microsoft类验证签名之前,一切都正常工作,此时它会生成一个异常,说明参数不正确。 有什么想法吗?

  • 下面是Java代码: 然后使用C代码来验证签名 我在想我需要将我的签名编码为hexa,但它并没有解决我的问题。我已经使用crypto编写了一个c版本的符号方法,并且已经验证过了。所以为什么当我使用java代码时,签名没有得到验证。谢谢

  • 下面是我的场景--我从条形码中读取数据,并将其转换为纯文本。本文是条码数据+数字签名的结合。数字签名附加在末尾,使我能够分离出实际数据和数字签名数据。数字签名数据使用sha256哈希-用户将公钥作为windows证书文件()发送给我。 所需实现:-需要从证书中提取公钥,并根据提供的条形码数据和数字签名验证公钥。 问题:

  • 问题内容: 我已经测试了一种解决方案,可以验证ECDSA签名如何从EC公共密钥字节中获取PublicKey对象?,该签名可以完美地处理给定的数据。 这是数据: 这是代码(显示 true ): 当我将签名和数据更改为来自已实施系统的示例输入时,就会出现我的问题: 新数据输出此错误: 我认为问题出在 安全消息 附带的签名上,因为: 密钥对的长度和格式与示例相同。并且是正确的,因为它来自对消息进行签名的

  • 我使用OpenSSL(在C中)对文本进行签名,但是我的Java程序并不总是验证签名的消息(只有大约1/5得到验证)。有趣的是,https://kjur.github.io/jsrsasign/sample/sample-ecdsa.html没有证实其中任何一个: 曲线名称:secp256k1签名算法:SHA256with ECDSA 私钥 密钥 失败: 成功: 爪哇 C.

  • 我想创建一个签名并使用openssl验证它。我想有我的签名的十六进制输出。 这是我的密码 我得到这个错误: 如果我在创建签名的过程中删除了-hex,它就可以工作了。