【问题标题】:C# ECDsaCng.SignData use signature in OpenSSL?C# ECDsaCng.SignData 在 OpenSSL 中使用签名?
【发布时间】:2023-03-02 22:48:01
【问题描述】:

我需要知道什么编码

https://msdn.microsoft.com/en-us/library/bb347054(v=vs.110).aspx

ECDsaCng.SignData Method (Byte[])

默认使用它的字节数组以及如何将其转换为可接受的DER格式

https://www.openssl.org/docs/manmaster/crypto/i2d_ECDSA_SIG.html

这样我就可以使用 ECDSA_do_verify 方法在 OpenSSL 中验证我的 C# 生成的 ECDSA 签名。

我知道它的 SHA1 并且我知道如何加载该摘要,我只是不知道 ECDsaCng.SignData 方法的字节编码是什么,也不知道如何将其转换为 DER 格式,如果我什至需要这样做的话.

【问题讨论】:

  • 您提到了 C# 中的 DSA 和 OpenSSL 中的 ECDSA;您实际尝试使用哪种算法?他们不一样...
  • 啊抱歉,ECDsaCng.SignData Method (Byte[]) 是什么意思..
  • 请注意,对于阅读本文的任何人,正确的函数是 SignHash,因为 ECDSA_do_verify 需要一个已知的摘要,并且 SignData 将使用 .NET 默认值重新散列,这就是给我带来这么多麻烦的原因.有一个使用 C# 密钥的 OpenSSL 验证实现,我在我的个人资料下的一个问题中提出了您可能还想查看的问题。这也可能有帮助:stackoverflow.com/questions/24251336/…
  • 啊,我错过了那个微妙之处;我以为你在使用 [ECDsa.SignData(byte[], HashAlgorithmName)](msdn.microsoft.com/en-us/library/mt591029(v=vs.110).aspx)。您调用的那个使用来自 ECDsaCng.HashAlgorithm 的任何算法。 .net 4.6.1 将 SignData 移至 ECDsa 基类并添加了哈希算法参数。

标签: c# c++ openssl signing ecdsa


【解决方案1】:

ECDSA 签名是值对 (r, s)

Windows CNG 将此作为两个值的串联发出,并且由于 .NET 不会重新解释数据,因此这是事实上的 .NET 格式。 (r 是数组的前半部分,s 是后半部分)

OpenSSL 需要一个 DER 编码的 SEQUENCE(INTEGER(r), INTEGER(s)) 结构。这大致意味着{ 0x30, payload_length, 0x02, r_length, r_bytes[0]...r_bytes[r_length-1], 0x02, s_length, s_bytes[0]...s_bytes[s_length-1] };虽然它比这稍微复杂一些,因为当 r_bytes[0] 或 s_bytes[0] >= 0x80 时需要填充字节(因为这使它显示为负数)。

不幸的是,默认情况下,框架中没有公开通用 DER 编码器。

如果您尝试在 Linux 上运行,则使用 .NET Core 可能会更好,因为 Linux 的 ECDSA 实现 already does 这种数据转换。

【讨论】:

  • 正好是数组的一半吗?即 r 和 s 的大小相等吗?如果不是,我如何确定它(r 或 s)何时开始和结束?
  • 嗯,.NET Core 肯定会将其解释为大小始终相等(因此 blob 应该始终具有偶数长度)。由于 Windows 也没有足够的信息来知道额外(或不足)字节是来自 r 还是 s,所以它们使用严格的输出似乎很合乎逻辑。
【解决方案2】:

这里是TLSSigAPI.cs 使用.Net 生成签名并使用OpenSSL 验证的代码。

也许对你有帮助。

byte[] rawDataHash = SHA256(rawData);
byte[] rawSig = ecdsa.SignHash(rawDataHash);
int halfLength = rawSig.Length / 2;
byte[][] rEncoded = SegmentedEncodeUnsignedInteger(rawSig, 0, halfLength);
byte[][] sEncoded = SegmentedEncodeUnsignedInteger(rawSig, halfLength, halfLength);
List<byte[][]> items = new List<byte[][]>() { rEncoded, sEncoded };
byte[] opensslSig = ConstructSequence(items);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-26
    • 2014-07-27
    • 1970-01-01
    • 2020-06-11
    • 2019-04-30
    相关资源
    最近更新 更多