para - Entender la inicialización del motor en OpenSSL
openssl linux (3)
De acuerdo, resulta que no tienes que usar un motor, pero no entendí exactamente cómo no usar un motor explícito. También malentendí cómo formatear correctamente los vectores de prueba. Al final, miré hmactest.c, que hace todo lo que quiero hacer, simplemente no entendí el código.
La solución final a lo que estaba tratando de hacer se ve así:
int main() {
unsigned char* key = (unsigned char*) "Jefe";
unsigned char* data = (unsigned char*) "what do ya want for nothing?";
unsigned char* expected = (unsigned char*) "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843";
unsigned char* result;
unsigned int result_len = 32;
int i;
static char res_hexstring[32];
result = HMAC(EVP_sha256(), key, 4, data, 28, NULL, NULL);
for (i = 0; i < result_len; i++) {
sprintf(&(res_hexstring[i * 2]), "%02x", result[i]);
}
if (strcmp((char*) res_hexstring, (char*) expected) == 0) {
printf("Test ok, result length %d/n", result_len);
} else {
printf("Got %s instead of %s/n", res_hexstring, expected);
}
}
Pero como estaba preguntando sobre algo completamente diferente, no estoy seguro de qué hacer con la pregunta original. Sugerencias?
Estoy intentando establecer una prueba básica de hash HMAC-SHA-256 pero estoy teniendo problemas con la configuración del motor. Idealmente, me gustaría configurar solo el algoritmo HMAC-SHA, pero hasta ahora no he tenido el caso general en el que cargar todos los algoritmos para trabajar. Actualmente obtengo seg_segmentos en la fila donde intento establecer los resúmenes por defecto.
Además, regularmente soy Java, así que no dudes en señalar cualquier error en el código.
#include <openssl/hmac.h>
#include <openssl/evp.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
unsigned char* key = (unsigned char*) "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b";
unsigned char* data = (unsigned char*) "4869205468657265";
unsigned char* expected = (unsigned char*) "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7";
unsigned char* result;
HMAC_CTX* ctx;
ENGINE* e;
ENGINE_load_builtin_engines();
ENGINE_register_all_complete();
ENGINE_set_default_digests(e);
HMAC_CTX_init(ctx);
HMAC_Init_ex(ctx, key, 40, EVP_sha256(), e);
result = HMAC(NULL, NULL, 40, data, 16, NULL, NULL);
HMAC_CTX_cleanup(ctx);
ENGINE_finish(e);
ENGINE_free(e);
if (strcmp((char*) result, (char*) expected) == 0) {
printf("Test ok/n");
} else {
printf("Got %s instead of %s/n", result, expected);
}
}
EDITAR: El programa ahora ha evolucionado a lo siguiente, pero todavía estoy segfaulting en HMAC_Init_ex
:
unsigned char* key = (unsigned char*) "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b";
unsigned char* data = (unsigned char*) "4869205468657265";
unsigned char* expected = (unsigned char*) "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7";
unsigned char* result;
unsigned int result_len = 64;
HMAC_CTX ctx;
ENGINE* e;
result = (unsigned char*) malloc(sizeof(char) * result_len);
e = (ENGINE*) ENGINE_new();
ENGINE_load_builtin_engines();
ENGINE_register_all_complete();
ENGINE_set_default_digests(e);
HMAC_CTX_init(&ctx);
HMAC_Init_ex(&ctx, key, 16, EVP_sha256(), e);
HMAC_Update(&ctx, data, 40);
HMAC_Final(&ctx, result, &result_len);
HMAC_CTX_cleanup(&ctx);
ENGINE_finish(e);
ENGINE_free(e);
Parece que nada está asignando un motor, por lo que el primer uso de e
es segfaulting. Creo que primero debe llamar a ENGINE *ENGINE_new(void)
.
(Tenga en cuenta que he usado OpenSSL, pero no he usado las funciones ENGINE
antes).
Actualización : no estoy muy contento con mi propia respuesta (tuve que irme al té, antes). Entonces mis notas adicionales son:
He
ENGINE_new
un vistazo a la página de manual (larga) para las funcionesENGINE
, y no estoy seguro de que sea suficiente llamar aENGINE_new
.No me di cuenta de que las llamadas a las funciones
HMAC_CTX_*
tomaban un puntero no inicializado, en lugar de un puntero a una estructura asignada.HMAC_CTX_init
intentará escribir en la memoria apuntada por su parámetroctx
, que segmentará. Necesitas declarar y usarctx
así:HMAC_CTX ctx; HMAC_CTX_init(&ctx); HMAC_Init_ex(&ctx, key, 40, EVP_sha256(), e); ...
De esta forma, estás asignando la estructura en la pila y luego pasando un puntero a ella.
La función
HMAC
no toma ningún puntero a unCTX
en absoluto, por lo que aparte del almacenamiento global o de subprocesos locales, no estoy seguro de cuál es su conexión con elCTX
. Creo que puede pasar porHMAC_Update
llamando aHMAC_Update
una o más veces, seguido deHMAC_Final
para obtener el resultado. Tendría que asignar espacio para ese resultado, por lo que algo como lo siguiente funcionaría para eso:unsigned int len; HMAC_Final(&ctx, result, &len);
El problema con su sugerencia original es, como dijo Martin, que necesita inicializar el MOTOR. El problema con su código editado era que estaba haciendo ENGINE_new, que le proporciona un MOTOR completamente nuevo, que luego debe proporcionar con métodos de cifrado, métodos de resumen, etc. De hecho, para lo que desea (y qué casi todo el mundo quiere), ignorar por completo todo el material del MOTOR es la elección correcta.
Algunos problemas subsidiarios:
- tus cadenas eran hexadecimales, pero necesitabas / xx por carácter para obtener realmente ese byte hexadecimal en esa posición de la cadena, que sospecho que era lo que querías.
- estabas tratando de hash 40 bytes de "datos", que no fue tan largo (efecto real: terminarás haciendo hashing en parte con la cadena de resultados)
- su resultado esperado fue (por lo que puedo decir) incorrecto
- imprimiría caracteres aleatorios en la terminal, ya que la función HMAC producirá 32 bytes de datos binarios aleatorios, no material imprimible.
El siguiente código compila, funciona y pasa la prueba. Es un poco diferente al código de ejemplo que encontraste (ya que todavía usa las funciones HMAC_ * individuales, es útil si quieres hacer hash bit a bit usando HMAC_Update):
#include <openssl/engine.h>
#include <openssl/hmac.h>
#include <openssl/evp.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void)
{
unsigned char* key = (unsigned char*) "/x0b/x0b/x0b/x0b/x0b/x0b/x0b/x0b/x0b/x0b/x0b/x0b/x0b/x0b/x0b/x0b/x0b/x0b/x0b/x0b";
unsigned char* data = (unsigned char*) "/x48/x69/x20/x54/x68/x65/x72/x65";
unsigned char* expected = (unsigned char*) "/x49/x2c/xe0/x20/xfe/x25/x34/xa5/x78/x9d/xc3/x84/x88/x06/xc7/x8f/x4f/x67/x11/x39/x7f/x08/xe7/xe7/xa1/x2c/xa5/xa4/x48/x3c/x8a/xa6";
unsigned char* result;
unsigned int result_len = 32;
int i;
HMAC_CTX ctx;
result = (unsigned char*) malloc(sizeof(char) * result_len);
ENGINE_load_builtin_engines();
ENGINE_register_all_complete();
HMAC_CTX_init(&ctx);
HMAC_Init_ex(&ctx, key, 16, EVP_sha256(), NULL);
HMAC_Update(&ctx, data, 8);
HMAC_Final(&ctx, result, &result_len);
HMAC_CTX_cleanup(&ctx);
for (i=0; i!=result_len; i++)
{
if (expected[i]!=result[i])
{
printf("Got %02X instead of %02X at byte %d!/n", result[i], expected[i], i);
break;
}
}
if (i==result_len)
{
printf("Test ok!/n");
}
return 0;
}
Por supuesto, no responde a su pregunta original sobre cómo inicializar ENGINE, pero realmente no hay una respuesta correcta sin tener más contexto, cuyo contexto resulta no ser relevante en su situación ...