I'm trying to write a X509 Cert to DER format in memory. Writing it to a file works perfectly.
I need the Cert in PEM format without the "-----BEGIN PRIVATE KEY-----" header, footer or newlines. I can't figure out how to do it directly so... I'm outputting to der and base64 encoding.
THIS WORKS.
int X509_to_DER_file(X509 *cert) {
int res=0;
out = BIO_new(BIO_s_file());
if (NULL != out) {
if(BIO_write_filename(out, "my.der") > 0) {
res = i2d_X509_bio(out, cert);
}
BIO_free_all(out);
}
return (tres);
}
THIS DOES NOT. It returns and mallocs the correct number of bytes and appears to write out to memory correctly but the resulting string is incorrect (the first 15 or so positions are correct).
char *X509_to_DER_mem(X509 *cert) {
char *der = NULL;
bio = BIO_new(BIO_s_mem());
if (NULL != bio) {
//load cert into bio
if (0 == i2d_X509_bio(bio, cert)) {
BIO_flush(bio);
BIO_free(bio);
return NULL;
}
der = (char *) malloc(bio->num_write + 1);
if (NULL == der) {
BIO_free(bio);
return NULL;
}
memset(der, 0, bio->num_write + 1);
BIO_read(bio, der, bio->num_write);
// Appears to work put "der" is incomplete.
BIO_free(bio);
}
return der;
}
It returns and mallocs the correct number of bytes and appears to write out to memory correctly but the resulting string is incorrect
The result of i2d_X509_bio()
is not a (zero-terminated) string, but a bunch of bytes. If you try to write it to a file as a string, it might look incomplete because you might encounter a 0-byte at a location before you reach the end. So in addition to the char *
result, your function X509_to_DER_mem()
will have to return the number of bytes that make up the result.
With regard to the memory BIO
, another way of obtaining its data is with the BIO_get_mem_data()
function. Something like this:
char *ptr = NULL;
long len = BIO_get_mem_data(bio, &ptr);
der = malloc(len);
memcpy(der, ptr, len);
Finally, your actual question is
I need the Cert in PEM format without the "-----BEGIN PRIVATE KEY-----" header, footer or newlines.
Writing the certificate in DER format does not seem to give you what you need. This answer to another SO question explains how you could use the function PEM_read_bio()
in combination with EVP_EncodeBlock()
for that purpose.