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]);
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]);
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;
}
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);
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);
}
où str
est une chaîne C dont vous voulez le hachage et digest
est le condensé MD5 résultant.
Il semblerait que vous devriez
struct MD5context
et le transmettre à MD5Init
pour le mettre dans un bon état de départMD5Update
avec le contexte et vos donnéesMD5Final
pour obtenir le hachage résultantCes 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).