Saltar al contenido

Crear certificado X509 mediante programación con OpenSSL

Nuestro grupo de redactores ha pasado mucho tiempo buscando para dar soluciones a tus preguntas, te compartimos la soluciones así que esperamos resultarte de gran apoyo.

Solución:

Me doy cuenta de que esta es una respuesta muy tardía (y larga). Pero considerando qué tan bien esta pregunta parece clasificarse en los resultados de los motores de búsqueda, pensé que valdría la pena escribir una respuesta decente.

Mucho de lo que leerá a continuación se tomó prestado de esta demostración y de los documentos de OpenSSL. El código siguiente se aplica tanto a C como a C ++.


Antes de que podamos crear un certificado, necesitamos crear un key. OpenSSL proporciona la EVP_PKEY estructura para almacenar un algoritmo privado independiente key en memoria. Esta estructura está declarada en openssl/evp.h pero está incluido por openssl/x509.h (que necesitaremos más adelante) por lo que realmente no es necesario incluir explícitamente el encabezado.

Para asignar un EVP_PKEY estructura, usamos EVP_PKEY_new:

EVP_PKEY * pkey;
pkey = EVP_PKEY_new();

También hay una función correspondiente para liberar la estructura: EVP_PKEY_free – que acepta un solo argumento: el EVP_PKEY estructura inicializada arriba.

Ahora necesitamos generar un key. Para nuestro ejemplo, generaremos un RSA key. Esto se hace con el RSA_generate_key función que se declara en openssl/rsa.h. Esta función devuelve un puntero a un RSA estructura.

Una simple invocación de la función podría verse así:

RSA * rsa;
rsa = RSA_generate_key(
    2048,   /* number of bits for the key - 2048 is a sensible value */
    RSA_F4, /* exponent - RSA_F4 is defined as 0x10001L */
    NULL,   /* callback - can be NULL if we aren't displaying progress */
    NULL    /* callback argument - not needed in this case */
);

Si el valor de retorno de RSA_generate_key es NULL, entonces algo salió mal. Si no, entonces ahora tenemos un RSA keyy podemos asignarlo a nuestro EVP_PKEY estructura de antes:

EVP_PKEY_assign_RSA(pkey, rsa);

los RSA La estructura se liberará automáticamente cuando el EVP_PKEY la estructura se libera.


Ahora para el certificado en sí.

OpenSSL utiliza el X509 estructura para representar un certificado x509 en la memoria. La definición de esta estructura está en openssl/x509.h. La primera función que vamos a necesitar es X509_new. Su uso es relativamente sencillo:

X509 * x509;
x509 = X509_new();

Como fue el caso con EVP_PKEY, hay una función correspondiente para liberar la estructura – X509_free.

Ahora necesitamos establecer algunas propiedades del certificado usando algunos X509_* funciones:

ASN1_INTEGER_set(X509_get_serialNumber(x509), 1);

Esto establece el número de serie de nuestro certificado en ‘1’. Algunos servidores HTTP de código abierto se niegan a aceptar un certificado con un número de serie “0”, que es el predeterminado. El siguiente paso es especificar el período de tiempo durante el cual el certificado es realmente válido. Hacemos eso con las siguientes dos llamadas a funciones:

X509_gmtime_adj(X509_get_notBefore(x509), 0);
X509_gmtime_adj(X509_get_notAfter(x509), 31536000L);

La primera línea establece el certificado notBefore propiedad a la hora actual. (Los X509_gmtime_adj La función agrega el número especificado de segundos a la hora actual; en este caso, ninguno.) La segunda línea establece el certificado notAfter propiedad a 365 días a partir de ahora (60 segundos * 60 minutos * 24 horas * 365 días).

Ahora tenemos que configurar el público key para nuestro certificado usando el key que generamos antes:

X509_set_pubkey(x509, pkey);

Dado que se trata de un certificado autofirmado, establecemos el nombre del emisor con el nombre del sujeto. El primer paso en ese proceso es obtener el nombre del sujeto:

X509_NAME * name;
name = X509_get_subject_name(x509);

Si alguna vez ha creado un certificado autofirmado en la línea de comando, probablemente recuerde que se le pidió un código de país. Aquí es donde lo proporcionamos junto con la organización (‘O’) y el nombre común (‘CN’):

X509_NAME_add_entry_by_txt(name, "C",  MBSTRING_ASC,
                           (unsigned char *)"CA", -1, -1, 0);
