anterior índice siguiente

Firma/Verificación

EVP permite abstraer los procesos de firma y verificación. El usuario no tendrá que calcular el resumen del texto que desea firmar. Lo veremos en los dos apartados siguientes:


La firma

En primer lugar vamos a aprender a firmar. Veamos cuales son las funciones de inicialización, actualización y finalización:

  • void EVP_SignInit (EVP_MD_CTX *ctx, const EVP_MD *type)
  • void EVP_SignUpdate (EVP_MD_CTX *ctx, const void *d, unsigned int cnt)
  • int EVP_SignFinal (EVP_MD_CTX *ctx, unsigned char *sig, unsigned int *s, EVP_PKEY *pkey)

Vamos a entrar en calor.




Ejemplo 1. Firma una cadena de caracteres.

El ejemplo firma la cadena de caracteres apuntada por mensaje. Uno se da cuenta que no es necesario calcular explícitamente el message digest de mensaje (de hecho en la versión actual EVP_SignInit no hace más que una llamada a EVP_DigestInit).

Por lo que respecta a la inicialización (EVP_SignInit()), únicamente se especifica la función hash que se utilizará. Le remito a la parte de message digest para obtener una tabla con las funciones hash disponibles.

Por lo que respecta a la actualización ( EVP_SignUpdate() ), el segundo argumento apunta a un buffer en el que residen los datos que añadiremos a la firma. En nuestro caso, sólo el buffer mensaje. En el tercer argumento especificamos el número de bytes a tomar del buffer. Podemos llamar repetidas veces a EVP_SignUpdate() para añadir nuevos datos al contexto de la firma.

En cuanto a la finalización ( EVP_SignFinal() ) cabe hacer algunas puntualizaciones primero. Esta función va a devolvernos en el segundo argumento la firma, por lo que nuestro primer problema reside en averiguar qué cantidad de memoria va a ser necesaria para albergarla. Pues bien, a lo sumo EVP_PKEY_size() bytes de memoria (consulte el apartado Las claves en EVP).

EVP_SignFinal() devuelve en el tercer parámetro (salvo que este sea NULL) el tamaño en bytes de la firma. El último parámetro contiene la clave privada con la que firmaremos el mensaje. Devuelve 1 si la operación se ha llevado a cabo con éxito o 0 en caso de fallo.

Veamos otro ejemplo. Ahora vamos a firmar la información que nos llegue por la entrada estándar. Para ello leeremos la clave privada de un fichero en formato PEM. Puede generar usted mismo una clave rsa de 1024 bits con el comando:

openssl genrsa -out clave.pem 1024




Ejemplo 2. Firmamos la entrada estándar.

Puede encontrar información relativa a OpenSSL/PEM en el tutorial NISU de Mario Prats y Rafa Forcada. No se inquiete!! No es necesario que lo aprenda ahora. Vamos ahora a verificar la firma...


La verificación

El proceso de verificación posee de sus propias funciones de inicialización, actualización y finalización. Son las siguientes:

  • void EVP_VerifyInit(EVP_MD_CTX *ctx, const EVP_MD *type);
  • void EVP_VerifyUpdate(EVP_MD_CTX *ctx, const void *d, unsigned int cnt);
  • int EVP_VerifyFinal (EVP_MD_CTX *ctx, unsigned char *sigbuf, unsigned int siglen, EVP_PKEY *pkey);

Los prototipos son prácticamente idénticos a los de la firma. Describamos las funciones antes de ver un ejemplo.

La función de inicialización (EVP_VerifyInit()) inicializa el contexto con la función hash a utilizar. Recuerde la relación existente entre los algoritmos de clave pública y las funciones hash, ya que esta suele ser una fuente importante de problemas.

La función de actualización toma como entrada la información en claro (d) que va a verificarse. Básicamente se limita a calcular el message digest de la misma. Como viene siendo habitual, EVP_VerifyUpdate() puede llamarse repetidas para procesar la información de entrada por bloques.

La función de finalización, es la encargada de emitir el veredicto. Como parámetros toma la firma (sigbuf), la longitud de la firma (siglen) y la clave pública correspondiente a la clave privada con que se firma (pkey). Los valores devueltos por EVP_VerifyFinal() son 1 si la firma es correcta, 0 si no lo es y -1 en caso de error.

Muy bien, vamos a verificar una firma y para ello nos basaremos en el ejemplo 2. Además leeremos la clave pública correspondiente a la clave privada que firmó, de un certificado. Puede generarse un certificado autofirmado y una clave utilizando el siguiente comando:

openssl req -new -x509 -out cert.pem -newkey rsa:1024 -keyout clave.pem -nodes




Ejemplo 3. Verificación de firma.


anterior índice siguiente