【问题标题】:sha1 example in C using openssl library使用 openssl 库的 C 中的 sha1 示例
【发布时间】:2017-04-27 20:24:59
【问题描述】:

我有一个使用 openSSL 库用 C 语言编写的sha256 的最简单示例。

// 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 我需要同样的方法,但我找不到类似的实际有效的简单示例。用SHA1 替换上述代码中出现的SHA256 的天真方法不起作用(显然)。

如何为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 *’

【问题讨论】:

  • 如果您遇到 "警告:初始化丢弃'const'限定符..." 警告,那么我相信您使用的是真正旧版本的 OpenSSL。也许 OS X 上的 OpnSSL 0.9.8?您可能需要考虑更新库。
  • @jww - 我在 Debian 上使用 libssl-dev 版本 1.0.1t-1+deb7u1

标签: c openssl cryptography sha


【解决方案1】:

不要使用特定于 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 初始化函数的调用

【讨论】:

  • 谢谢。能否请您添加其余缺少的代码,以便我可以准确复制它?目前,当将您的代码粘贴到我的程序中(替换相关部分)时,我遇到了几个错误。另外,我相信你这里有一个错字:for (i = 0; len &lt; len; ++i),应该是i&lt;len
  • @MartinVegter 你需要#include &lt;openssl/evp.h&gt;#include &lt;openssl/err.h&gt;。除此之外,它应该可以工作。如果没有,请使用相关代码更新您的问题(或发布新问题)。
  • @MartinVegter 我最初发布的内容有一些错误。我已经编辑了我的示例代码并确认它运行正确。
  • 错误检查代码会检查哪些错误,应将其集成到代码的哪一部分?
  • @MartinVegter 将错误检查应用于EVP_Digest* 函数。另外,检查EVP_get_digestbyname 是否返回NULL
【解决方案2】:

你可以这样做:-

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

【讨论】:

    猜你喜欢
    • 2021-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-22
    • 1970-01-01
    • 2010-10-19
    • 1970-01-01
    相关资源
    最近更新 更多