一、 openssl 命令计算摘要值
$ echo -n "123456789" | openssl sha256
(stdin)= 15e2b0d3c33891ebb0f1ef609ec419420c20e320ce94c65fbc8c3312448eb225
需要注意这里 echo 命令的 -n 选项,表示去除字符串的换行符
如果是针对文件进行哈希计算
$ openssl sha256 test.file
SHA256(test.file)= 181c968be7bf421dd331ce8d2847a4875543cdc8a471fa36056f0b56c15588bb
二、openssl 代码实现摘要值计算
方式一、单SHA256函数
void test_sha(void)
{
char src_str[] = "123456789";
char md_value[32] = {0};
SHA256(src_str, strlen(src_str), md_value);
printf("digest is:\n");
for (int i = 0; i < sizeof(md_value); i++)
{
printf("%02x", md_value[i]);
}
printf("\n");
return ;
}
方式二、SHA256组合函数
void test_sha_v2(void)
{
char src_str[] = "123456789";
char md_value[32] = {0};
SHA256_CTX ctx;
SHA256_Init(&ctx);
SHA256_Update(&ctx, src_str, strlen(src_str));
SHA256_Final(md_value, &ctx);
... // 省去打印
return ;
}
方式二、EVP组合函数
void test_evp(void)
{
EVP_MD_CTX *mdctx = NULL;
char src_str[] = "123456789";
char md_value[32] = {0};
int md_len = 0;
mdctx = EVP_MD_CTX_new();
EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL);
EVP_DigestUpdate(mdctx, src_str, strlen(src_str));
EVP_DigestFinal_ex(mdctx, md_value, &md_len);
EVP_MD_CTX_free(mdctx);
...\\ 省去打印
return ;
}
三个方式运算结果:
./a.out
digest is:
15e2b0d3c33891ebb0f1ef609ec419420c20e320ce94c65fbc8c3312448eb225
digest is:
15e2b0d3c33891ebb0f1ef609ec419420c20e320ce94c65fbc8c3312448eb225
digest is:
15e2b0d3c33891ebb0f1ef609ec419420c20e320ce94c65fbc8c3312448eb225
和命令结果一致。
从函数实现来看,方式一单SHA256 最简便,但其使用场景也仅针对较短的字符串或者少量数据进行 HASH 计算;如果是针对大文件进行 HASH 计算,虽然也可以通过单 SHA256 函数一次调用计算,但这就需要一次申请该大文件所对应的内存空间,对于嵌入式设备而言,明显是不可行的,此种情况下就需要用到方式二和方式三通过小内存多次 update 哈希计算了。
至于方式二和方式三,可以看出来,方式三更具有抽象性,完全可以针对摘要算法作为入参使用,后续便于替换其他摘要算法。
三、摘要算法知识补充
摘要算法,也称哈希算法,或者单向散列算法,是日常工作中经常会用到的算法。其特性就是运算速度快,不管内容多长都输出固定长度值,通过摘要值难以推导出原始明文数据等。
其主要用途有:
1、文件比较 (一般网站下载文件,会显示给文件的哈希值用于比较)
2、登入口令不可逆存储,一般是口令再加盐值等信息做摘要后存储,这样即使数据库被泄露了,攻击者也很难获取到原始口令;随之对应的摘要认证