我需要知道编码
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格式,如果我甚至需要那样做。
答案 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);