web-dev-qa-db-fra.com

Comment utiliser le hachage SHA1 dans la programmation C

J'essaie d'écrire un programme C qui prouve que SHA1 est presque sans collision, mais je ne peux pas comprendre comment créer réellement le hachage pour mes valeurs d'entrée. J'ai juste besoin de créer le hachage et de stocker la valeur hexadécimale dans un tableau. Après quelques recherches sur Google, j'ai trouvé une documentation OpenSSL me demandant d'utiliser ceci:

 #include <openssl/sha.h>

 unsigned char *SHA1(const unsigned char *d, unsigned long n,
                  unsigned char *md);

 int SHA1_Init(SHA_CTX *c);
 int SHA1_Update(SHA_CTX *c, const void *data,
                  unsigned long len);
 int SHA1_Final(unsigned char *md, SHA_CTX *c);

Je crois que je devrais utiliser le caractère non signé * SHA1 ou SHA1_Init, mais je ne suis pas sûr de ce que seraient les arguments, étant donné que x est mon entrée à hacher. Quelqu'un pourrait-il clarifier cela pour moi? Merci.

27
spassen

Si vous avez toutes vos données en même temps, utilisez simplement le SHA1 une fonction:

// The data to be hashed
char data[] = "Hello, world!";
size_t length = strlen(data);

unsigned char hash[SHA_DIGEST_LENGTH];
SHA1(data, length, hash);
// hash now contains the 20-byte SHA-1 hash

Si, en revanche, vous n'obtenez vos données qu'une seule pièce à la fois et que vous souhaitez calculer le hachage à mesure que vous recevez ces données, utilisez les autres fonctions:

// Error checking omitted for expository purposes

// Object to hold the current state of the hash
SHA_CTX ctx;
SHA1_Init(&ctx);

// Hash each piece of data as it comes in:
SHA1_Update(&ctx, "Hello, ", 7);
...
SHA1_Update(&ctx, "world!", 6);
// etc.
...
// When you're done with the data, finalize it:
unsigned char hash[SHA_DIGEST_LENGTH];
SHA1_Final(hash, &ctx);
48
Adam Rosenfield

La première fonction (SHA1()) est la plus élevée, c'est probablement celle que vous souhaitez. Le document est assez clair sur l'utilisation - d est entrée, n est sa taille et md est où le résultat est placé (vous l'allouez).

Quant aux 3 autres fonctions - elles sont de niveau inférieur et je suis sûr qu'elles sont utilisées en interne par la première. Ils sont mieux adaptés aux entrées plus importantes qui doivent être traitées de manière bloc par bloc.

3
kralyk

Calculez le hachage comme ceci

// Object to hold the current state of the hash
SHA_CTX ctx;
SHA1_Init(&ctx);

// Hash each piece of data as it comes in:
SHA1_Update(&ctx, "Hello, ", 7);
...
SHA1_Update(&ctx, "world!", 6);
// etc.
...
// When you're done with the data, finalize it:
unsigned char tmphash[SHA_DIGEST_LENGTH];
SHA1_Final(tmphash, &ctx);

Enfin, vous pouvez décoder le hachage sous une forme lisible par un code comme celui-ci.

unsigned char hash[SHA_DIGEST_LENGTH*2];

int i = 0;
for (i=0; i < SHA_DIGEST_LENGTH; i++) {
    sprintf((char*)&(hash[i*2]), "%02x", tmphash[i]);
}
// And print to stdout
printf("Hash: %s\n", hash);
2
linux_art

Je pense que je devrais utiliser soit unsigned char *SHA1 ou SHA1_Init ...

Pour les versions ultérieures de la bibliothèque OpenSSL, comme 1.0.2 et 1.1.0, le projet recommande d'utiliser l'interface EVP. Un exemple d'utilisation de EVP Message Digests avec SHA256 est disponible sur le wiki OpenSSL:

#define handleErrors abort

EVP_MD_CTX *ctx;

if((ctx = EVP_MD_CTX_create()) == NULL)
    handleErrors();

if(1 != EVP_DigestInit_ex(ctx, EVP_sha256(), NULL))
    handleErrors();

unsigned char message[] = "abcd .... wxyz";
unsinged int message_len = sizeof(message);

if(1 != EVP_DigestUpdate(ctx, message, message_len))
    handleErrors();

unsigned char digest[EVP_MAX_MD_SIZE];
unsigned int digest_len = sizeof(digest);

if(1 != EVP_DigestFinal_ex(ctx, digest, &digest_len))
    handleErrors();

EVP_MD_CTX_destroy(ctx);
2
jww

La réponse d'Adam Rosenfield est correcte, mais utilisez strlen plutôt que sizeof, sinon le hachage sera calculé en incluant le terminateur nul. Ce qui est probablement bien dans ce cas, mais pas si vous devez comparer votre hachage avec celui généré par un autre outil.

// The data to be hashed
char data[] = "Hello, world!";
size_t length = strlen(data);

unsigned char hash[SHA_DIGEST_LENGTH];
SHA1(data, length, hash);
// hash now contains the 20-byte SHA-1 hash
1
Shadowchaser