将低级 OpenSSL API 迁移到高级 OpenSSL API 所需的建议

bou*_*rne 4 encryption hash openssl md5

我是 OpenSSL 的新手,目前正在开发一个依赖于 OpenSSL 的 C++ 项目。最近我开始使用一台安装了 openSSL 3.0 的机器,但无法构建项目,因为我收到如下所示的编译器错误(请注意,警告在项目中被视为错误)

error: 'MD5' is deprecated
    if (!MD5((uint8_t*)key.data(), key.size(), hashOutput)) {
         ^
/usr/local/Cellar/openssl@3/3.0.0_1/include/openssl/md5.h:52:1: note: 'MD5' has been explicitly marked deprecated here
OSSL_DEPRECATEDIN_3_0 unsigned char *MD5(const unsigned char *d, size_t n,
^
/usr/local/Cellar/openssl@3/3.0.0_1/include/openssl/macros.h:182:49: note: expanded from macro 'OSSL_DEPRECATEDIN_3_0'
#   define OSSL_DEPRECATEDIN_3_0                OSSL_DEPRECATED(3.0)
                                                ^
/usr/local/Cellar/openssl@3/3.0.0_1/include/openssl/macros.h:62:52: note: expanded from macro 'OSSL_DEPRECATED'
#     define OSSL_DEPRECATED(since) __attribute__((deprecated))
                                                   ^
1 error generated.
Run Code Online (Sandbox Code Playgroud)

经过一些调查,我发现这些 API 在 OpenSSL 3.0.0 中已被弃用,现在我有三个选择

  1. 忽略警告。它们只是警告。已弃用的函数仍然存在,您仍然可以使用它们。但请注意,它们可能会从 OpenSSL 的未来版本中删除。

  2. 抑制警告。有关如何执行此操作的信息,请参阅编译器文档。

  3. 删除对低级 API 的使用。在这种情况下,您需要重写代码以使用高级 API。

我选择了第三个选项,但即使在阅读了与 OpenSSL 相关的文档后,我仍然不确定与 OpenSSL 3.0.0 中已弃用的 MD5 方法等效的 EVP API 是什么。如果您检查链接https://www.openssl.org/docs/manmaster/man3/MD5.html它指出

本页描述的所有功能均已弃用。应用程序应使用 EVP_DigestInit_ex(3)、EVP_DigestUpdate(3) 和 EVP_DigestFinal_ex(3)。

如果有人可以向我提供一些反馈/帮助或其他资源/链接,这可能会帮助我了解高级 OpenSSL API 的一般使用情况,以便我可以使其适用于我的用例(即 MD5 加密),那就太好了。

我还必须提到,我从github下载了OpenSSL repo,发现md5方法的实现如下

    unsigned char *MD5(const unsigned char *d, size_t n, unsigned char *md)
{
    MD5_CTX c;
    static unsigned char m[MD5_DIGEST_LENGTH];

    if (md == NULL)
        md = m;
    if (!MD5_Init(&c))
        return NULL;
#ifndef CHARSET_EBCDIC
    MD5_Update(&c, d, n);
#else
    {
        char temp[1024];
        unsigned long chunk;

        while (n > 0) {
            chunk = (n > sizeof(temp)) ? sizeof(temp) : n;
            ebcdic2ascii(temp, d, chunk);
            MD5_Update(&c, temp, chunk);
            n -= chunk;
            d += chunk;
        }
    }
#endif
    MD5_Final(md, &c);
    OPENSSL_cleanse(&c, sizeof(c)); /* security consideration */
    return md;
}
Run Code Online (Sandbox Code Playgroud)

小智 7

我希望这个示例会有所帮助(我不会在示例中检查错误和异常,因此请注意这一点):

已弃用的实施

#include <openssl/md5.h>

static void calculate_md5(unsigned char* buf, unsigned int buf_size)
{
    unsigned char md5_digest[MD5_DIGEST_LENGTH];
    MD5_CTX md5ctx;

    MD5_Init(&md5ctx);
    MD5_Update(&md5ctx, buf, buf_size);
    MD5_Final(md5_digest, &md5ctx);
}
Run Code Online (Sandbox Code Playgroud)

新实施:

#include <openssl/evp.h>

static void calculate_md5(unsigned char* buf, unsigned int buf_size)
{
    EVP_MD_CTX *mdctx;
    unsigned char *md5_digest;
    unsigned int md5_digest_len = EVP_MD_size(EVP_md5());
    
    // MD5_Init
    mdctx = EVP_MD_CTX_new();
    EVP_DigestInit_ex(mdctx, EVP_md5(), NULL);

    // MD5_Update
    EVP_DigestUpdate(mdctx, buf, buf_size);

    // MD5_Final
    md5_digest = (unsigned char *)OPENSSL_malloc(md5_digest_len);
    EVP_DigestFinal_ex(mdctx, md5_digest, &md5_digest_len);
    EVP_MD_CTX_free(mdctx);
}
Run Code Online (Sandbox Code Playgroud)