Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Program to convert private key from pem to der format

1,172 views
Skip to first unread message

phildoch

unread,
Jul 24, 2014, 9:13:45 AM7/24/14
to
Hello,

I currently have a short program that converts a certificate from pem format
to der format.

static int vpncm_convert_pem_to_der(struct cm_module *module, char
*pem_file_name, char *der_file_name )
{

int res,ret = 0;
FILE* f;
BIO *out = NULL;
X509 *loaded = NULL;


f = fopen( pem_file_name,"r");

if(f != NULL)
{
/*Read the cert into structure*/
loaded = PEM_read_X509(f, NULL, NULL, NULL);
if(loaded)
{
/*write from the internal X509 to pemfile*/
out = BIO_new(BIO_s_file());
if(out != NULL)
{
/*der_file_name is the file's name for der certificate*/
if(BIO_write_filename(out, der_file_name) > 0)
{
/*Convert the pem structure to der and save it in der
file.*/
res = i2d_X509_bio(out, loaded);

}
fclose(f);
BIO_free_all(out);
}

return ret;
}

I would like to do the same, i.e. convert from pem to der, for a private key
file. The key may have been generated either with ecdsa or rsa 2048/4096
algorithm.
May I use the program above and just replace a few openssl api's, or is it
more complicated?
Can someone share a piece of code that does the job?

Thanks



--
View this message in context: http://openssl.6102.n7.nabble.com/Program-to-convert-private-key-from-pem-to-der-format-tp52282.html
Sent from the OpenSSL - User mailing list archive at Nabble.com.
______________________________________________________________________
OpenSSL Project http://www.openssl.org
User Support Mailing List openss...@openssl.org
Automated List Manager majo...@openssl.org

Salz, Rich

unread,
Jul 24, 2014, 9:16:55 AM7/24/14
to
Just do base64 decode.

--
Principal Security Engineer, Akamai Technologies, Cambridge, MA
IM: rs...@jabber.me; Twitter: RichSalz

Viktor Dukhovni

unread,
Jul 24, 2014, 9:27:30 AM7/24/14
to
On Thu, Jul 24, 2014 at 06:13:45AM -0700, phildoch wrote:

> I currently have a short program that converts a certificate from pem format
> to der format.

PEM and DER are strictly speaking encodings, not formats. The
underlying data is identical, an ASN.1 DER X.509v3 certificate,
which in the PEM case is converted to base64 and enclosed in
"-----BEGIN CERTIFICATE" ... "-----END CERTIFICATE" armour.

> I would like to do the same, i.e. convert from pem to der, for a private key
> file.

This is a more complex question, because now you really need to
think about formats. Private keys can be in algorithm-specific
PEM formats, algorithm neutral PKCS8 format, PKCS12 format (key +
certificate chain, and other metadata) Microsoft's PVK format, ...

So you need to decide on the right format first, and then worry
about which encodinds (PEM vs. binary ASN.1 DER) that format
supports.

What key format is needed by the system that will be using the key?

--
Viktor.

phildoch

unread,
Jul 24, 2014, 11:07:01 AM7/24/14
to
Viktor,

The key format needed by the system is algorithm-specific DER format. It is
received from the user in the same algorithm-specific in PEM format.
The algorithm can be:
1) secp384r1 (i.e. created by "openssl ecparam -out ec_key.pem -name
secp384r1 -genkey")
2) rsa:2048 (i.e. created by "openssl genrsa -out rsa2048_key.pem 2048)
3) rsa:4096 (i.e. created by "openssl genrsa -out rsa4096_key.pem 4096)


I tried to create a program based on the code of the command "openssl pkey
-in key.pem -outform DER -out keyout.der" in file /apps/pkey.c in openssl
project. I suppressed what I thought was not needed:

static int convert_key_pem_to_der(struct cm_module *module, char
*pem_key_file_name, char *der_key_file_name )
{
BIO *in = NULL, *out = NULL;
EVP_PKEY *pkey=NULL;
BIO *bio_err;

int ret = 0;

bio_err = BIO_new_fp (stderr, BIO_NOCLOSE);

ERR_load_crypto_strings();
OpenSSL_add_all_algorithms();

if (!(out = BIO_new_file (der_key_file_name, "wb")))
{
ret = 1;
printf("Can't open output file %s", der_key_file_name);
}
else
{
pkey = load_key(bio_err, pem_key_file_name, FORMAT_PEM, 1, NULL,
NULL, "key");

if (!pkey)
{
printf("Can't load key from file %s", pem_key_file_name);
ret = 1;
}
else
{
i2d_PrivateKey_bio(out, pkey);
}
}

EVP_PKEY_free(pkey);
BIO_free_all(out);
BIO_free(in);

return ret;
}

EVP_PKEY *load_key(BIO *err, const char *file, int format, int maybe_stdin,
const char *pass, ENGINE *e, const char *key_descrip)
{
BIO *key=NULL;
EVP_PKEY *pkey=NULL;

key=BIO_new(BIO_s_file());
if (key == NULL)
{
ERR_print_errors(err);
goto end;
}

if (BIO_read_filename(key,file) <= 0)
{
BIO_printf(err, "Error opening %s %s\n", key_descrip, file);
ERR_print_errors(err);
goto end;
}

/* Read from PEM format file*/
pkey=PEM_read_bio_PrivateKey(key, NULL, NULL, NULL);

end:
if (key != NULL) BIO_free(key);
if (pkey == NULL)
{
BIO_printf(err,"unable to load %s\n", key_descrip);
ERR_print_errors(err);
}
return(pkey);
}


But using this program, the DER file obtained in output is different of the
one I obtain when using the openssl command (it is about half size only).
When I try to convert is back to PEM I get the following errors:
openssl pkey -inform DER -in key.der -outform PEM -out key_after.pem
unable to load key
1073868400:error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong
tag:tasn_dec.c:1319:
1073868400:error:0D06C03A:asn1 encoding
routines:ASN1_D2I_EX_PRIMITIVE:nested asn1 error:tasn_dec.c:831
:
1073868400:error:0D08303A:asn1 encoding
routines:ASN1_TEMPLATE_NOEXP_D2I:nested asn1 error:tasn_dec.c:7
51:Field=version, Type=PKCS8_PRIV_KEY_INFO
1073868400:error:0D0CF0A7:asn1 encoding
routines:d2i_AutoPrivateKey:unsupported public key type:d2i_pr.c:157:

Any help would be appreciated.
Thanks.





--
View this message in context: http://openssl.6102.n7.nabble.com/Program-to-convert-private-key-from-pem-to-der-format-tp52282p52286.html
Sent from the OpenSSL - User mailing list archive at Nabble.com.

Viktor Dukhovni

unread,
Jul 24, 2014, 2:17:49 PM7/24/14
to
On Thu, Jul 24, 2014 at 08:07:01AM -0700, phildoch wrote:

> The key format needed by the system is algorithm-specific DER format.

I am not aware of any standard formats for keys other than PKCS#8
or PKCS#12. In particular, the algorithm-specific PEM encodings
output by "openssl rsa|ec" are I believe non-standard, and their
DER forms are even more so supported on an ad-hoc basis.

Note that the pkey(1) utility included with OpenSSL 1.0.0, reads
any of the various ad-hoc formats in either PEM or DER encoding,
but outputs PKCS#8. Thus:

openssl ec -outform DER | openssl pkey -inform DER

is not an identity transformation, as can be seen by looking at
the ASN.1 with asn1parse(1).

> It is received from the user in the same algorithm-specific in PEM format.
> The algorithm can be:
>
> 1) secp384r1 (i.e. created by "openssl ecparam -out ec_key.pem -name
> secp384r1 -genkey")

This outputs an ad-hoc algorithm-specific PEM encoding.

> 2) rsa:2048 (i.e. created by "openssl genrsa -out rsa2048_key.pem 2048)
> 3) rsa:4096 (i.e. created by "openssl genrsa -out rsa4096_key.pem 4096)

As do these. What software could possibly want to consume these in
DER encoding, rather than as a DER-encoded PKCS#8 object?

> I tried to create a program based on the code of the command "openssl pkey
> -in key.pem -outform DER -out keyout.der" in file /apps/pkey.c in openssl
> project.

This reads any of the various legacy formats and outputs DER-encoded
PKCS#8.

> Any help would be appreciated.

You still have not explained which software is going to consume
these keys, and why it expects to consume the legacy ad-hoc OpenSSL
key formats in DER form.

--
Viktor.

Dave Thompson

unread,
Jul 28, 2014, 3:15:47 AM7/28/14
to
> From: owner-ope...@openssl.org On Behalf Of Viktor Dukhovni
> Sent: Thursday, July 24, 2014 14:18

> On Thu, Jul 24, 2014 at 08:07:01AM -0700, phildoch wrote:
>
> > The key format needed by the system is algorithm-specific DER format.
>
> I am not aware of any standard formats for keys other than PKCS#8
> or PKCS#12. In particular, the algorithm-specific PEM encodings
> output by "openssl rsa|ec" are I believe non-standard, and their
> DER forms are even more so supported on an ad-hoc basis.
>
RSA is PKCS1, and EC is X9.62 (according to SECG1 and rfc3279).

PKCS8 only defines the wrapper, basically AlgId and optional PKCS5 PBE.
It leaves the chocolately inside to other standards, including
but not limited to those above.

PKCS12 defines an outer wrapper and uses PKCS8 for privatekey "bag".

AFAICS the more flexible PKCS12 and to some extent PKCS8 are
indeed more widely used/supported.

> Note that the pkey(1) utility included with OpenSSL 1.0.0, reads
> any of the various ad-hoc formats in either PEM or DER encoding,
> but outputs PKCS#8. Thus:
>
> openssl ec -outform DER | openssl pkey -inform DER
>
> is not an identity transformation, as can be seen by looking at
> the ASN.1 with asn1parse(1).
>
(And even in 0.9 pkcs8 -topk8 could do that, but the OP is
obviously on 1.0.0 or higher.)

> > It is received from the user in the same algorithm-specific in PEM
format.
> > The algorithm can be:
> >
> > 1) secp384r1 (i.e. created by "openssl ecparam -out ec_key.pem -name
> > secp384r1 -genkey")
>
> This outputs an ad-hoc algorithm-specific PEM encoding.
>
> > 2) rsa:2048 (i.e. created by "openssl genrsa -out rsa2048_key.pem
2048)
> > 3) rsa:4096 (i.e. created by "openssl genrsa -out rsa4096_key.pem
4096)
>
> As do these. What software could possibly want to consume these in
> DER encoding, rather than as a DER-encoded PKCS#8 object?
>
Any that uses the d2i_{alg}PrivateKey routine(s) which handle
only the matching alg-specific format, unlike d2i_PrivateKey which
handles all algorithms using a really ugly guessing game.

In contrast PEM_read_{alg,PKCS8,}PrivateKey can all recognize
and parse both PKCS8 and alg-spec formats from the BEGIN line;
the only difference is that {RSA,DSA,EC}PrivateKey then gives an
error if the key is not the corrrect algorithm (in either format)

> > I tried to create a program based on the code of the command "openssl
> pkey
> > -in key.pem -outform DER -out keyout.der" in file /apps/pkey.c in
openssl
> > project.
>
> This reads any of the various legacy formats and outputs DER-encoded
> PKCS#8.
>
(In 1.0.0+. In 0.9.8 i2d_PrivateKey, or PEM_write_PrivateKey,
dispatches to the various alg-specific formats; only the PKCS8PrivateKey or
PKCS8_PRIV_KEY_INFO versions do PKCS8.)
0 new messages