2011-10-02 6 views
30

Ho trovato un codice md5 costituito dai seguenti prototipi ...Come creare un hash MD5 di una stringa in C?

Ho cercato di scoprire dove devo mettere la stringa che desidero hash, quali funzioni devo chiamare e dove trovare la stringa una volta che è stata sottoposta a hash. Sono confuso riguardo a ciò che uint32 buf [4] e uint32 bit [2] sono nella struttura.

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]); 

risposta

35

Non conosco questa libreria particolare, ma ho usato chiamate molto simili. Quindi questa è la mia ipotesi migliore:

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

Questo ti restituirà una rappresentazione intera dell'hash. Puoi quindi trasformarlo in una rappresentazione esadecimale se vuoi passarlo come una stringa.

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

bel pensiero, esibendo la conversione del hash per una stringa. – dmckee

+0

Hmm, sto ottenendo 'errore: la dimensione di archiviazione di 'contesto' non è nota' Sto includendo' #include ' –

+0

@SSHQuesto non credo che il codice OPs stia usando openssl. –

5

Per essere onesti, i commenti che accompagnano i prototipi sembrano abbastanza chiari. Qualcosa del genere dovrebbe fare il trucco:

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

dove str è una stringa C si desidera che l'hash, e digest è la risultante digest MD5.

1

Sembrerebbe che si dovrebbe

  • Creare un struct MD5context e passarlo a MD5Init per ottenere in una vera e propria condizione di partenza
  • chiamata MD5Update con il contesto ei dati
  • Chiamata MD5Final per ottenere l'hash risultante

Queste tre funzioni e la definizione della struttura formano una bella interfaccia astratta per l'algoritmo di hash. Non sono sicuro del motivo per cui ti è stata mostrata la funzione di trasformazione principale in quell'intestazione, poiché probabilmente non dovresti interagire direttamente con essa.

L'autore avrebbe potuto fare un po 'più di occultamento dell'implementazione rendendo la struttura un tipo astratto, ma in quel caso sarebbe stato costretto ad allocare la struttura sull'heap ogni volta (al contrario di ora dove è possibile inserirla sul impilare se lo desideri).

7

Come altre risposte hanno menzionato, le seguenti chiamate saranno calcolare l'hash:

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

Lo scopo di dividere in su in che molte funzioni è quello di far eseguire lo streaming di dati di grandi dimensioni.

Ad esempio, se si esegue l'hashing di un file da 10 GB e non si adatta alla ram, ecco come si farebbe per farlo. Dovresti leggere il file in blocchi più piccoli e chiamare MD5Update su di essi.

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

Ecco un esempio 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

Attenzione, l'uso di '16 * 2' in' sprintf' non è valido, dovresti usare '3' invece (assumendo che' out' sia abbastanza grande). – Lekensteyn

+1

'MD5_Update' prende la lunghezza in unità di byte. Puoi anche usare 'MD5 (str, strlen (str), digest);' dato che conosci la lunghezza in precedenza. ('MD5' è disponibile in tutte le versioni di OpenSSL in base alla sua pagina di manuale). – Lekensteyn