使用 .NET 库 ECDsaCng 验证 BouncyCastle ECDsa 签名

2024-03-23

现有系统使用 Bouncy Castle (.NET) 生成签名,我需要使用 Microsoft ECDsaCng 类验证这些现有签名。

考虑以下尝试执行此操作的代码:

   public static void InterchangeTest()
{
    //AsymmetricCipherKeyPair bKeyPair_0 = Crypto.GenerateEcdsaKey();
    String sPassPhrase = "bob is your uncle";
    byte[] bPassPhrase = new UTF8Encoding(false).GetBytes(sPassPhrase);

    int SaltBitSize = 128;
    int EcdsaBitLength = 521;

    byte[] bSalt = new byte[SaltBitSize / 8];
    new SecureRandom().NextBytes(bSalt);

    if (EcdsaBitLength != 192 && EcdsaBitLength != 256 && EcdsaBitLength != 521)
    {
        throw new ArgumentException("Invalid EcdsaBitLength length () " + EcdsaBitLength + " ECDSA supports 192, 256, and 521 bit lengths.");
    }

    string curveName = "P-" + EcdsaBitLength.ToString();
    X9ECParameters ecP = NistNamedCurves.GetByName(curveName);
    ECDomainParameters ecSpec = new ECDomainParameters(ecP.Curve, ecP.G, ecP.N, ecP.H, ecP.GetSeed());
    IAsymmetricCipherKeyPairGenerator g = GeneratorUtilities.GetKeyPairGenerator("ECDH");
    g.Init(new ECKeyGenerationParameters(ecSpec, new SecureRandom()));
    AsymmetricCipherKeyPair aKeyPair = g.GenerateKeyPair();

    ECPrivateKeyParameters mPrivateKey = (ECPrivateKeyParameters)aKeyPair.Private;
    ECPublicKeyParameters mPublicKey = (ECPublicKeyParameters)aKeyPair.Public;

    byte[] bPrivateKey = ((ECPrivateKeyParameters)aKeyPair.Private).D.ToByteArray();

    String SignerName = "SHA-256withECDSA";
    ISigner bSigner = SignerUtilities.GetSigner(SignerName);
    bSigner.Init(true, aKeyPair.Private);
    bSigner.BlockUpdate(bPassPhrase, 0, bPassPhrase.Length);
    byte[] bouncySignature = bSigner.GenerateSignature();

    ISigner bVerifier = SignerUtilities.GetSigner(SignerName);
    bVerifier.Init(false, aKeyPair.Public);
    bVerifier.BlockUpdate(bPassPhrase, 0, bPassPhrase.Length);
    bool passed = bVerifier.VerifySignature(bouncySignature);
    Console.WriteLine("Verified with Bouncy: " + passed);

    var xmlImport = "<ECDSAKeyValue xmlns='http://www.w3.org/2001/04/xmldsig-more#'>\n"
    + "  <DomainParameters>\n"
    + "    <NamedCurve URN='urn:oid:1.3.132.0.35' />\n"
    + "  </DomainParameters >\n"
    + "   <PublicKey >\n"
    + "     <X Value='" + ((ECPublicKeyParameters)aKeyPair.Public).Q.X.ToBigInteger().ToString() + "' xsi:type='PrimeFieldElemType' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' />\n"
    + "     <Y Value='" + ((ECPublicKeyParameters)aKeyPair.Public).Q.Y.ToBigInteger().ToString() + "' xsi:type='PrimeFieldElemType' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' />\n"
    + "  </PublicKey >\n"
    + " </ECDSAKeyValue>";

    //using (StreamWriter outputFile = new StreamWriter(@"C:\Dev\x2.txt"))
    //{
    //    outputFile.WriteLine(xmlImport);
    //}

    ECDsaCng eccImporter = new ECDsaCng();
    eccImporter.FromXmlString(xmlImport, ECKeyXmlFormat.Rfc4050);

    Console.WriteLine("hash algorithm = " + eccImporter.HashAlgorithm + " Probably " + CngAlgorithm.Sha256);
    Console.WriteLine("Signature algorithm = " + eccImporter.SignatureAlgorithm + " Probably ECDsa");
    Console.WriteLine("After import, key size = " + eccImporter.KeySize + " probably 521");

    try
    {
        if (eccImporter.VerifyData(bPassPhrase, bouncySignature))
        {
            Console.WriteLine("Verified the signature from bouncy castle using .NET");
        }
    }
    catch (CryptographicException e)
    {
        // "The parameter is incorrect"
        Console.WriteLine("Did not verify bouncy signature with .NET because: " + e.Message);
    }


    CngKey msKey = CngKey.Create(CngAlgorithm.ECDsaP521, null, new CngKeyCreationParameters { ExportPolicy = CngExportPolicies.AllowPlaintextArchiving });
    ECDsaCng ms_ecdsaCNG = new ECDsaCng(msKey);

    String xmlExport = ms_ecdsaCNG.ToXmlString(ECKeyXmlFormat.Rfc4050);

    eccImporter = new ECDsaCng();
    eccImporter.FromXmlString(xmlExport, ECKeyXmlFormat.Rfc4050);

    byte[] ms_SignedData = ms_ecdsaCNG.SignData(bPassPhrase);
    Console.WriteLine("Verify .NET signature with .NET: " + ms_ecdsaCNG.VerifyData(bPassPhrase, ms_SignedData));
    Console.WriteLine("Verify .NET signature with imported .NET: " + eccImporter.VerifyData(bPassPhrase, ms_SignedData));

    //Console.WriteLine();
    //Console.WriteLine(xmlExport);
    //Console.WriteLine();

}