X509_NAME_add_entry_by_txt(name, "O",  MBSTRING_ASC,
                           (unsigned char *)"MyCompany Inc.", -1, -1, 0);
X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
                           (unsigned char *)"localhost", -1, -1, 0);

(Estoy usando el valor “CA” aquí porque soy canadiense y ese es nuestro código de país. También tenga en cuenta que el parámetro n. ° 4 debe convertirse explícitamente en un unsigned char *.)

Ahora podemos establecer el nombre del emisor:

X509_set_issuer_name(x509, name);

Y finalmente estamos listos para realizar el proceso de firma. Llamamos X509_sign con el key que generamos antes. El código para esto es dolorosamente simple:

X509_sign(x509, pkey, EVP_sha1());

Tenga en cuenta que estamos utilizando el algoritmo hash SHA-1 para firmar el key. Esto difiere del mkcert.c demo que mencioné al comienzo de esta respuesta, que usa MD5.


¡Ahora tenemos un certificado autofirmado! Pero aún no hemos terminado, tenemos que escribir estos archivos en el disco. Afortunadamente, OpenSSL nos tiene cubiertos allí también con el PEM_* funciones que se declaran en openssl/pem.h. El primero que necesitaremos es PEM_write_PrivateKey por salvar nuestro privado key.

FILE * f;
f = fopen("key.pem", "wb");
PEM_write_PrivateKey(
    f,                  /* write the key to the file we've opened */
    pkey,               /* our key from earlier */
    EVP_des_ede3_cbc(), /* default cipher for encrypting the key on disk */
    "replace_me",       /* passphrase required for decrypting the key on disk */
    10,                 /* length of the passphrase string */
    NULL,               /* callback for requesting a password */
    NULL                /* data to pass to the callback */
);

Si no desea cifrar lo privado key, luego simplemente pase NULL para el tercer y cuarto parámetro anteriores. De cualquier manera, definitivamente querrá asegurarse de que el archivo no sea legible por todo el mundo. (Para los usuarios de Unix, esto significa chmod 600 key.pem.)

¡Uf! Ahora nos quedamos con una función: tenemos que escribir el certificado en el disco. La función que necesitamos para esto es PEM_write_X509:

FILE * f;
f = fopen("cert.pem", "wb");
PEM_write_X509(
    f,   /* write the certificate to the file we've opened */
    x509 /* our certificate */
);

¡Y hemos terminado! Con suerte, la información en esta respuesta es suficiente para darle una idea aproximada de cómo funciona todo, aunque apenas hemos arañado la superficie de OpenSSL.

Para aquellos interesados ​​en ver cómo se ve todo el código anterior en una aplicación real, he reunido un Gist (escrito en C ++) que pueden ver aquí.

Primero deberá familiarizarse con la terminología y los mecanismos.

Un X.509 certificado, por definición, no incluye un key. En cambio, es una versión firmada por una CA del público key (junto con cualquier attributes la CA pone en la firma). El formato PEM realmente solo admite el almacenamiento separado de key y el certificado, aunque luego puede concatenar los dos.

En cualquier caso, deberá invocar más de 20 funciones diferentes de la API de OpenSSL para crear una key y un certificado autofirmado. Un ejemplo está en la propia fuente OpenSSL, en demos / x509 / mkcert.c

Para obtener una respuesta más detallada, consulte la explicación de Nathan Osman a continuación.

Cualquier posibilidad de hacer esto a través de un system llamar desde dentro de su aplicación? Varias buenas razones para hacer esto:

  • Licencias: Llamar al openssl podría decirse que el ejecutable lo separa de su aplicación y puede proporcionar ciertas ventajas. Descargo de responsabilidad: consulte a un abogado al respecto.

  • Documentación: OpenSSL viene con fenomenal documentación de línea de comandos que simplifica enormemente una herramienta potencialmente complicada.

  • Capacidad de prueba: puede ejercitar OpenSSL desde la línea de comandos hasta que comprenda exactamente cómo crear sus certificados. Hay un lote de opciones; espere dedicar alrededor de un día a esto hasta que tenga todos los detalles correctos. Después de eso, es trivial incorporar el comando en su aplicación.

Si opta por utilizar la API, marque la openssl-dev lista de desarrolladores en www.openssl.org.

¡Buena suerte!

Puntuaciones y reseñas

Si guardas alguna perplejidad o disposición de enriquecer nuestro escrito eres capaz de realizar una crítica y con gusto lo leeremos.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *