M. Altmann
M. Altmann

Reputation: 726

ECDiffieHellmanCng PublicKey always the same?

I'm playing around with the C# ECDiffieHellmanCng class and found a (in my opinion strange) behavior using the code from the sample: Every generated public key in any project ist the same! Is this correct and a desired behavior?

Example:

using (ECDiffieHellmanCng bob = new ECDiffieHellmanCng())
            {
                bob.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;
                bob.HashAlgorithm = CngAlgorithm.Sha256;
                Trace.WriteLine(Encoding.UTF8.GetString(bob.PublicKey.ToByteArray()));
            }

The trace will always have "ECK5B" as output. Using a different constructor will only differ the output a bit but not the fact, that it is always the same. Do I missunderstand something and this result is as expected and there is no chance to provide a random public key? I just thought the system would use some more randomness.

Upvotes: 1

Views: 888

Answers (1)

bartonjs
bartonjs

Reputation: 33088

The ToByteArray() method, returns the (Windows-specific) CNG blob describing the key.

The blob layout is

UINT32 Magic
UINT32 cbKey
<cbKey bytes of public key>

the value for BCRYPT_ECDH_PUBLIC_P521_MAGIC is 0x354B4345, which if viewed in Little-Endian order (45 43 4B 35) is the ASCII string ECK5. The x coordinate of a point on the NIST P-521 curve needs up to 521 bits, or ((521+7)/8) == 66 bytes. (UINT32)66 in Little-Endian is 42 00 00 00. So all of the byte arrays (for a NIST P-521-based public key) will start with

45 43 4B 35 42 00 00 00

(and then have 66 more bytes of the X component of the ECPoint). Since the ASCII string will terminate when it reads the first 0x00, this gets interpreted (as a string) as ECK5B.

As you've already discovered, this value isn't actually a string, so in order to be treated as one it needs to be encoded to a string-safe format, such as hex or Base64. Since hex is a 1=>2 encoding (or 1=>~3 with spaces) and Base64 is a 3=>4 encoding, most applications end up using Base64.

Upvotes: 5

Related Questions