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 32int 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