Pkcs7 en C con OpenSSL.
En esta entrada muestro código de ejemplo para poder firmar un mensaje según la especificación Pkcs 7. Para hacerlo aprovecho el api que brinda el proyecto OpenSSL. Por razones obvias el lenguaje de programación es C.
Una vez generado el binario ejecutable del siguiente código, tendremos una aplicación de terminal, que recibe tres parámetros:
- ruta del archivo del certificado X509. Dicho archivo puede estar en formato PEM o DER.
- ruta del archivo de la clave privada. También el formato puede ser PEM o DER.
- mensaje para firmar.
Para finalizar se imprime por stdout el resultado.
Para compilar:
Evidentemente deben estar instalados OpenSSL y sus headers de desarrollo para poder compilar.
A continuación el ejemplo:
Una vez generado el binario ejecutable del siguiente código, tendremos una aplicación de terminal, que recibe tres parámetros:
- ruta del archivo del certificado X509. Dicho archivo puede estar en formato PEM o DER.
- ruta del archivo de la clave privada. También el formato puede ser PEM o DER.
- mensaje para firmar.
Para finalizar se imprime por stdout el resultado.
Para compilar:
jaa@dino-thunder_ng ~/taller $ gcc pkcs7_sign.c -o pkcs7_sign -lssl
Evidentemente deben estar instalados OpenSSL y sus headers de desarrollo para poder compilar.
A continuación el ejemplo:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/x509.h>
extern FILE *stderr;
char * pkcs7_sign
(char * certfile,
char * keyfile,
char * message,
char * cert_passwd,
char * key_passwd);
int main (int argc, char ** argv)
{
char * pk7sm= NULL;
if (argc != 4)
{
printf ("MODO DE USO: %s cert_file key_file, message\\n",argv[0]);
exit (1);
}
pk7sm=pkcs7_sign (argv[1],argv[2],argv[3],NULL,NULL);
if (pk7sm != NULL)
printf ("%s",pk7sm);
else
{
fprintf (stderr, "Error inesperado.\\n");
exit (1);
}
exit (0);
}
X509 * load_file (char * fname)
{
FILE * fp = NULL;
X509 * cert = NULL;
fp = fopen ((const char *)fname, "r");
if (fp == NULL)
{
perror ("fopen()");
return NULL;
}
cert = d2i_X509_fp(fp, NULL);
if (cert != NULL)
goto success;
if (cert == NULL)
{
rewind (fp);
cert = (X509 *)PEM_read_X509 (fp, NULL, NULL, NULL);
}
success:
fclose (fp);
return cert;
}
EVP_PKEY * load_key_file (char * fname)
{
FILE * fp = NULL;
EVP_PKEY * pkey = NULL;
fp = fopen ((const char *)fname, "r");
if (fp == NULL)
{
perror ("fopen()");
return NULL;
}
pkey = d2i_PrivateKey_fp (fp, NULL);
if (pkey != NULL)
goto success;
if (pkey == NULL)
{
rewind (fp);
pkey = (EVP_PKEY *) PEM_read_PrivateKey (fp, NULL, NULL, NULL);
}
success:
fclose (fp);
return pkey;
}
char * pkcs7_sign
(char * certfile,
char * keyfile,
char * message,
char * cert_passwd,
char * key_passwd)
{
PKCS7 * scms = NULL;
X509 * cert = NULL;
EVP_PKEY * pkey = NULL;
BIO * message_bio = NULL;
BIO * signed_message= NULL;
char * bio_data_ptr = NULL;
char * smessage = NULL;
long bio_data_len = 0;
cert = load_file (certfile);
if (cert == NULL)
{
fprintf (stderr,"Formato de certificado no valido: DER o PEM\\n");
goto finally;
}
pkey = load_key_file (keyfile);
if (pkey == NULL)
{
fprintf (stderr,"Formato de clave no valido: DER o PEM\\n");
goto finally;
}
message_bio = BIO_new_mem_buf (message, strlen(message));
if (message_bio == NULL)
{
fprintf (stderr,"Error creando buffer.\\n");
goto finally;
}
SSL_library_init();
scms = PKCS7_sign (cert, pkey, NULL, message_bio, PKCS7_DETACHED);
if (scms == NULL)
{
long err= ERR_get_error ();
char * err_txt = (char *)ERR_error_string (err);
fprintf (stderr,"Error firmando pkcs7 (%i): %s\\n",\\
(int)err,((err_txt==NULL)?" ":err_txt));
goto finally;
}
signed_message = BIO_new (BIO_s_mem());
if (signed_message == NULL)
{
fprintf (stderr,"Error creando buffer.\\n");
goto finally;
}
if (PEM_write_bio_PKCS7 (signed_message, scms) <= 0)
{
fprintf (stderr,"Error transportando a PEM.\\n");
goto finally;
}
bio_data_len =BIO_get_mem_data (signed_message, &bio_data_ptr);
smessage = (char *)malloc (bio_data_len + 1);
if (smessage == NULL)
{
perror ("malloc ()");
goto finally;
}
memcpy (smessage, bio_data_ptr, bio_data_len);
*(smessage+bio_data_len)=\'\\0\';
finally:
if (message_bio != NULL)
BIO_free(message_bio);
if (signed_message != NULL)
BIO_free(signed_message);
if (cert != NULL)
X509_free(cert);
if (pkey != NULL)
EVP_PKEY_free(pkey);
return smessage;
}
Etiquetas: C language, firma digital, pk7 sign, programacion, programación

0 comentarios:
Publicar un comentario en la entrada
Suscribirse a Enviar comentarios [Atom]
<< Página principal