Discussion:
How to convert from PEM to DER format?
(too old to reply)
Srivardhan Hebbar
2013-01-29 09:57:16 UTC
Permalink
Hi,

I have a string which has the certificate in PEM(Base64) format. I want to
convert it to DER format(unsigned char). How can I do it?

I wrote the following code:
BIO *certBio = BIO_new(BIO_s_mem());
int len = BIO_puts(certBio,value.c_str());
if (len < 1) {
BIO_free(certBio);
return ERROR;
}
BIO *bp = certBio;
X509 *x = PEM_read_bio_X509(bp,NULL,0,NULL);
if (NULL == x) {
BIO_free(certBio);
return ERROR;
}
unsigned char *certUc = (unsigned char *) malloc (4 * 1024);
unsigned char *out = certUc;
len = i2d_X509(x,&out);
if (len < 1) {
BIO_free(certBio);
X509_free(x);
free(certUc);
return ERROR;
}

This code is compiled using c++ compiler. 'value' is a String which has the
certificate in base64 encoded format.

This code is failing. Am getting 'x' always null. Can anyone pls help me.

I want a DER encoded certificate in unsigned char format from the String.
Can anyone tell me the way.

Thank-you,
Sri
Dave Thompson
2013-02-05 00:17:22 UTC
Permalink
Sent: Tuesday, 29 January, 2013 04:57
I have a string which has the certificate in PEM(Base64) format.
I want to convert it to DER format(unsigned char). How can I do it?
I wrote the following code:<snip>
This code is failing. Am getting 'x' always null.
PEM is not just base64. PEM is base64 plus header and trailer lines,
here -----BEGIN CERTIFICATE---- and -----END CERTIFICATE----- .
Do you have that?

If not, either:

- add the header and trailer lines, then PEM_read and i2d as now --
except there is no guarantee that a (DER) certificate fits in 4K
bytes. Reasonable DNs, and practically usable pubkey and signature,
can't be much more than 1K, but CAs can, and some do, add the most
mind-boggling crud in extensions. Either call i2d_(,NULL) first to
determine the length and allocate that; or call it and check the
length fits in your fixed size before doing i2d_(,buffer);
or check the PEM (or just the base64) before decoding is not more
than about 5.3KC (which does guarantee the binary fits in 4KB).

- decode the base64 to binary directly. With OpenSSL you can
read it through a b64-BIO, or (undocumented) just call
EVP_DecodeBlock, or you can decode b64 in about 20 lines
of C (maybe 10 if you don't care about handling errors).
Unlike the above approach this does not check your data contains
a facially-valid cert (that is, it is correctly structured and
all required fields exist, but we don't know if it was properly
signed by a trusted CA and not expired or revoked). But if you
subsequently use the DER cert for anything, presumably that will
at least decode it and hopefully verify/validate it.

Aside: you could save some copies by creating a readonly mem-BIO
directly on the c++ std::string's internal buffer, instead of
.c_str() which may need to copy and BIO_puts which definitely does.
But unless you have many (or huge) certs this shouldn't matter much.


______________________________________________________________________
OpenSSL Project http://www.openssl.org
User Support Mailing List openssl-***@openssl.org
Automated List Manager ***@openssl.org
Srivardhan Hebbar
2013-02-06 04:53:30 UTC
Permalink
Thanks Dave,

EVP_DecodeBlock did the magic.

-Sri
Post by Dave Thompson
Sent: Tuesday, 29 January, 2013 04:57
I have a string which has the certificate in PEM(Base64) format.
I want to convert it to DER format(unsigned char). How can I do it?
I wrote the following code:<snip>
This code is failing. Am getting 'x' always null.
PEM is not just base64. PEM is base64 plus header and trailer lines,
here -----BEGIN CERTIFICATE---- and -----END CERTIFICATE----- .
Do you have that?
- add the header and trailer lines, then PEM_read and i2d as now --
except there is no guarantee that a (DER) certificate fits in 4K
bytes. Reasonable DNs, and practically usable pubkey and signature,
can't be much more than 1K, but CAs can, and some do, add the most
mind-boggling crud in extensions. Either call i2d_(,NULL) first to
determine the length and allocate that; or call it and check the
length fits in your fixed size before doing i2d_(,buffer);
or check the PEM (or just the base64) before decoding is not more
than about 5.3KC (which does guarantee the binary fits in 4KB).
- decode the base64 to binary directly. With OpenSSL you can
read it through a b64-BIO, or (undocumented) just call
EVP_DecodeBlock, or you can decode b64 in about 20 lines
of C (maybe 10 if you don't care about handling errors).
Unlike the above approach this does not check your data contains
a facially-valid cert (that is, it is correctly structured and
all required fields exist, but we don't know if it was properly
signed by a trusted CA and not expired or revoked). But if you
subsequently use the DER cert for anything, presumably that will
at least decode it and hopefully verify/validate it.
Aside: you could save some copies by creating a readonly mem-BIO
directly on the c++ std::string's internal buffer, instead of
.c_str() which may need to copy and BIO_puts which definitely does.
But unless you have many (or huge) certs this shouldn't matter much.
______________________________________________________________________
OpenSSL Project http://www.openssl.org
Loading...