openssl-摘要算法

Posted by 周思进 on April 5, 2022

一、 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、登入口令不可逆存储,一般是口令再加盐值等信息做摘要后存储,这样即使数据库被泄露了,攻击者也很难获取到原始口令;随之对应的摘要认证