UWP ECDSP签名
我想用这段代码制作一个ECDSA签名:
AsymmetricKeyAlgorithmProvider objAsymmAlgProv = AsymmetricKeyAlgorithmProvider.OpenAlgorithm(AsymmetricAlgorithmNames.EcdsaSha256); CryptographicKey keypair = objAsymmAlgProv.CreateKeyPairWithCurveName(EccCurveNames.SecP256r1); BinaryStringEncoding encoding = BinaryStringEncoding.Utf8; buffMsg = CryptographicBuffer.ConvertStringToBinary("Test Message", encoding); IBuffer buffSIG = CryptographicEngine.Sign(keypair, buffMsg); byte [] SignByteArray = buffSIG.ToArray(); bool res = CryptographicEngine.VerifySignature(keypair, buffMsg, buffSIG);
VerifySignature
始终返回true,这没关系。
但我在签名方面遇到了一些问题。
为什么签名长度( SignByteArray
)已修复? (0x40字节)。
为什么SignByteArray [0]
和SignByteArray [2]
值不正确? (我认为它们应该是0x30和0x02)
我期待像https://kjur.github.io/jsrsasign/sample-ecdsa.html这样的东西
ECDSA规范最后确定该对( r
, s
)是签名。 它忽略的是表明应该如何写下来。
Windows和.NET使用IEEE(P)1363格式,这是big-endian r
concat big-endian s
。 r
和s
具有相同的大小(由密钥大小决定),因此签名总是长度均匀,r是前半部分。
OpenSSL使用ASN.1 / DER编码,即SEQUENCE(INTEGER(r),INTEGER(s))。 DER编码可以一直下降到6个字节( 30 04 02 00 02 00
,退化r = 0,s = 0),并且平均比IEEEforms大6个字节。 它编码为30 [length, one or more bytes] 02 [length, one or more bytes] [optional padding 00] [big-endian r with no leading 00s] 02 [length, one or more bytes] [optional padding 00] [big-endian s with no leading 00s]
。
DER表单过于依赖数据而无法具体描述,因此一个示例应该有所帮助。 假设我们在32位字段中使用曲线并生成(r = 1016,s = 2289644760)。
IEEE 1363:
// r 00 00 03 F8 // s 88 79 34 D8
DER:
SEQUENCE(INTEGER(1016), INTEGER(2289644760)) // Encode r // 1016 => 0x3F8 => 03 F8 (length 02) SEQUENCE( 02 02 03 F8, INTEGER(2289644760)) // Encode s // 2289644760 => 0x887934D8 => 88 79 34 D8 // But since the high bit is set this is a negative number (-2005322536), // and s is defined to be positive. So insert a 00 to ensure the high bit is clear. // => 00 88 79 34 D8 (length 05) SEQUENCE( 02 02 03 F8 02 05 00 88 79 34 D8) // And encode the sequence, whose payload length we can now count as 11 (0B) 30 0B 02 02 03 F8 02 05 00 88 79 34 D8
因此,Windows / .NET发出00 00 03 F8 88 79 34 D8
,OpenSSL发出30 0B 02 02 03 F8 02 05 00 88 79 34 D8
。 但他们都只是说(r, s) = (1016, 2289644760)
。
(旁白:您观察到DER编码中的签名[2] == 0x02对于您正在使用的大小键是正确的,但是在大约496位密钥处,SEQUENCE长度在统计上可能需要多于一个字节;因此,对于P-521键,它最有可能从03 81 88 02
, 88
字节的变化)