OpenSSL генерирует пару ключей ED25519 С++

Я хочу создать сертификат x509 и самостоятельно подписать его с помощью закрытого ключа eddsa (ed25519)!

Поэтому я попробовал следующий пример из документации: https://www.openssl.org/docs/man1.1.1/man7/Ed25519.html

EVP_PKEY* server::generate_privatekey()
{
   EVP_PKEY *pkey = NULL;
   EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_ED25519, NULL);

   if(EVP_PKEY_keygen_init(pctx) <= 0){
       std::cout << "keygen init fail\n" << std::endl;
   }
   
   //EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, NID_ED25519); 
   //gives return value -1 in combination with EVP_PKEY_CTX_new_id(EVP_PKEY_EC , NULL); 
   //EVP_PKEY_EC != eddsa (ecdsa/ecdh only?)
   //gives return value 0 in combination with EVP_PKEY_CTX_new_id(EVP_PKEY_ED25519 , NULL);

   if(EVP_PKEY_keygen(pctx, &pkey) <= 0){
       std::cout << "keygen fail\n" << std::endl;
   }

   //////////KEYPAIR CHECK///////////
   int chk = EVP_PKEY_check(pctx);

   if(chk == 1){
       std::cout << "key pair valid: " << chk << std::endl;
   }
   else if(chk == -2){
       std::cout << "algorithm not supported: " << chk << std::endl;
   }
   else{
       std::cout << "keypair error: " << chk << std::endl;
   }
   //////////////////////////////////

   EVP_PKEY_CTX_free(pctx);

   return pkey;
}

https://www.openssl.org/docs/man1.1.1/man3/EVP_PKEY_check.html

EVP_PKEY_check() возвращает значение 0 (ошибка пары ключей)!

EVP_PKEY_public_check() тот же результат.

Я думаю, именно поэтому я получаю X509_sign() возвращаемое значение 0 (сбой):

string server::Generate_x509(EVP_PKEY* pkey)
{
   //////////////////////////////////////////////////////
   //set expiration = 10 years
   time_t exp;
   time(&exp);
   exp += 315360000;

   //create x509 structure
   X509* x509= X509_new();

   //set serial to 420
   if(ASN1_INTEGER_set(X509_get_serialNumber(x509), 420) == 0){
       std::cout << "asn1 set serial number fail\n" << std::endl;
   }

   //set start & expiration time
   if(X509_time_adj_ex(X509_getm_notBefore(x509), 0, 0, 0) == NULL){
       std::cout << "set time fail\n" << std::endl;
   }

   if(X509_time_adj_ex(X509_getm_notAfter(x509), 0, 0, &exp) == NULL){
       std::cout << "set end time fail\n" << std::endl;
   }

   //set public key
   if(X509_set_pubkey(x509, pkey) == 0){
       std::cout << "set pubkey fail\n" << std::endl;
   }

   //sign certificate with private key
   if(X509_sign(x509, pkey, EVP_sha512()) == 0){
       std::cout << "sign fail\n" << std::endl;
       return "Creating certificate failed...\n";
   }

   FILE*f;

   f = fopen("key.pem", "wb");

   PEM_write_PrivateKey(
       f,                          /* write the key to the file we've opened */
       pkey,                       /* our key from earlier */
       EVP_aes_256_cbc(),          /* default cipher for encrypting the key on disk */
       (unsigned char*)"aaa",      /* passphrase required for decrypting the key on disk */
       3,                          /* length of the passphrase string */
       NULL,                       /* callback for requesting a password */
       NULL                        /* data to pass to the callback */
   );
   fclose(f);

   f = fopen("cert.pem", "wb");
   PEM_write_X509(
       f,   /* write the certificate to the file we've opened */
       x509 /* our certificate */
   );
   fclose(f);

   return "Certificate created succesfully\n";
}

Все отлично работает со сгенерированным ключом RSA.

Этот пример тоже работает, но не с моими параметрами (см. код выше):

Используя только 1 EVP_PKEY при создании ключей EC с использованием OpenSSL 1.1

Я использую OpenSSL v1.1.1i

я надеюсь, что этот вопрос не слишком глуп..

с уважением


person 6920616d206964696f74    schedule 15.12.2020    source источник
comment
В вашем связанном примере выполняется вызов EVP_PKEY_CTX_set_ec_paramgen_curve_nid между *keygen_init и *keygen, которого нет у вас. Кроме того, связанный код пройдет проверку для любого положительного значения (например, 2 — это нормально), но ваш код допускает только 1 [и зачем вместо этого вызывать подпрограмму проверки дважды из (например) int ecode = EVP_PKEY_check(pctx); if (ecode ...) ... else if (ecode ...) ...] И когда вы сталкиваетесь с ошибкой, вы не печатаете ни конкретное сообщение об ошибке, ни фактическое возвращаемое значение (например, может быть -3 [ против -2], что может помочь с отладкой)   -  person Craig Estey    schedule 16.12.2020
comment
Привет, спасибо за ваш ответ! Вы правы, я отредактировал свой пост. К сожалению, эта функция (EVP_PKEY_CTX_set_ec_paramgen_curve_nid) мне не помогает (см. мое редактирование выше). Я разрешаю только 1, потому что EVP_PKEY_check(), EVP_PKEY_public_check() и EVP_PKEY_param_check() возвращают 1 в случае успеха или другие в случае неудачи. Они возвращают -2, если операция не поддерживается для конкретного алгоритма. приветствует   -  person 6920616d206964696f74    schedule 16.12.2020