2016-12-12 6 views
3

У меня есть простой пример sha256, написанный на C, с использованием библиотеки openSSL.Пример sha1 в C с использованием библиотеки openssl

// compile with: gcc -o sha256 sha256.c -lcrypto 

#include <openssl/sha.h> 
#include <stdio.h> 
int main(int argc, char **argv) 
{ 
    unsigned char buffer[BUFSIZ]; 
    FILE *f; 
    SHA256_CTX ctx; 
    size_t len; 
    if (argc < 2) { 
     fprintf(stderr, "usage: %s <file>\n", argv[0]); 
     return 1; 
    } 

    f = fopen(argv[1], "r"); 
    if (!f) { 
     fprintf(stderr, "couldn't open %s\n", argv[1]); 
     return 1; 
    } 

    SHA256_Init(&ctx); 

    do { 
     len = fread(buffer, 1, BUFSIZ, f); 
     SHA256_Update(&ctx, buffer, len); 
    } while (len == BUFSIZ); 

    SHA256_Final(buffer, &ctx); 

    fclose(f); 

    for (len = 0; len < SHA256_DIGEST_LENGTH; ++len) 
     printf("%02x", buffer[len]); 
    putchar('\n'); 
    return 0; 
} 

мне нужно то же самое для sha1, но я не мог найти подобный простой пример, который на самом деле работает. Наивный подход к замене вхождений SHA256 в приведенный выше код с SHA1 не работает (очевидно).

Как я могу изменить свою программу для SHA1?

UPDATE

как предложено @dbush, я использовал его EVP код, и интегрировать его в мою программу. Моя программа теперь выглядит следующим образом:

#include <stdio.h> 
#include <openssl/sha.h> 
#include <openssl/evp.h> 
#include <openssl/err.h> 

int main(int argc, char **argv) 
{ 

FILE *f; 
size_t len; 
unsigned char buffer[BUFSIZ]; 

if (argc < 2) { 
    fprintf(stderr, "usage: %s <file>\n", argv[0]); 
    return 1; 
} 

f = fopen(argv[1], "r"); 

if (!f) { 
    fprintf(stderr, "couldn't open %s\n", argv[1]); 
    return 1; 
} 


EVP_MD_CTX hashctx; 
//EVP_MD *hashptr = EVP_get_digestbyname("SHA256"); 
EVP_MD *hashptr = EVP_get_digestbyname("SHA1"); 

EVP_MD_CTX_init(&hashctx); 
EVP_DigestInit_ex(&hashctx, hashptr, NULL)); 

do { 
    len = fread(buffer, 1, BUFSIZ, f); 
    EVP_DigestUpdate(&hashctx, buffer, len); 
} while (len == BUFSIZ); 

EVP_DigestFinal_ex(&hashctx, buffer, &len); 
EVP_MD_CTX_cleanup(&hashctx); 

fclose(f); 

int i; 
for (i = 0; i < len; ++i) 
    printf("%02x", buffer[i]); 

    return 0; 
} 

Когда я компилирую его с помощью gcc -o evp evp.c -lcrypto, я получаю пару ошибок, таких как:

evp.c: In function ‘main’: 
evp.c:29:19: warning: initialization discards ‘const’ qualifier from pointer target type [enabled by default] 
evp.c:32:43: error: expected ‘;’ before ‘)’ token 
evp.c:32:43: error: expected statement before ‘)’ token 
evp.c:39:1: warning: passing argument 3 of ‘EVP_DigestFinal_ex’ from incompatible pointer type [enabled by default] 
In file included from evp.c:4:0: 
/usr/include/openssl/evp.h:574:5: note: expected ‘unsigned int *’ but argument is of type ‘size_t *’ 
+0

Если вы встречая * «предупреждение:„константный“классификатор инициализации сбрасывает ...» * предупреждения, то я верю, что вы используете очень старую версию OpenSSL. Возможно, OpnSSL 0.9.8 на OS X? Возможно, вам захочется обновить библиотеку. – jww

+0

@jww - Я использую 'libssl-dev' версию' 1.0.1t-1 + deb7u1' на Debian. –

ответ

3

Вместо того чтобы использовать SHA1 или SHA256 специфические функции, используйте EVP_Digest* семейство функций, которые работают с любым хешем.

... 

// makes all algorithms available to the EVP* routines 
OpenSSL_add_all_algorithms(); 
// load the error strings for ERR_error_string 
ERR_load_crypto_strings(); 

EVP_MD_CTX hashctx; 
//const EVP_MD *hashptr = EVP_get_digestbyname("SHA256"); 
const EVP_MD *hashptr = EVP_get_digestbyname("SHA1"); 

EVP_MD_CTX_init(&hashctx); 
EVP_DigestInit_ex(&hashctx, hashptr, NULL); 

do { 
    len = fread(buffer, 1, BUFSIZ, f); 
    EVP_DigestUpdate(&hashctx, buffer, len); 
} while (len == BUFSIZ); 

unsigned int outlen; 
EVP_DigestFinal_ex(&hashctx, buffer, &outlen); 
EVP_MD_CTX_cleanup(&hashctx); 

fclose(f); 

int i; 
for (i = 0; i < outlen; ++i) 
    printf("%02x", buffer[i]); 

Я пропустил проверку ошибок для краткости. Для того, чтобы проверить на наличие ошибок, выполните следующие действия:

if (function_to_check() == 0) { 
    char errstr[1000]; 
    ERR_error_string(ERR_get_error(), errstr); 
    printf("error: %s\n", errstr; 
} 

EDIT:

Были некоторые ошибки в приведенном выше коде, которые были исправлены:

  • hashptr был объявлен EVP_MD *, теперь const EVP_MD *.
  • Вызов EVP_DigestInit_ex был дополнительный скобку в конце
  • Третий параметр EVP_DigestFinal_ex специально дан unsigned int * вместо того, чтобы в size_t *, которые не обязательно могут быть одинаковыми.
  • Добавлено вызовов двух функций инициализации OpenSSL в верхней
+0

спасибо. Не могли бы вы добавить остальную часть недостающего кода, чтобы я мог ее скопировать? В настоящий момент, когда вы вставляете свой код в мою программу (заменяя соответствующие части), я получаю пару ошибок. Кроме того, я считаю, что у вас есть опечатка: 'for (i = 0; len

+0

@MartinVegter Вам понадобится '#include и' #include '. Кроме этого, он должен работать. Если нет, обновите свой вопрос (или опубликуйте новый) с соответствующим кодом. – dbush

+0

@MartinVegter Было несколько ошибок в том, что я изначально опубликовал. Я отредактировал свой примерный код и подтвердил, что он работает правильно. – dbush