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

时间:2016-08-01 15:03:10

标签: c# c++ openssl signing ecdsa

我需要知道编码

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格式,如果我甚至需要那样做。

2 个答案:

答案 0 :(得分: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这种数据转换。

答案 1 :(得分: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);