Как сгенерировать пару ключей DSA, используя OpenSSL libcrypto? - PullRequest
0 голосов
/ 01 декабря 2018

У меня следующий код, пытающийся сгенерировать пару ключей DSA.

OpenSSL_add_all_algorithms();
ctx=EVP_PKEY_CTX_new_id(EVP_PKEY_DSA,NULL); EVP_PKEY_keygen_init(ctx);
if (EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx,1024)<=0)      ERR_print_errors_fp(stderr);

, и я получаю следующую ошибку

3073906944: ошибка: 06089094: процедуры цифрового конверта:EVP_PKEY_CTX_ctrl: недопустимая операция: pmeth_lib.c: 398:

Любая подсказка о том, что я делаю неправильно?спасибо

1 Ответ

0 голосов
/ 01 декабря 2018

Вам нужно два контекста;один для параметров, а другой для фактического кейгена.Вы должны выполнить следующие два набора операций:

Генерация параметров

  1. Создать генератор параметров, используя EVP_PKEY_CTX_new_id(EVP_PKEY_DSA, NULL)
  2. Установить биты в контексте генератора параметров, используя EVP_PKEY_CTX_set_dsa_paramgen_bits; не контекст keygen (который, если вы все делаете правильно, еще даже не существует).
  3. Инициализируйте генератор параметров, используя EVP_PKEY_paramgen_init
  4. Наконец, сгенерируйте параметры, используя EVP_PKEY_paramgen.В результате получается объект EVP_PKEY (я назову его pkey_params), который содержит входные параметры для будущей генерации ключа

После того, как все будет сделано, затем Вы переходите к фактической генерации ключа, которая значительно проще:

Генерация ключа

  1. Создание нового контекста с использованием EVP_PKEY_CTX_new(pkey_params, NULL) Обратите внимание на pkey_paramsиз предыдущей серии шагов.
  2. Инициализируйте контекст генератора, используя EVP_PKEY_keygen_init
  3. Сгенерируйте фактический ключ, используя EVP_PKEY_keygen

После завершения все ресурсыкроме финала pkey сверху должен быть должным образом уничтожен.Освободите окончательный ключ, как только сделаете его.Вот и все.

Пример

Здесь нет проверки ошибок, но здесь важен порядок операций.Так что обратите на это внимание.

#include <stdio.h>
#include <openssl/evp.h>
#include <openssl/dsa.h>
#include <openssl/pem.h>

// required for any BIO standard stream IO.
#include <openssl/applink.c>

int main()
{
    OPENSSL_init();
    OpenSSL_add_all_algorithms();

    // build parameters first
    EVP_PKEY_CTX *ctx_params = EVP_PKEY_CTX_new_id(EVP_PKEY_DSA, NULL);
    EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx_params, 1024);
    EVP_PKEY_paramgen_init(ctx_params);

    EVP_PKEY* pkey_params = NULL;
    EVP_PKEY_paramgen(ctx_params, &pkey_params);

    // using parameters, build DSA keypair
    EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey_params, NULL);
    EVP_PKEY_keygen_init(ctx);

    EVP_PKEY* pkey = NULL;
    EVP_PKEY_keygen(ctx, &pkey);

    // cleanup everything but the final key
    EVP_PKEY_free(pkey_params);
    EVP_PKEY_CTX_free(ctx_params);
    EVP_PKEY_CTX_free(ctx);

    // TODO: whatever you want with the generator pkey. in this
    //  example we're just dumping the full unencrypted key to 
    //  stdout. 
    DSA* dsa = EVP_PKEY_get1_DSA(pkey);
    BIO* bio = BIO_new_fp(stdout, BIO_NOCLOSE);
    PEM_write_bio_DSAPrivateKey(bio, dsa, NULL, NULL, 0, NULL, NULL);
    BIO_flush(bio);
    DSA_free(dsa);
    EVP_PKEY_free(pkey);

    return 0;
}

Вывод (варьируется, очевидно)

-----BEGIN DSA PRIVATE KEY-----
MIIBuwIBAAKBgQDJ+NoL8SZeTcqVA83WI7CCO6INYLw18DiALLMewPqXEPm99mof
RX2693WJfpbWIjuHi/KXzH6vQ/0sQU+2z1CqgWhudVhQTofGNcsPrUbPpShTDMcP
OoTx9dRb8rXWbxg7dfhGZ9z2pEhzRtPWpI2y81VxYhGXzVSC3zqW6+ec2QIVALaE
fynSMqc56gPqDPZfRz1rlq3dAoGAL+vbbYu+gSy8zGqoLykqhG+Vl4/Eh/zQIWoB
t64bfh7GU6o0wvgTQgcdGZK3/laa9Msa6J3iEGZcP3dd9x4fTQ5vzxDGIYikcC8I
L8s2JbNi1Jxbr5dw3/sOKsdHIt95rFZ03+gMzaV+9pc8LpATnaXMtp5mmH+lRgsJ
SIEdLqcCgYAVGpwZHaFUnttqQAf3/ohMtqIQG+RBp/yUf2EA7rcoHpA7bCBADApx
mG5hH/F4dKjCSciKdHq4Ibf60ctAJNL2sobPKNArTMo/GNuzE+J79Wj6s/b7zwt7
AF+27H9PAiXB08ftMmCSesXkX7v926EHRxDgSlVAgCPSfkXKNQn1XwIVALF2MF2N
GRdMtFUxZFnIk2GnqC1R
-----END DSA PRIVATE KEY-----
...