C#ECDsaCng.SignData在OpenSSL中使用签名?

问题描述 投票:0回答:2

我需要知道什么编码

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# c++ openssl signing ecdsa
2个回答
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这种数据转换。


0
投票

这是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);
© www.soinside.com 2019 - 2024. All rights reserved.