web-dev-qa-db-fra.com

Comment créer un hachage md5 d'une chaîne en C?

J'ai trouvé du code md5 composé des prototypes suivants ...

J'ai essayé de savoir où je dois mettre la chaîne que je veux hacher, quelles fonctions je dois appeler et où trouver la chaîne une fois hachée. Je suis confus quant à ce que sont les bits uint32 buf [4] et uint32 [2] dans la structure.

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

Je ne connais pas cette bibliothèque particulière, mais j'ai utilisé des appels très similaires. Voici donc ma meilleure estimation:

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

Cela vous donnera une représentation entière du hachage. Vous pouvez ensuite le transformer en une représentation hexadécimale si vous souhaitez le faire passer sous forme de chaîne.

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

Voici un exemple complet:

#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;
    }
33
todd

Comme d'autres réponses l'ont mentionné, les appels suivants calculent le hachage:

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

Le but de le diviser en autant de fonctions est de vous permettre de diffuser de grands ensembles de données.

Par exemple, si vous hachez un fichier de 10 Go et qu'il ne rentre pas dans la mémoire RAM, voici comment procéder. Vous devriez lire le fichier en petits morceaux et appeler MD5Update sur eux.

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

Pour être honnête, les commentaires accompagnant les prototypes semblent assez clairs. Quelque chose comme ça devrait faire l'affaire:

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

str est une chaîne C dont vous voulez le hachage et digest est le condensé MD5 résultant.

5
NPE

Il semblerait que vous devriez

  • Créer un struct MD5context et le transmettre à MD5Init pour le mettre dans un bon état de départ
  • Appel MD5Update avec le contexte et vos données
  • Appel MD5Final pour obtenir le hachage résultant

Ces trois fonctions et la définition de la structure font une belle interface abstraite avec l'algorithme de hachage. Je ne sais pas pourquoi on vous a montré la fonction de transformation principale dans cet en-tête car vous ne devriez probablement pas interagir directement avec elle.

L'auteur aurait pu cacher un peu plus l'implémentation en faisant de la structure un type abstrait, mais vous auriez alors été forcé d'allouer la structure sur le tas à chaque fois (contrairement à maintenant où vous pouvez la mettre sur la pile si vous le souhaitez) envie).

1
dmckee