2012-02-14 12 views
23

Sto provando a scrivere un programma C che dimostri che SHA1 è quasi privo di collisioni, ma non riesco a capire come effettivamente creare l'hash per i miei valori di input. Ho solo bisogno di creare l'hash e memorizzare il valore esadecimale in un array. Dopo alcune ricerche su Google, ho trovato me dirigere utilizzare questa documentazione OpenSSL:Come utilizzare l'hashing SHA1 nella programmazione C

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

credo che dovrei essere utilizzando unsigned char * SHA1 o SHA1_Init, ma non sono sicuro di quello che sarebbero gli argomenti, dato x è il mio input da sottoporre a hash. Qualcuno potrebbe chiarire questo per me? Grazie.

+0

Quali sono i valori di input: stringhe in memoria o contenuto del file? –

+0

Sto scrivendo un attacco di compleanno che dovrebbe creare un nuovo hash e aggiungerlo alla fine ogni volta che rimuovo l'array. Stavo solo per mantenerlo semplice e ho cancellato il valore di i. Risposta rapida, in stringhe di memoria. – spassen

+1

Cosa intendi con 'dimostrando che SHA1 è quasi privo di collisioni'? SHA1 è un hash di 160 bit, quindi ci sono 2^160 valori possibili, ma ci sono molto più di 2^160 possibili stringhe (diciamo più corte di 1MB), quindi ci sono tonnellate di collisioni. Se vuoi solo verificare se ottieni delle collisioni da un certo numero di stringhe generate casualmente, il numero di stringhe necessarie per una risposta a metà affidabile è troppo alto (a meno che non trovi una collisione in anticipo, ma SHA1 è testato abbastanza bene da assegnare quella una probabilità trascurabilmente piccola). –

risposta

39

Se si dispone di tutti i dati in una sola volta, basta usare la funzione SHA1:

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

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

Se, d'altra parte, si ottiene solo i dati un pezzo alla volta e si vuole calcolare la hash come si ricevono i dati, quindi utilizzare le altre funzioni:

// 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); 
+0

Ho provato a utilizzare la funzione sha1, ma quando compilo nel terminale si dice riferimento non definito a SHA1. Non ho alcuna lamentela riguardo a nient'altro. Qualche idea di cosa mi stia perdendo? – spassen

+7

È necessario creare un collegamento con la libreria di runtime OpenSSL. Supponendo che stai usando gcc, aggiungi '-lcrypto' alla riga di comando del tuo linker. –

+0

come si genera hmacsha1? – Cmag

11

Sono due modi diversi per ottenere la stessa cosa.

In particolare, è sia uso SHA_Init, poi SHA_Update come numero di volte necessario per passare i dati attraverso e poi SHA_Final per ottenere il digest, o si SHA1.

Il motivo delle due modalità è che quando si eseguono hashing di file di grandi dimensioni è normale leggere il file in blocchi, in quanto l'alternativa utilizza molta memoria. Quindi, tenendo traccia di SHA_CTX - il contesto SHA - come si va ti permette di aggirare questo. L'algoritmo internamente si adatta anche a questo modello, ovvero i dati vengono passati in blocco alla volta.

Il metodo SHA dovrebbe essere abbastanza semplice. Le altre opere come questa:

unsigned char md[SHA_DIGEST_LENGTH]; 
SHA_CTX context; 
int SHA1_Init(&context); 

for (i = 0; i < numblocks; i++) 
{ 
    int SHA1_Update(&context, pointer_to_data, data_length); 
} 
int SHA1_Final(md, &context); 

soprattutto, alla fine md conterranno il digest binario, non una rappresentazione esadecimale - non è una stringa e non deve essere utilizzato come uno.

+0

come si genera hmacsha1? – Cmag

+0

@Clustermagnet hmacsha1 è un algoritmo HMAC che utilizza SHA1 come hash. È la stessa idea della mia risposta qui (vedi [qui] (http://www.openssl.org/docs/crypto/hmac.html)) ma per l'argomento 'EVP_MD' specifico per HMAC si specifica' EVP_sha1() '. –

+0

@Cmag - vedi [Firma EVP e verifica | HMAC] (http://wiki.openssl.org/index.php/EVP_Signing_and_Verifying#HMAC) sul wiki OpenSSL. Vedi anche [Uso delle funzioni HMAC e EVP in OpenSSL] (http://stackoverflow.com/a/20322002/608639) su Stack Overflow. – jww

3

la prima funzione (SHA1()) è il livello più alto, è probabilmente quello che si desidera. Il documento è abbastanza chiaro sull'utilizzo - d è immesso, n è la sua dimensione e md è dove viene inserito il risultato (lo si assegna).

Come per le altre 3 funzioni - queste sono di livello inferiore e sono abbastanza sicuro che siano utilizzate internamente dal primo. Sono più adatti per input più grandi che devono essere elaborati in blocco a blocco.

2

credo dovrei usare sia unsigned char *SHA1 o SHA1_Init ...

Per le versioni successive del libreria OpenSSL, come 1.0.2 e 1.1.0, il progetto raccomanda di utilizzare l'interfaccia EVP.Un esempio di utilizzo EVP Message Digests con SHA256 è disponibile sul wiki OpenSSL: risposta

#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); 
0

Adam Rosenfield va bene, ma l'uso strlen piuttosto che sizeof, altrimenti hash sarà calcolato includendo terminatore null. Probabilmente in questo caso va bene, ma non se è necessario confrontare il tuo hash con quello generato da un altro strumento.

// 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 
Problemi correlati