I want to make a ECDSA signature with this code :
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
always returns true and this is ok.
But I have some problems with signature.
Why is length of signature ( SignByteArray
) fixed? (0x40 byte).
And Why are SignByteArray [0]
and SignByteArray [2]
values incorrect? (I think they should be 0x30 and 0x02)
I expected a thing like https://kjur.github.io/jsrsasign/sample-ecdsa.html
The ECDSA specification concludes with a determination that the pair (
r
,s
) are the signature. What it neglects to do is indicate how one should write them down.Windows and .NET use the IEEE (P)1363 format, which is big-endian
r
concat big-endians
.r
ands
have the same size (determined by the key size), so the signature is always even in length and r is the first half.OpenSSL uses an ASN.1/DER encoding, which is SEQUENCE(INTEGER(r), INTEGER(s)). The DER encoding can go all the way down to 6 bytes (
30 04 02 00 02 00
, in the degenerate r=0, s=0) and is, on average, 6 bytes bigger than the IEEE form. It encodes as30 [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]
.The DER form is too data dependant to specifically describe, so an example should help. Assuming we're using a curve in a 32-bit field and we generate (r=1016, s=2289644760).
IEEE 1363:
DER:
So Windows/.NET emit
00 00 03 F8 88 79 34 D8
, and OpenSSL emits30 0B 02 02 03 F8 02 05 00 88 79 34 D8
. But they're both just saying(r, s) = (1016, 2289644760)
.(Aside: Your observation that signature[2] == 0x02 in the DER encoding is correct for the size key you're working with, but at around a 496-bit key the SEQUENCE length becomes statistically likely to require more than one byte; so for a P-521 key it's most likely that it starts as
03 81 88 02
, with variability in the88
byte)