[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