一切正常,直到我尝试使用 Microsoft 类验证签名,此时它会生成一个异常,指出参数不正确。

有什么想法吗?


马滕·博德维斯是正确的。我的问题是签名是使用 BouncyCastly 使用 ASN.1/DER 格式进行编码的。 MS 使用较小的格式(我认为是 IEEE P-1393)。因此,我用 C# 编写了这个小例程来转换签名。

public static byte[] ConvertDerToP1393(byte[] data)
{
    byte[] b = new byte[132];
    int totalLength = data[1];
    int n = 0;
    int offset = 4;
    int thisLength = data[offset++];
    if (data[offset] == 0)  {
        // Negative number!
        ++offset;
        --thisLength;
    }
    for (int i= thisLength; i < 66; ++i) {
        b[n++] = 0;
    }
    if (thisLength > 66) {
        System.Console.WriteLine("BAD, first number is too big! " + thisLength);
    } else {
        for (int i = 0; i < thisLength; ++i) {
            b[n++] = data[offset++];
        }
    }
    ++offset;
    thisLength = data[offset++];

    for (int i = thisLength; i < 66; ++i){
        b[n++] = 0;
    }
    if (thisLength > 66) {
        System.Console.WriteLine("BAD, second number is too big! " + thisLength);
    } else {
        for (int i = 0; i < thisLength; ++i) {
            b[n++] = data[offset++];
        }
    }
    return b;
}

