2011-10-02 26 views
30

He encontrado un código md5 que consta de los siguientes prototipos ...Cómo crear un hash md5 de una cadena en C?

He estado tratando de averiguar dónde tengo que poner la cadena que quiero hash, a qué funciones debo llamar, y dónde encontrar la cadena una vez que ha sido hash. Estoy confundido con respecto a qué uint32 buf [4] y uint32 bits [2] están en la estructura.

struct MD5Context { 
    uint32 buf[4]; 
    uint32 bits[2]; 
    unsigned char in[64]; 
}; 

/* 
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious 
* initialization constants. 
*/ 
void MD5Init(struct MD5Context *context); 

/* 
* Update context to reflect the concatenation of another buffer full 
* of bytes. 
*/ 
void MD5Update(struct MD5Context *context, unsigned char const *buf, unsigned len); 

/* 
* Final wrapup - pad to 64-byte boundary with the bit pattern 
* 1 0* (64-bit count of bits processed, MSB-first) 
*/ 
void MD5Final(unsigned char digest[16], struct MD5Context *context); 

/* 
* The core of the MD5 algorithm, this alters an existing MD5 hash to 
* reflect the addition of 16 longwords of new data. MD5Update blocks 
* the data and converts bytes into longwords for this routine. 
*/ 
void MD5Transform(uint32 buf[4], uint32 const in[16]); 

Respuesta

35

No conozco esta biblioteca en particular, pero he usado llamadas muy similares. Así que esta es mi mejor estimación:

unsigned char digest[16]; 
const char* string = "Hello World"; 
struct MD5Context context; 
MD5Init(&context); 
MD5Update(&context, string, strlen(string)); 
MD5Final(digest, &context); 

Esto le devolverá una representación entera del hash. A continuación, puede convertir esto en una representación hexadecimal si desea pasarlo como una cadena.

char md5string[33]; 
for(int i = 0; i < 16; ++i) 
    sprintf(&md5string[i*2], "%02x", (unsigned int)digest[i]); 
+0

pensamiento agradable, exhibiendo la conversión del hash de una cadena. – dmckee

+0

Hmm, obtengo el 'error: el tamaño de almacenamiento de 'context' no se conoce' Estoy incluyendo' #include ' –

+0

@SSHEsto no creo que el código OPs esté usando openssl. –

5

Para ser honesto, los comentarios que acompañan a los prototipos parecen claros. Algo como esto debe hacer el truco:

void compute_md5(char *str, unsigned char digest[16]) { 
    MD5Context ctx; 
    MD5Init(&ctx); 
    MD5Update(&ctx, str, strlen(str)); 
    MD5Final(digest, &ctx); 
} 

donde str es una cadena C que desea el hash de, y digest es el resumen MD5 resultante.

1

Parecería que usted debe

  • Crear un struct MD5context y pasarlo a MD5Init conseguirlo en una condición de partida adecuado
  • llamada MD5Update con el contexto y los datos
  • Call MD5Final para obtener el hash resultante

Estas tres funciones y la definición de estructura conforman una bonita interfaz abstracta para el algoritmo hash. No estoy seguro de por qué se te mostró la función de transformación del núcleo en ese encabezado, ya que probablemente no deberías interactuar directamente con él.

El autor podría haber hecho un poco más de ocultación de la implementación haciendo que la estructura sea un tipo abstracto, pero entonces se habría visto obligado a asignar la estructura en el montón cada vez (a diferencia de ahora donde puede colocarlo en el pila si así lo deseas).

7

Como han mencionado otras respuestas, las siguientes llamadas serán calcular el hash:

MD5Context md5; 
MD5Init(&md5); 
MD5Update(&md5, data, datalen); 
MD5Final(digest, &md5); 

El propósito de dividirlo en que muchas de las funciones es dejar que permite transmitir grandes conjuntos de datos.

Por ejemplo, si está procesando un archivo de 10 GB y no encaja en el ram, aquí le mostramos cómo lo haría. Leerías el archivo en trozos más pequeños y llamarías al MD5Update.

MD5Context md5; 
MD5Init(&md5); 

fread(/* Read a block into data. */) 
MD5Update(&md5, data, datalen); 

fread(/* Read the next block into data. */) 
MD5Update(&md5, data, datalen); 

fread(/* Read the next block into data. */) 
MD5Update(&md5, data, datalen); 

... 

// Now finish to get the final hash value. 
MD5Final(digest, &md5); 
31

Aquí está un ejemplo completo:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#if defined(__APPLE__) 
# define COMMON_DIGEST_FOR_OPENSSL 
# include <CommonCrypto/CommonDigest.h> 
# define SHA1 CC_SHA1 
#else 
# include <openssl/md5.h> 
#endif 

char *str2md5(const char *str, int length) { 
    int n; 
    MD5_CTX c; 
    unsigned char digest[16]; 
    char *out = (char*)malloc(33); 

    MD5_Init(&c); 

    while (length > 0) { 
     if (length > 512) { 
      MD5_Update(&c, str, 512); 
     } else { 
      MD5_Update(&c, str, length); 
     } 
     length -= 512; 
     str += 512; 
    } 

    MD5_Final(digest, &c); 

    for (n = 0; n < 16; ++n) { 
     snprintf(&(out[n*2]), 16*2, "%02x", (unsigned int)digest[n]); 
    } 

    return out; 
} 

    int main(int argc, char **argv) { 
     char *output = str2md5("hello", strlen("hello")); 
     printf("%s\n", output); 
     free(output); 
     return 0; 
    } 
+0

Tenga cuidado, el uso de '16 * 2' en' sprintf' no es válido, debe usar '3' en su lugar (suponiendo que' out' sea lo suficientemente grande). – Lekensteyn

+1

'MD5_Update' toma la longitud en unidades de bytes. También puede usar 'MD5 (str, strlen (str), digest);' ya que conoce la longitud de antemano. ('MD5' está disponible en todas las versiones de OpenSSL de acuerdo con su página de manual). – Lekensteyn