分离 public 和 ECDSA 密钥对的私钥
Separating public and private keys of ECDSA keypair
我正在使用 C++ 尝试根据来自 OpenSSL wiki 的 Elliptic_Curve_Cryptography 生成 ECDSA 密钥对。
#include <iostream>
#include <openssl/obj_mac.h>
#include <openssl/ec.h>
int main()
{
EC_KEY *key;
if(NULL == (key = EC_KEY_new_by_curve_name(NID_secp224r1)))
std::cout << "error on new_curve_by_name" << std::endl;
if(1 != EC_KEY_generate_key(key)) std::cout << "error in generating keys" << std::endl;
}
密钥对生成没有错误,但我不知道如何在两个不同的对象(EC_POINT 和 BIGNUM)中提取 public 和私钥,知道吗?
我认为您必须执行以下操作:
BIGNUM *privateKey;
EC_POINT *publicKey;
privateKey = BN_new();
EC_KEY_set_private_key(key, privateKey);
EC_KEY_set_public_key(key, publicKey);
编辑:
这两个调用将分别设置 privateKey
和 publicKey
。
Open SSL Documentation 声称“destination 应该是通过调用 BN_new()
获得的新分配的 BIGNUM。它不应该用于其他目的或以任何方式初始化。”,因此我添加了 BN_new()
调用。
我没有看到任何类似于创建 EC_Point 对象的内容(除非您使用 EC_Group 以这种方式创建:EC_POINT *EC_POINT_new(const EC_GROUP *group);
所以试试这个,如果你还是不明白,那么也许你应该看看如何根据你的用法正确创建一个 EC_Point 对象。
这个returns私钥为BIGNUM
BIGNUM* bn = EC_KEY_get0_private_key(key);
对于 public 密钥,不确定如何获得 EC_POINT,但您可以通过以下方式获取原始字节:
// first call returns length of key
int len = i2o_ECPublicKey(key, 0);
std::vector<unsigned char> bytes b(len, 0);
unsigned char* p = &b[0];
// second call copies key into p (and returns length if successful)
if (i2o_ECPublicKey(key, &p)) != len)
{
// handle error
}
我想你想要的方法是:
EC_KEY_get0_private_key 和
EC_KEY_get0_public_key
这对我有用:
EC_KEY* key = EC_KEY_new_by_curve_name(NID_secp224r1);
if(!key)
{
std::cerr << "Error creating curve key" << '\n';
return EXIT_FAILURE;
}
if(!EC_KEY_generate_key(key))
{
std::cerr << "Error generating curve key" << '\n';
EC_KEY_free(key);
return EXIT_FAILURE;
}
BIGNUM const* prv = EC_KEY_get0_private_key(key);
if(!prv)
{
std::cerr << "Error getting private key" << '\n';
EC_KEY_free(key);
return EXIT_FAILURE;
}
std::cout << "Private key: " << prv << '\n';
EC_POINT const* pub = EC_KEY_get0_public_key(key);
if(!pub)
{
std::cerr << "Error getting public key" << '\n';
EC_KEY_free(key);
return EXIT_FAILURE;
}
std::cout << "Public key: " << pub << '\n';
// Use keys here ...
EC_KEY_free(key);
注意:
当像这样使用 C
库时,我经常定义一个自定义 智能指针 来处理删除。这使得代码不太容易发生内存泄漏和 "exception safe".
例如我会这样定义:
struct ec_key_dter{void operator()(EC_KEY* k)const{if(k) EC_KEY_free(k);}};
using ec_key_uptr = std::unique_ptr<EC_KEY, ec_key_dter>;
并像这样使用它:
auto key = ec_key_uptr(EC_KEY_new_by_curve_name(NID_secp224r1));
if(!key)
throw std::runtime_error("Error creating curve key");
if(!EC_KEY_generate_key(key.get()))
throw std::runtime_error("Error generating curve key");
if(!EC_KEY_check_key(key.get()))
throw std::runtime_error("Error checking curve key");
// ... etc ...
// Do not delete the key manually!!
我正在使用 C++ 尝试根据来自 OpenSSL wiki 的 Elliptic_Curve_Cryptography 生成 ECDSA 密钥对。
#include <iostream>
#include <openssl/obj_mac.h>
#include <openssl/ec.h>
int main()
{
EC_KEY *key;
if(NULL == (key = EC_KEY_new_by_curve_name(NID_secp224r1)))
std::cout << "error on new_curve_by_name" << std::endl;
if(1 != EC_KEY_generate_key(key)) std::cout << "error in generating keys" << std::endl;
}
密钥对生成没有错误,但我不知道如何在两个不同的对象(EC_POINT 和 BIGNUM)中提取 public 和私钥,知道吗?
我认为您必须执行以下操作:
BIGNUM *privateKey;
EC_POINT *publicKey;
privateKey = BN_new();
EC_KEY_set_private_key(key, privateKey);
EC_KEY_set_public_key(key, publicKey);
编辑:
这两个调用将分别设置 privateKey
和 publicKey
。
Open SSL Documentation 声称“destination 应该是通过调用 BN_new()
获得的新分配的 BIGNUM。它不应该用于其他目的或以任何方式初始化。”,因此我添加了 BN_new()
调用。
我没有看到任何类似于创建 EC_Point 对象的内容(除非您使用 EC_Group 以这种方式创建:EC_POINT *EC_POINT_new(const EC_GROUP *group);
所以试试这个,如果你还是不明白,那么也许你应该看看如何根据你的用法正确创建一个 EC_Point 对象。
这个returns私钥为BIGNUM
BIGNUM* bn = EC_KEY_get0_private_key(key);
对于 public 密钥,不确定如何获得 EC_POINT,但您可以通过以下方式获取原始字节:
// first call returns length of key
int len = i2o_ECPublicKey(key, 0);
std::vector<unsigned char> bytes b(len, 0);
unsigned char* p = &b[0];
// second call copies key into p (and returns length if successful)
if (i2o_ECPublicKey(key, &p)) != len)
{
// handle error
}
我想你想要的方法是:
EC_KEY_get0_private_key 和 EC_KEY_get0_public_key
这对我有用:
EC_KEY* key = EC_KEY_new_by_curve_name(NID_secp224r1);
if(!key)
{
std::cerr << "Error creating curve key" << '\n';
return EXIT_FAILURE;
}
if(!EC_KEY_generate_key(key))
{
std::cerr << "Error generating curve key" << '\n';
EC_KEY_free(key);
return EXIT_FAILURE;
}
BIGNUM const* prv = EC_KEY_get0_private_key(key);
if(!prv)
{
std::cerr << "Error getting private key" << '\n';
EC_KEY_free(key);
return EXIT_FAILURE;
}
std::cout << "Private key: " << prv << '\n';
EC_POINT const* pub = EC_KEY_get0_public_key(key);
if(!pub)
{
std::cerr << "Error getting public key" << '\n';
EC_KEY_free(key);
return EXIT_FAILURE;
}
std::cout << "Public key: " << pub << '\n';
// Use keys here ...
EC_KEY_free(key);
注意:
当像这样使用 C
库时,我经常定义一个自定义 智能指针 来处理删除。这使得代码不太容易发生内存泄漏和 "exception safe".
例如我会这样定义:
struct ec_key_dter{void operator()(EC_KEY* k)const{if(k) EC_KEY_free(k);}};
using ec_key_uptr = std::unique_ptr<EC_KEY, ec_key_dter>;
并像这样使用它:
auto key = ec_key_uptr(EC_KEY_new_by_curve_name(NID_secp224r1));
if(!key)
throw std::runtime_error("Error creating curve key");
if(!EC_KEY_generate_key(key.get()))
throw std::runtime_error("Error generating curve key");
if(!EC_KEY_check_key(key.get()))
throw std::runtime_error("Error checking curve key");
// ... etc ...
// Do not delete the key manually!!