[ << ] | [ < ] | [ Up ] | [ > ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
6.3 Managing encrypted keys
Transferring or storing private keys in plain might not be a good idea. Any access on the keys becomes a fatal compromise. Storing the keys in hardware tokens (see Security modules) could solve the storage problem but it is not always practical or efficient enough. This section describes alternative ways that involve encryption of the private keys to store and transfer.
There are two alternatives to use for key encryption, PKCS #8 and #12 methods of private key encryption. The PKCS #8 method only allows encryption of the private key, whilst the PKCS #12 method allows in addition the bundling of other data into the structure. That could be bundling together the certificate as well as the trusted CA certificate.
PKCS #8 structures
PKCS #8 keys can be imported and exported as normal private keys using
the functions below. An addition to the normal import functions, are
a password and a flags argument. The flags can be any element of the gnutls_pkcs_encrypt_flags_t
enumeration. Note however, that GnuTLS only supports the PKCS #5 PBES2
encryption scheme. Keys encrypted with the obsolete PBES1 scheme cannot
be decrypted.
- GNUTLS_PKCS_PLAIN Unencrypted private key.
- GNUTLS_PKCS8_PLAIN
Same as
GNUTLS_PKCS_PLAIN
. - GNUTLS_PKCS_USE_PKCS12_3DES PKCS-12 3DES.
- GNUTLS_PKCS8_USE_PKCS12_3DES
Same as
GNUTLS_PKCS_USE_PKCS12_3DES
. - GNUTLS_PKCS_USE_PKCS12_ARCFOUR PKCS-12 ARCFOUR.
- GNUTLS_PKCS8_USE_PKCS12_ARCFOUR
Same as
GNUTLS_PKCS_USE_PKCS12_ARCFOUR
. - GNUTLS_PKCS_USE_PKCS12_RC2_40 PKCS-12 RC2-40.
- GNUTLS_PKCS8_USE_PKCS12_RC2_40
Same as
GNUTLS_PKCS_USE_PKCS12_RC2_40
. - GNUTLS_PKCS_USE_PBES2_3DES PBES2 3DES.
- GNUTLS_PKCS_USE_PBES2_AES_128 PBES2 AES-128.
- GNUTLS_PKCS_USE_PBES2_AES_192 PBES2 AES-192.
- GNUTLS_PKCS_USE_PBES2_AES_256 PBES2 AES-256.
Table 6.2
PKCS #12 structures
A PKCS #12 structure [PKCS12] usually contains a user’s private keys and certificates. It is commonly used in browsers to export and import the user’s identities.
In GnuTLS the PKCS #12 structures are handled
using the gnutls_pkcs12_t
type. This is an abstract type that
may hold several gnutls_pkcs12_bag_t
types. The bag types are
the holders of the actual data, which may be certificates, private
keys or encrypted data. A bag of type encrypted should be decrypted
in order for its data to be accessed.
The following functions are available to read a PKCS #12 structure.
- gnutls_pkcs12_bag_get_count
- gnutls_pkcs12_bag_get_data
- gnutls_pkcs12_bag_get_key_id
- gnutls_pkcs12_bag_get_friendly_name
The functions below are used to generate a PKCS #12 structure. An example of their usage is also shown.
- gnutls_pkcs12_bag_set_data
- gnutls_pkcs12_bag_set_crl
- gnutls_pkcs12_bag_set_crt
- gnutls_pkcs12_bag_set_key_id
- gnutls_pkcs12_bag_set_friendly_name
/* This example code is placed in the public domain. */ #ifdef HAVE_CONFIG_H #include <config.h> #endif #include <stdio.h> #include <stdlib.h> #include <gnutls/gnutls.h> #include <gnutls/pkcs12.h> #include "examples.h" #define OUTFILE "out.p12" /* This function will write a pkcs12 structure into a file. * cert: is a DER encoded certificate * pkcs8_key: is a PKCS #8 encrypted key (note that this must be * encrypted using a PKCS #12 cipher, or some browsers will crash) * password: is the password used to encrypt the PKCS #12 packet. */ int write_pkcs12 (const gnutls_datum_t * cert, const gnutls_datum_t * pkcs8_key, const char *password) { gnutls_pkcs12_t pkcs12; int ret, bag_index; gnutls_pkcs12_bag_t bag, key_bag; char pkcs12_struct[10 * 1024]; size_t pkcs12_struct_size; FILE *fd; /* A good idea might be to use gnutls_x509_privkey_get_key_id() * to obtain a unique ID. */ gnutls_datum_t key_id = { (char *) "\x00\x00\x07", 3 }; gnutls_global_init (); /* Firstly we create two helper bags, which hold the certificate, * and the (encrypted) key. */ gnutls_pkcs12_bag_init (&bag); gnutls_pkcs12_bag_init (&key_bag); ret = gnutls_pkcs12_bag_set_data (bag, GNUTLS_BAG_CERTIFICATE, cert); if (ret < 0) { fprintf (stderr, "ret: %s\n", gnutls_strerror (ret)); return 1; } /* ret now holds the bag's index. */ bag_index = ret; /* Associate a friendly name with the given certificate. Used * by browsers. */ gnutls_pkcs12_bag_set_friendly_name (bag, bag_index, "My name"); /* Associate the certificate with the key using a unique key * ID. */ gnutls_pkcs12_bag_set_key_id (bag, bag_index, &key_id); /* use weak encryption for the certificate. */ gnutls_pkcs12_bag_encrypt (bag, password, GNUTLS_PKCS_USE_PKCS12_RC2_40); /* Now the key. */ ret = gnutls_pkcs12_bag_set_data (key_bag, GNUTLS_BAG_PKCS8_ENCRYPTED_KEY, pkcs8_key); if (ret < 0) { fprintf (stderr, "ret: %s\n", gnutls_strerror (ret)); return 1; } /* Note that since the PKCS #8 key is already encrypted we don't * bother encrypting that bag. */ bag_index = ret; gnutls_pkcs12_bag_set_friendly_name (key_bag, bag_index, "My name"); gnutls_pkcs12_bag_set_key_id (key_bag, bag_index, &key_id); /* The bags were filled. Now create the PKCS #12 structure. */ gnutls_pkcs12_init (&pkcs12); /* Insert the two bags in the PKCS #12 structure. */ gnutls_pkcs12_set_bag (pkcs12, bag); gnutls_pkcs12_set_bag (pkcs12, key_bag); /* Generate a message authentication code for the PKCS #12 * structure. */ gnutls_pkcs12_generate_mac (pkcs12, password); pkcs12_struct_size = sizeof (pkcs12_struct); ret = gnutls_pkcs12_export (pkcs12, GNUTLS_X509_FMT_DER, pkcs12_struct, &pkcs12_struct_size); if (ret < 0) { fprintf (stderr, "ret: %s\n", gnutls_strerror (ret)); return 1; } fd = fopen (OUTFILE, "w"); if (fd == NULL) { fprintf (stderr, "cannot open file\n"); return 1; } fwrite (pkcs12_struct, 1, pkcs12_struct_size, fd); fclose (fd); gnutls_pkcs12_bag_deinit (bag); gnutls_pkcs12_bag_deinit (key_bag); gnutls_pkcs12_deinit (pkcs12); return 0; }
[ << ] | [ < ] | [ Up ] | [ > ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This document was generated on January 4, 2012 using texi2html 5.0.