使用openssl库在C中的sha1示例

时间:2016-12-12 21:26:07

标签: c openssl cryptography sha

我有一个用C语言编写的sha256的最简单的例子,使用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的程序?

更新

根据@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 *’

2 个答案:

答案 0 :(得分: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;
}

编辑:

上述代码中有一些错误已经纠正:

  • hashptr已宣布为EVP_MD *,现在为const EVP_MD *
  • EVP_DigestInit_ex的调用最后有一个额外的括号
  • EVP_DigestFinal_ex的第三个参数专门为unsigned int *而非size_t *,可能不一定相同。
  • 在顶部添加了对两个OpenSSL初始化函数的调用

答案 1 :(得分:0)

您可以这样做: -

#include <openssl/sha.h>
#include <stdio.h>
int main(int argc, char **argv)
 {
    unsigned char buffer[BUFSIZ];
    FILE *f;
    SHA_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;
    }

    SHA1_Init(&ctx);

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

    SHA1_Final(buffer, &ctx);

    fclose(f);

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