[gnutls-help] How to generate a private key and sign the certificate using GnuTLS API?

Nicolas Mora nicolas at babelouest.org
Wed Sep 4 04:24:54 CEST 2019


Hello,

I'm trying to generate a private RSA key, extract a certificate and sign
the certificate using the GnuTLS C API.

Basically, I try to reproduce the following certtool commands using the
API only:
certtool --generate-privkey --outfile client.key --bits=4096
certtool --generate-request --load-privkey client.key --outfile client.csr
certtool --generate-certificate --load-request client.csr
--load-ca-certificate root.crt --load-ca-privkey root.key --outfile
client.crt

The files root.key and root.crt already exist and contain the private
key and self-signed certificate of the CA.

I test with the code below but I got the following error message:
error gnutls_x509_crt_sign2: -43
which is GNUTLS_E_CERTIFICATE_ERROR

What did I do wrong with my certificate?

Thanks in advance

/Nicolas

#include <stdio.h>

#include <string.h>

#include <gnutls/gnutls.h>

#include <gnutls/x509.h>

#include <gnutls/abstract.h>



#define EXPIRATION 60*60*24*512

#define DN "cn=localhost,dc=glewlwyd,dc=babelouest,dc=org"



unsigned char key_issuer_pem[] = "-----BEGIN RSA PRIVATE KEY-----\n\

MIIJKAIBAAKCAgEArqDzGjUcgeuNrkZo3QbiXxMUDxUwCC9Z9B7KLRMF+Js2HtIz\n\

[...]\

sBlw0Z5kMXY3BEBA5FjawULzcCt9TEBcxGe9rRF4ZxLGjsm8d8tS3jERRLQ=\n\

-----END RSA PRIVATE KEY-----";

unsigned char cert_issuer_pem[] = "-----BEGIN CERTIFICATE-----\n\

MIIFjTCCA3WgAwIBAgIUJNuB/YIWqA+rQEbdzhI+rYw/iv4wDQYJKoZIhvcNAQEM\n\

[...]\

7GsnMfZ2lfkbHugkd2g5rjLQyAcMC0DNT76xHL8YWWDI\n\

-----END CERTIFICATE-----";



int main() {

  gnutls_x509_privkey_t privkey_x509 = NULL, key_issuer = NULL;

  gnutls_privkey_t privkey = NULL;

  gnutls_x509_crt_t crt = NULL, crt_issuer = NULL;

  gnutls_datum_t dat;

  time_t now, exp;

  const char * err = NULL;

  char crt_export[1024*16] = {0};

  size_t crt_export_len = 1024*16;

  int res;



  time(&now);

  exp = now + EXPIRATION;



  gnutls_global_init();



  do {

    if ((res = gnutls_x509_privkey_init(&privkey_x509)) < 0) {

      fprintf(stderr, "error gnutls_x509_privkey_init: %d\n", res);

      break;

    }



    if ((res = gnutls_privkey_init(&privkey)) < 0) {

      fprintf(stderr, "error gnutls_privkey_init: %d\n", res);

      break;

    }



    if ((res = gnutls_x509_crt_init(&crt)) < 0) {

      fprintf(stderr, "error gnutls_x509_crt_init: %d\n", res);

      break;

    }



    if ((res = gnutls_x509_privkey_init(&key_issuer)) < 0) {

      fprintf(stderr, "error gnutls_x509_privkey_init: %d\n", res);

      break;

    }



    if ((res = gnutls_x509_crt_init(&crt_issuer)) < 0) {

      fprintf(stderr, "error gnutls_x509_crt_init: %d\n", res);

      break;

    }



    dat.data = key_issuer_pem;

    dat.size = strlen((const char *)key_issuer_pem);

    if ((res = gnutls_x509_privkey_import(key_issuer, &dat,
GNUTLS_X509_FMT_PEM)) < 0) {

      fprintf(stderr, "error gnutls_x509_privkey_import: %d\n", res);

      break;

    }



    dat.data = cert_issuer_pem;

    dat.size = strlen((const char *)cert_issuer_pem);

    if ((res = gnutls_x509_crt_import(crt_issuer, &dat,
GNUTLS_X509_FMT_PEM)) < 0) {

      fprintf(stderr, "error gnutls_x509_crt_import: %d\n", res);

      break;

    }



    if ((res = gnutls_x509_privkey_generate(privkey_x509, GNUTLS_PK_RSA,
gnutls_sec_param_to_pk_bits(GNUTLS_PK_RSA, GNUTLS_SEC_PARAM_MEDIUM),
GNUTLS_PRIVKEY_FLAG_REPRODUCIBLE)) < 0) {

      fprintf(stderr, "error gnutls_x509_privkey_generate: %d\n", res);

      break;

    }



    if ((res = gnutls_privkey_import_x509(privkey, privkey_x509,
GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE)) < 0) {

      fprintf(stderr, "error gnutls_privkey_import_x509: %d\n", res);

      break;

    }



    if ((res = gnutls_x509_crt_set_key(crt, privkey_x509)) < 0) {

      fprintf(stderr, "error gnutls_x509_crt_set_key: %d\n", res);

      break;

    }



    if ((res = gnutls_x509_crt_set_private_key_usage_period(crt, now,
exp)) < 0) {

      fprintf(stderr, "error
gnutls_x509_crt_set_private_key_usage_period: %d\n", res);

      break;

    }



    if ((res = gnutls_x509_crt_set_dn(crt, DN, &err)) < 0) {

      fprintf(stderr, "error gnutls_x509_crt_set_dn: %d\n", res);

      break;

    }



    if ((res = gnutls_x509_crt_sign2(crt, crt_issuer, key_issuer,
GNUTLS_DIG_SHA256, 0)) < 0) {

      fprintf(stderr, "error gnutls_x509_crt_sign2: %d\n", res);

      break;

    }



    if ((res = gnutls_x509_privkey_export(privkey_x509,
GNUTLS_X509_FMT_PEM, crt_export, &crt_export_len)) < 0) {

      fprintf(stderr, "error gnutls_x509_privkey_export: %d\n", res);

      break;

    }

    printf("privkey:\n%.*s\n", (int)crt_export_len, crt_export);



    if ((res = gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_PEM,
crt_export, &crt_export_len)) < 0) {

      fprintf(stderr, "error gnutls_x509_crt_export: %d\n", res);

      break;

    }

    printf("cert:\n%.*s\n\n", (int)crt_export_len, crt_export);



  } while (0);



  if (privkey)

    gnutls_privkey_deinit(privkey);

  if (crt)

    gnutls_x509_crt_deinit(crt);

  if (key_issuer)

    gnutls_x509_privkey_deinit(key_issuer);

  if (crt_issuer)

    gnutls_x509_crt_deinit(crt_issuer);



  gnutls_global_deinit();



  return 0;

}




More information about the Gnutls-help mailing list