椭圆曲线 Diffie Hellman public 密钥大小
Elliptic Curve Diffie Hellman public key size
我想使用 Diffie hellman 在 c# 服务器和 c++ 客户端之间生成密钥。此代码为服务器生成一个 public 密钥:
serverECDH = new ECDiffieHellmanCng(ECCurve.NamedCurves.nistP256);
serverECDH.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;
serverECDH.HashAlgorithm = CngAlgorithm.Sha256;
ECDHPublicKey =Convert.ToBase64String(serverECDH.PublicKey.ToByteArray());
Console.WriteLine(serverECDH.KeySize); //256
Console.WriteLine(serverECDH.PublicKey.ToByteArray().Length); //72
Console.WriteLine(ECDHPublicKey);
我想知道为什么 publicKey Byte Array Size 是 72 而我期望的是 64 字节长的数组?
除此之外,这是我在客户端中生成 public 密钥的实现:
if (NULL == (pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL))) HandleErrors(1);
if (1 != EVP_PKEY_paramgen_init(pctx)) HandleErrors(2);
if (1 != EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, NID_X9_62_prime256v1)) HandleErrors(3);
if (!EVP_PKEY_paramgen(pctx, ¶ms)) HandleErrors(4);
if (NULL == (kctx = EVP_PKEY_CTX_new(params, NULL))) HandleErrors(5);
if (1 != EVP_PKEY_keygen_init(kctx)) HandleErrors(6);
if (1 != EVP_PKEY_keygen(kctx, &pkey)) HandleErrors(7);
bio = BIO_new(BIO_s_mem());
PEM_write_bio_PUBKEY(bio, pkey);
int publicKeyLen = BIO_pending(bio);
cout << publicKeyLen << endl;
unsigned char* publicKeyChar = (unsigned char*)malloc(publicKeyLen);
BIO_read(bio, publicKeyChar, publicKeyLen);
ECDHPublicKey = string(reinterpret_cast<char const*>(publicKeyChar),publicKeyLen);
cout << ECDHPublicKey << endl;
在此代码中,public 密钥长度为 128 字节(字符?),这又很奇怪,因为我指定了 NID_X9_62_prime256v1 曲线。我的错误在哪里?
此外 NID_X9_62_prime256v1 和 nistP256 在 c++ 和 c# 中匹配吗?
编辑:
这是 cout << ECDHPublicKey << endl 输出的示例:
-----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEUFD9ZNby6x2bf/VC16/NHSxIXdit
Ips60uLoi0/jKmbmMHRg2xbXVVzV8Uc1DElMlZA817bMFCnVvi1VsM5JYg==
-----END PUBLIC KEY-----
在 C++ 代码中,public 密钥不仅是 DER 编码的,它也是 PEM 编码的。这会在 base 64 编码的 DER 结构周围添加页眉和页脚。 PEM 用于基于文本的界面,其中二进制数据可能会失真。因此,它有时也被称为 "ASCII armor"(或 "ASCII armour",具体取决于您的方言)。
如果您想查看 C++/OpenSSL 代码的结构,只需将 base 64 编码的 DER 结构粘贴到 this site 或使用 openssl asn1parse
.
serverECDH.PublicKey.ToByteArray()
返回的 Mickeysoft 结构似乎由 "ECK1" + 20 00 00 00
后跟两个静态大小的编码坐标(可能是大端或小端)组成。 ECK1 可能是 Elliptic Curve Key format 1 - 不管是什么 - 并且 20 00 00 00
可能是八位字节中的键/坐标大小,为 32 * 8 = 256。请注意,C# 正式使用平台字节顺序,因此 20 00 00 00
是一个 32 位小端值。可能您需要一个外部库来对它们的密钥进行编码,以便任何其他运行时都能理解它们。
至于你的附加问题:是的,ANS(I) X9.62 prime256r1 曲线与 NIST P-256 和 secp256r1 相同(我认为)最初由 Certicom corp 定义。曲线首先被定义,然后被各种组织采用和标准化。
我想使用 Diffie hellman 在 c# 服务器和 c++ 客户端之间生成密钥。此代码为服务器生成一个 public 密钥:
serverECDH = new ECDiffieHellmanCng(ECCurve.NamedCurves.nistP256);
serverECDH.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;
serverECDH.HashAlgorithm = CngAlgorithm.Sha256;
ECDHPublicKey =Convert.ToBase64String(serverECDH.PublicKey.ToByteArray());
Console.WriteLine(serverECDH.KeySize); //256
Console.WriteLine(serverECDH.PublicKey.ToByteArray().Length); //72
Console.WriteLine(ECDHPublicKey);
我想知道为什么 publicKey Byte Array Size 是 72 而我期望的是 64 字节长的数组? 除此之外,这是我在客户端中生成 public 密钥的实现:
if (NULL == (pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL))) HandleErrors(1);
if (1 != EVP_PKEY_paramgen_init(pctx)) HandleErrors(2);
if (1 != EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, NID_X9_62_prime256v1)) HandleErrors(3);
if (!EVP_PKEY_paramgen(pctx, ¶ms)) HandleErrors(4);
if (NULL == (kctx = EVP_PKEY_CTX_new(params, NULL))) HandleErrors(5);
if (1 != EVP_PKEY_keygen_init(kctx)) HandleErrors(6);
if (1 != EVP_PKEY_keygen(kctx, &pkey)) HandleErrors(7);
bio = BIO_new(BIO_s_mem());
PEM_write_bio_PUBKEY(bio, pkey);
int publicKeyLen = BIO_pending(bio);
cout << publicKeyLen << endl;
unsigned char* publicKeyChar = (unsigned char*)malloc(publicKeyLen);
BIO_read(bio, publicKeyChar, publicKeyLen);
ECDHPublicKey = string(reinterpret_cast<char const*>(publicKeyChar),publicKeyLen);
cout << ECDHPublicKey << endl;
在此代码中,public 密钥长度为 128 字节(字符?),这又很奇怪,因为我指定了 NID_X9_62_prime256v1 曲线。我的错误在哪里? 此外 NID_X9_62_prime256v1 和 nistP256 在 c++ 和 c# 中匹配吗?
编辑: 这是 cout << ECDHPublicKey << endl 输出的示例:
-----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEUFD9ZNby6x2bf/VC16/NHSxIXdit Ips60uLoi0/jKmbmMHRg2xbXVVzV8Uc1DElMlZA817bMFCnVvi1VsM5JYg==
-----END PUBLIC KEY-----
在 C++ 代码中,public 密钥不仅是 DER 编码的,它也是 PEM 编码的。这会在 base 64 编码的 DER 结构周围添加页眉和页脚。 PEM 用于基于文本的界面,其中二进制数据可能会失真。因此,它有时也被称为 "ASCII armor"(或 "ASCII armour",具体取决于您的方言)。
如果您想查看 C++/OpenSSL 代码的结构,只需将 base 64 编码的 DER 结构粘贴到 this site 或使用 openssl asn1parse
.
serverECDH.PublicKey.ToByteArray()
返回的 Mickeysoft 结构似乎由 "ECK1" + 20 00 00 00
后跟两个静态大小的编码坐标(可能是大端或小端)组成。 ECK1 可能是 Elliptic Curve Key format 1 - 不管是什么 - 并且 20 00 00 00
可能是八位字节中的键/坐标大小,为 32 * 8 = 256。请注意,C# 正式使用平台字节顺序,因此 20 00 00 00
是一个 32 位小端值。可能您需要一个外部库来对它们的密钥进行编码,以便任何其他运行时都能理解它们。
至于你的附加问题:是的,ANS(I) X9.62 prime256r1 曲线与 NIST P-256 和 secp256r1 相同(我认为)最初由 Certicom corp 定义。曲线首先被定义,然后被各种组织采用和标准化。