2012-02-14 19 views
23

Estoy intentando escribir un programa C que pruebe que SHA1 está casi libre de colisiones, pero no puedo encontrar la manera de crear realmente el hash para mis valores de entrada. Solo necesito crear el hash y almacenar el valor hexadecimal en una matriz. Después de algunas búsquedas de Google, he encontrado la de OpenSSL orientarme a utilizar esto:Cómo usar el hash SHA1 en la programación 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); 

creo que debería estar utilizando ya sea sin firma SHA1 char * o SHA1_Init, pero no estoy seguro de lo que serían los argumentos, dado x es mi entrada para ser hash. ¿Alguien podría aclarar esto por mí? Gracias.

+0

¿cuáles son sus valores de entrada: cadenas en memoria, o el contenido del archivo? –

+0

Estoy escribiendo un ataque de cumpleaños que debería crear un hash nuevo y lo agrega al final cada vez que paso por la matriz. Simplemente iba a mantenerlo simple y calcular el valor de i. Respuesta rápida, en cadenas de memoria. – spassen

+1

¿Qué quiere decir con 'probar que SHA1 está casi libre de colisiones'? SHA1 es un hash de 160 bits, por lo que hay 2^160 valores posibles, pero hay mucho más de 2^160 cadenas posibles (digamos más corto que 1MB), por lo que hay toneladas de colisiones. Si solo desea probar si obtiene colisiones de varias cadenas generadas aleatoriamente, la cantidad de cadenas necesarias para una respuesta a medio camino confiable es demasiado alta (a menos que encuentre una colisión antes, pero SHA1 se prueba lo suficientemente bien como para asignar esa una probabilidad insignificantemente pequeña). –

Respuesta

39

Si tiene todos sus datos a la vez, sólo tiene que utilizar la función 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 

Si, por el contrario, que sólo recibe los datos de una sola pieza a la vez y desea calcular el condensado que recibe los datos, a continuación, utilizar las otras funciones:

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

Intenté usar la función sha1, pero cuando compilo en el terminal dice Referencia indefinida a SHA1. No tengo quejas sobre nada más. ¿Alguna idea de lo que me estoy perdiendo? – spassen

+7

Debe establecer un enlace con la biblioteca de tiempo de ejecución de OpenSSL. Asumiendo que estás usando gcc, agrega '-lcrypto' a tu línea de comando del enlazador. –

+0

¿cómo se generaría hmacsha1? – Cmag

11

Son dos formas diferentes de lograr lo mismo.

En concreto, ya sea uso SHA_Init, luego SHA_Update tantas veces como sea necesario para pasar sus datos a través y luego SHA_Final para obtener el producto de digestión, o que SHA1.

El motivo de dos modos es que cuando se procesan archivos grandes es común leer el archivo en fragmentos, ya que la alternativa utilizaría mucha memoria. Por lo tanto, hacer un seguimiento del SHA_CTX - el contexto SHA - sobre la marcha le permite evitar esto. El algoritmo también se ajusta internamente a este modelo, es decir, los datos se pasan en bloque a la vez.

El método SHA debe ser bastante sencillo. Las otras obras como esta:

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

Fundamentalmente, al final md contendrán el binario digerido, no una representación hexadecimal - no es una cadena y no debe utilizarse como una sola.

+0

¿cómo se generaría hmacsha1? – Cmag

+0

@Clustermagnet hmacsha1 es un algoritmo HMAC que usa SHA1 como hash. Es la misma idea que en mi respuesta aquí (vea [aquí] (http://www.openssl.org/docs/crypto/hmac.html)) pero para el argumento 'EVP_MD' específico de HMAC, usted especifica' EVP_sha1() '. –

+0

@Cmag - ver [Firma y Verificación EVP | HMAC] (http://wiki.openssl.org/index.php/EVP_Signing_and_Verifying#HMAC) en la wiki de OpenSSL. Consulte también [Uso de funciones HMAC vs EVP en OpenSSL] (http://stackoverflow.com/a/20322002/608639) en Desbordamiento de pila. – jww

3

la primera función (SHA1()) es el de mayor nivel uno, es probable que sea el que usted desea. El documento es bastante claro sobre el uso: d se ingresa, n es su tamaño y md es donde se coloca el resultado (lo asigna).

En cuanto a las otras 3 funciones, estas son de nivel inferior y estoy bastante seguro de que son utilizadas internamente por la primera. Son más adecuados para entradas más grandes que deben procesarse de manera bloque por bloque.

2

creo que debería usar ya sea unsigned char *SHA1 o SHA1_Init ...

Para las versiones posteriores de la biblioteca OpenSSL, como 1.0.2 y 1.1.0, el proyecto recomienda el uso de la interfaz de EVP.Un ejemplo del uso EVP Message Digests con SHA256 está disponible en el wiki de OpenSSL: Respuesta

#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

de Adam Rosenfield está muy bien, pero el uso strlen más que sizeof, de lo contrario de hash se calculará incluyendo terminador nulo. Lo cual probablemente esté bien en este caso, pero no si necesita comparar su hash con uno generado por otra herramienta.

// 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 
Cuestiones relacionadas