ECDiffieHellmanCng PublicKey 始终相同吗?

M. *_*ann 1 c# cryptography

我正在使用 C# ECDiffieHellmanCng 类,并使用示例中的代码发现了一个(在我看来奇怪的)行为任何项目中生成的每个公钥都是相同的!这是正确且理想的行为吗?

例子:

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

跟踪始终将“ECK5B”作为输出。使用不同的构造函数只会使输出略有不同,但事实并非如此,它始终是相同的。我是否误解了什么,这个结果符合预期,并且没有机会提供随机公钥?我只是认为系统会使用更多的随机性。

bar*_*njs 5

该方法返回描述密钥的ToByteArray()(Windows 特定的)CNG blob 。

blob 布局是

UINT32 Magic
UINT32 cbKey
<cbKey bytes of public key>
Run Code Online (Sandbox Code Playgroud)

BCRYPT_ECDH_PUBLIC_P521_MAGIC的值为0x354B4345,如果按 Little-Endian 顺序 ( 45 43 4B 35) 查看,则为 ASCII 字符串ECK5。NIST P-521 曲线上的点的坐标x最多需要 521 位,即 ((521+7)/8) == 66 字节。(UINT32)66在 Little-Endian 中是42 00 00 00. 因此,所有字节数组(对于基于 NIST P-521 的公钥)都将以

45 43 4B 35 42 00 00 00
Run Code Online (Sandbox Code Playgroud)

(然后还有 ECPoint 的 X 分量的 66 个字节)。由于 ASCII 字符串在读取第一个 时将终止0x00,因此它被解释为(作为字符串)ECK5B

正如您已经发现的,该值实际上并不是字符串,因此为了将其视为字符串,需要将其编码为字符串安全格式,例如十六进制或 Base64。由于十六进制是 1=>2 编码(或 1=>~3 带空格),而 Base64 是 3=>4 编码,因此大多数应用程序最终都使用 Base64。