虽然我只做了有限的测试,但代码已经与我的测试配合使用了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 .NET 库 ECDsaCng 验证 BouncyCastle ECDsa 签名 的相关文章

  • 将字符串作为 PChar 从 CSharp 传递到 Delphi DLL

    我正在尝试将字符串从 C 传递到 Delphi 构建的 DLL Delphi DLL 需要 PChar 这是Delphi导出 procedure DLL Message Location PChar AIntValue integer st
  • 如何从 Qt 应用程序通过 ODBC 连接到 MySQL 数据库?

    我有一个新安装的 MySQL 服务器 它监听 localhost 3306 从 Qt 应用程序连接到它的正确方法是什么 原来我需要将MySQL添加到ODBC数据源 我在遵循这个视频教程后做到了这一点 https youtu be K3GZi
  • C# 无法捕获 SerializationException

    我的程序在加载序列化文件的部分遇到问题 如果文件无法反序列化 我希望很好地失败 但由于某种原因 我的程序将中断而不是进入 catch 子句 这是我的代码 using FileStream fs new FileStream openFile
  • ASP.NET - 在 RenderContent 调用中将事件处理程序添加到 Repeater 内的 LinkBut​​ton

    我有一个加载自定义用户控件的 Sharepoint WebPart 用户控件包含一个 Repeater 而 Repeater 又包含多个 LinkBut ton 在 Web 部件的 RenderContent 调用中 我有一些用于添加事件处
  • ContentDialog 未与 UWP 中心对齐

    据我所知 ContentDialog的默认行为应该是使其在 PC 上居中并在移动设备上与顶部对齐 但就我而言 即使在 PC 上我也将其与顶部对齐 但我不明白发生了什么 我正在使用代码隐藏来创建它 这是我正在使用的代码片段 Creates t
  • Monotouch全局异常处理

    我在野外发现了一只令人讨厌的虫子 但我无法确定它的具体情况 有没有办法拥有全局 Try Catch 块 或者有办法处理 Monotouch 中未处理的任何异常 我可以包起来吗UIApplication Main args 在 try cat
  • 如何自定义 Google 测试失败消息?

    我编写了一个如下所示的 Google 测试 它将一些计算值与 CSV 文件中预期存储的值进行比较 class SampleTest public testing Test public void setupFile const std st
  • C# 枚举到字符串自动转换?

    是否可以让编译器自动将我的 Enum 值转换为字符串 这样我就可以避免每次都显式调用 ToString 方法 这是我想做的一个例子 enum Rank A B C Rank myRank Rank A string myString Ran
  • 我可以将 UseCSharpNullComparisonBehavior 用于单个查询吗?

    我有一个查询 该查询曾经是存储过程 现已转换为 EF 查询 现在已经超时了 使用 SQL Profiler 我可以看到生成的 SQL 的唯一区别是 EF 转变的新行为entity Property value into entity Pro
  • DataGridView 行背景颜色没有改变

    我想根据加载时的特定条件更改 DGV 行的背景颜色 即使在 Windows 窗体中也是如此 但我看不到任何 DGV 行的颜色有任何变化 谁能告诉我如何解决这个问题 private void frmSecondaryPumps Load ob
  • 如何在 C# 中更改公共 IP 地址

    我正在创建一个 C winform 应用程序 我想在其中更改公共 IP 地址 而不是像 Hotspot Shield ZenMate OpenVPN 等那样更改 IPv4 地址 我已经检查了以下链接 但没有找到足够的帮助 所以我发布了这个问
  • 从 DataRow 单元格解析 int [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 如何从 DataRow 单元格解析 int 值 Int32 Parse item QuestionId ToString 这段代码可以工作 但看
  • Type.GetInterfaces() 仅适用于声明的接口

    首先 像这样的问题有很多 也许有些OP甚至在问同样的问题 问题是这些问题的答案 无论是否接受 都没有真正回答这个问题 至少我找不到 如何确定类直接声明的接口 而不是由父级或声明的接口继承的接口 e g interface I interfa
  • C++ 中是否有与 PHP 的explode() 函数等效的函数? [复制]

    这个问题在这里已经有答案了 可能的重复 在 C 中分割字符串 https stackoverflow com questions 236129 splitting a string in c 在 PHP 中 explode 函数将获取一个字
  • 连接到没有元数据的网络服务

    我想连接到此网络服务 https training api temando com schema 2009 06 server wsdl https training api temando com schema 2009 06 serve
  • 如何将System.Windows dll添加到Visual Studio 2010 Express?

    我正在开发一个小型应用程序C and VS2010 as IDE with NET框架4 我想用CaptureSource类以便从笔记本电脑的网络摄像头捕获视频 为此我需要添加一个命名空间System Windows DependencyO
  • C 变量声明的效率 [重复]

    这个问题在这里已经有答案了 例如 在 C 中声明一个变量需要多长时间int x or unsigned long long var 我想知道它是否会让我的代码在类似的事情中更快 for conditions int var 0 code 这
  • “1个未解决的外部”C++

    我已经检查了所有文件之间的连接以及类和函数定义 但每次我尝试运行我的程序时 它都会阻止我并告诉我它有 1 个未解析的外部 该程序应该打开多个文件 一个 学生 文件和一个 成绩 文件 从中读取数据 然后使用 查询文件 来查找数据 找到查询中要
  • 从脚本启用/禁用 GameObject 组件 [Unity3D]

    我需要获取一个脚本中设置的布尔值 放入名为 bouclier 的变量 以启用或禁用游戏对象 该变量位于游戏对象 Player 中 此处右下角 我需要启用或禁用这个游戏对象 Bouclier01 为此 我将脚本附加到游戏对象 Bouclier
  • 实体框架代码首次日期字段创建

    我正在使用实体框架代码优先方法来创建我的数据库表 下面的代码 创建一个DATETIME数据库中的列 但我想创建一个DATE柱子 DataType DataType Date DisplayFormatAttribute ApplyForma

随机推荐