ILD

使用libgcrypt计算sha256
作者:Yuan Jianpeng 邮箱:yuanjp89@163.com
发布时间:2019-6-9 站点:Inside Linux Development

libgcrypt是GNU的安全库,它提供API,支持哈希计算,对称加密,非对称加密等。


安装libgcrypt

1
sudo apt install libgcrypt20-dev


在使用任何的libgcrypt库函数前,需要对libgcrypt进行初始化,一个不使用安全内存的标准初始化如下:

1
2
3
4
5
6
7
8
9
10
11
12
#include <gcrypt.h>
 
void gcrypt_init()
{
    if (!gcry_check_version (GCRYPT_VERSION))
    {
        fputs ("libgcrypt version mismatch\n", stderr);
        exit (2);
    }
    gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
    gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
}


计算sha256比较简单,封装3个接口如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#define SHA256_DIGEST_SIZE 32
 
int gcrypt_sha256_init(gcry_md_hd_t *hd)
{
    gcry_error_t err = gcry_md_open(hd, GCRY_MD_SHA256, 0);
    if (err)
        return 1;
    return 0;
}
 
void gcrypt_sha256_update(gcry_md_hd_t hd, const void *data,  int len)
{
    gcry_md_write(hd, data, len);
}
 
void gcrypt_sha256_final(gcry_md_hd_t hd, void *digest)
{
    unsigned char *val = gcry_md_read(hd, GCRY_MD_SHA256);
    memcpy(digest, val, SHA256_DIGEST_SIZE);
    gcry_md_close(hd);
}


gcry_error_t gcry_md_open (gcry_md_hd_t * hd , int algo , unsigned int flags)

    创建一个消息摘要对象,算法由algo指定,存储到hd,如果创建失败,则hd为NULL。


void gcry_md_write (gcry_md_hd_t h , const void * buffer , size t length)

    更新消息摘要,对于大文件,不断的执行write即可。


unsigned char * gcry_md_read (gcry_md_hd_t h , int algo )

    会自动执行gcry_md_final(),将消息摘要的结果返回,返回结果存储到h上下文中,直到release都可用。

    返回结果的长度是由算法决定的,比如sha256为32位。返回结果是二进制。


void gcry_md_close (gcry_md_hd_t h )

    释放hash上下文的所有资源。


使用上述结果,计算文件的sha256,测试和工具sh256sum计算的结果完全一致。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
 
int main(int argc, char **argv)
{
    int fd;
    char buf[4096];
    int ret;
    gcry_md_hd_t hd;
    unsigned char digest[SHA256_DIGEST_SIZE];
 
    if (argc < 2) return 1;
 
    gcrypt_init();
 
    if (gcrypt_sha256_init(&hd)) {
        fputs("gcrypt sha256 init failed\n", stderr);
        return 1;
    }
 
    fd = open(argv[1], O_RDONLY);
    if (fd == -1) {
        fprintf(stderr, "open %s failed\n"strerror(errno));
        return 1;
    }
 
    do
    {
        ret = read(fd, buf, sizeof(buf));
        if (ret == -1) {
            fprintf(stderr, "open %s failed\n"strerror(errno));
            return 1;
        }
        gcrypt_sha256_update(hd, buf, ret);
    while (ret > 0);
 
    gcrypt_sha256_final(hd, digest);
    close(fd);
    for (ret = 0; ret < SHA256_DIGEST_SIZE; ret++)
        printf("%02x", digest[ret]);
    printf("\n");
 
    return 0;
}


编译需要链接:-lgcrypt


参考:

The Libgcrypt Reference Manual


Copyright © insidelinuxdev.net 2017-2021. Some Rights Reserved.