I am able to extract public and private keys from OSSL_PARAM array with these functions (i tried using special functions to get parameter by name, but they can't find actual parameters by that names)
std::vector<unsigned char> RSAKeyPair::GetNamedParam(EVP_PKEY *key, const std::string& name) {
OSSL_PARAM *param_array;
if (EVP_PKEY_todata(key, EVP_PKEY_PUBLIC_KEY, ¶m_array) == 0)
throw std::runtime_error("cannot read parameters");
OSSL_PARAM *cur_param;
int i = 0;
do {
cur_param = ¶m_array[i++];
if (std::string(cur_param->key) == name) {
auto data = GetParameterData(cur_param);
OSSL_PARAM_free(param_array);
return data;
}
} while (cur_param->key != nullptr);
throw std::runtime_error("cannot find parameter with name \"" + name + '"');
}
std::vector<unsigned char> RSAKeyPair::GetParameterData(OSSL_PARAM *param) {
BIGNUM *bignum{nullptr};
if(OSSL_PARAM_get_BN(param, &bignum) == 0)
throw std::runtime_error("cannot read bignum");
std::vector<unsigned char> bytes;
int new_size = BN_num_bytes(bignum);
bytes.resize(new_size);
BN_bn2bin(bignum, bytes.data());
return bytes;
}
The problem is when I try to build new key from raw bytes using the same approach
void RSAKeyPair::SetPublicKey(const std::vector<unsigned char> &key) {
OSSL_PARAM *parameters = GetKeyParameters({key}, std::nullopt);
SetKeyFromParameters(parameters);
OSSL_PARAM_free(parameters);
}
void RSAKeyPair::SetKeyFromParameters(OSSL_PARAM *parameters) {
auto ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, nullptr);
if (EVP_PKEY_fromdata_init(ctx) <= 0)
throw std::runtime_error("cannot init create key");
EVP_PKEY_free(keys_);
if (EVP_PKEY_fromdata(ctx, &keys_, EVP_PKEY_KEYPAIR, parameters) <= 0)
throw std::runtime_error("cannot create key");
}
OSSL_PARAM *RSAKeyPair::GetKeyParameters(std::optional<std::reference_wrapper<const std::vector<unsigned char>>> public_key,
std::optional<std::reference_wrapper<const std::vector<unsigned char>>> private_key) {
auto param_bld = OSSL_PARAM_BLD_new();
if (public_key.has_value()) {
auto public_data = public_key.value().get();
PushParamBuildBignum(param_bld, "n", public_data);
}
if (private_key.has_value()) {
auto private_data = private_key.value().get();
PushParamBuildBignum(param_bld, "d", private_data);
}
// default rsa exponent
OSSL_PARAM_BLD_push_long(param_bld, "e", RSA_F4);
auto parameters = OSSL_PARAM_BLD_to_param(param_bld);
OSSL_PARAM_BLD_free(param_bld);
return parameters;
}
void RSAKeyPair::PushParamBuildBignum(OSSL_PARAM_BLD *param_bld, const char *key, std::vector<unsigned char> &bytes) {
BIGNUM *bignum = BN_bin2bn(bytes.data(), (int)bytes.size(), nullptr);
OSSL_PARAM_BLD_push_BN(param_bld, key, bignum);
}
for some reason, function EVP_PKEY_fromdata() fails to create new key using my OSSL_PARAM array. What am I supposed to do to initialize ONLY public key on signature verifying end (where I cannot build full keypair with all parameters) ?
you can see full source code for this class at https://github.com/Valemos/course_work_inverted_index/blob/master/src/session/RSAKeyPair.cpp
Aucun commentaire:
Enregistrer un commentaire