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