0

I wrote following code to extract ECDH public key blob:

        var curve = ECCurve.NamedCurves.nistP256;
        ECDiffieHellman ecdh = ECDiffieHellman.Create(curve);

        var bytes = ecdh.PublicKey.ToByteArray();
        Console.WriteLine($"Public Key (byte length with format info): {bytes.Length}");

        var hexString = BitConverter.ToString(bytes).Replace("-", string.Empty);
        Console.WriteLine($"Public Key (hex with format info): {hexString}");

I got following output:

  • Public Key (byte length with format info): 72

  • Public Key (hex with format info): 45434B3120000000C3F1AC1F3D272BE14A26BE35B1A31F6C969425259162C06BEBE6AE977809984FC509ED5154E1E4782079D4BDDCDA6E083E48D271755267AD765CAD0E66B9FD9F

The first 4 bytes (key type) are 45434B31 (in hex format). This appears to be in big endian format where as this MSDN link indicates that it should be in little endian format, which dictates that these 4 bytes should be 314B4345 (again, as shown in this link). The link also uses "magic", instead of "key type". The next 4 bytes are 20000000 (in hex format) appears to be in the little endian format (as the above link says).

Is there a logical explanation for why key type is formatted as big endian? Or am I missing something here?

Raghu
  • 2,859
  • 4
  • 33
  • 65

1 Answers1

1

The first 4 bytes (key type) are 45434B31 (in hex format).

That would be 0x45434B31 (Big Endian interpretation), or 0x314B4345 (Little Endian interpretation). 0x314B4345 (LE) matches the nistP256 entry in your linked page.

Your question title indicates you believe that the length was stored big endian, but your question body you say it seems to be little endian. LE is correct. 20000000 is 0x00000020 (LE), or "32 byte fields". 32 bytes is 256 bits, which matches the expected answer for nistP256.


Note that you really don't want to use this blob format. The NIST P-256, 384, and 521 curves got distinct "magic" values, but the new Windows 10 additional curves all report under 0x504B4345 (BCRYPT_ECDH_PUBLIC_GENERIC_MAGIC). The curve name has to be carried externally.

The right answer on .NET for importing and exporting key values is the ECParameters struct via the ExportParameters and ImportParameters methods.

bartonjs
  • 30,352
  • 2
  • 71
  • 111
  • You are correct about my write up on key length. But why does the documentation say the "magic" (key type) should be in little endian when the actual value is shown as big endian? – Raghu Sep 04 '17 at 19:14
  • The documentation shows the value as a numerical constant. Big/Little Endian is about storage of values. If (in C) you wrote `*blob = 0x314B4345` on an x86/x64 system then inspect the memory it will appear as `45 43 4B 31` – bartonjs Sep 04 '17 at 19:36
  • I would agree with you in that it is a storage issue normally. When I make the call to ToByteArray() and get the result bytes, I am no longer interpreting bytes (as that was already done for me). So I would exepct to see the first bytes 8 as 314B434520000000 (and not 45434B3120000000) for consistency sake. Am I missing something here? – Raghu Sep 04 '17 at 19:51
  • What you're missing is that the underlying API uses a struct whose first value is a DWORD, and so they expect everyone to do a struct overlay. So they're thinking in structs and logical values, and you're thinking in bytes. That's the disconnect. – bartonjs Sep 04 '17 at 20:09