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