【问题标题】:OpenSSL Linking undefined reference 'EVP_MD_CTX_new' and '...fre'OpenSSL 链接未定义的参考 'EVP_MD_CTX_new' 和 '...fre'
【发布时间】:2017-10-16 10:25:07
【问题描述】:

我正在尝试使用 openssl 库提供的哈希算法。 我安装了 openssl 和 libssl-dev。版本为 1.1.0f。 我尝试运行 openssl.org 站点的示例代码:

#include <stdio.h>

#include <openssl/evp.h>

int main(int argc, char *argv[]){
EVP_MD_CTX *mdctx;
const EVP_MD *md;
char mess1[] = "Test Message\n";
char mess2[] = "Hello World\n";
unsigned char md_value[EVP_MAX_MD_SIZE];
int md_len, i;

if(!argv[1]) {
    printf("Usage: mdtest digestname\n");
    exit(1);
 }

md = EVP_get_digestbyname(argv[1]);

if(!md) {
    printf("Unknown message digest %s\n", argv[1]);
    exit(1);
}

mdctx = EVP_MD_CTX_new();
EVP_DigestInit_ex(mdctx, md, NULL);
EVP_DigestUpdate(mdctx, mess1, strlen(mess1));
EVP_DigestUpdate(mdctx, mess2, strlen(mess2));
EVP_DigestFinal_ex(mdctx, md_value, &md_len);
EVP_MD_CTX_free(mdctx);

printf("Digest is: ");
for (i = 0; i < md_len; i++)
    printf("%02x", md_value[i]);
printf("\n");

exit(0);
}

我尝试用以下代码编译:

 gcc digest_example.c -lcrypto -lssl

编译器给出错误:

digest_example.c:(.text+0xbc): undefined reference to `EVP_MD_CTX_new'
digest_example.c:(.text+0x138): undefined reference to `EVP_MD_CTX_free'
collect2: error: ld returned 1 exit status

老实说,我一无所知。我通过编译从网站安装并重新安装了 OpenSSL 2 次。此外,所有其他命令都没有问题。就这两个。链接时是否必须使用其他库?

感谢您的帮助。

【问题讨论】:

  • 使用gcc digest_example.c -lssl -lcrypto gcc digest_example.c -lcrypto -lssl。 LD 是单通道链接器。 libssl 依赖于libcrypto,所以libcrypto 需要跟随libssl。另一种方法是使用--start-group &lt;archives&gt; --end-group 链接器选项。另请参阅 ld(1) 手册页。
  • -lssl 和 -lcrypto 的顺序没有使它起作用。我把它们都换了,没有任何区别。看来,链接器和标头使用了不同的 OpenSSL 库。
  • OpenSSL 1.1.0 标头和库位于您的计算机上时的状态。注意:我知道的所有发行版都提供 OpenSSL 1.0.2;不是 OpenSSL 1.1.0。
  • 它提供了 1.0.2 。但我想使用 1.1.0,所以我从 openssl.org 下载了二进制文件并编译了它们。但似乎,在系统库中它仍然是旧版本。

标签: c linux linker openssl


【解决方案1】:

您似乎使用的是旧版本的 openssl (

1.1.0 中的EVP_MD_CTX_new() 已替换 1.0.x 中的EVP_MD_CTX_create()

1.1.0 中的EVP_MD_CTX_free() 已替换 1.0.x 中的EVP_MD_CTX_destroy()

您可以尝试使用这些函数的旧版本,或者确保您的链接器确实使用 >= 1.1.0 版本的 openssl 库。

【讨论】:

  • 感谢您的想法。但有趣的是,如果我使用 EVP_MD_CTX_create() 或 EVP_MD_CTX_destroy(),链接器的输出会带有 _new 和 _free。明天我将尝试链接器的规范。
  • @K.Math 这也可以解释:当使用 openssl 1.1.0 的头文件时,有兼容性宏,例如# define EVP_MD_CTX_create() EVP_MD_CTX_new()。所以你似乎使用 1.1.0 头文件,但链接到 1.0.x 库。
  • 谢谢。添加 -L 后,它起作用了。
【解决方案2】:

版本是1.1.0f。我尝试运行 openssl.org 站点的示例代码...

我通过编译从网站安装并重新安装了 OpenSSL 2 次...

我相信 OpenSSL 1.1.0 会安装到 /usr/local/ssl。标头位于/usr/local/ssl/include,库位于/usr/local/ssl/lib。您需要编译和链接:

gcc -I /usr/local/ssl digest_example.c -Wl,-L,/usr/local/lib -lssl -lcrypto

事实上,因为 Linux 路径是 f**k'd,所以您需要添加一个 RPATH,以便在运行时(而不是编译时)链接到正确的库。因此,您确实需要以下内容,因为 Linux 在 30 年左右后仍然无法做到这一点:

gcc -I /usr/local/ssl digest_example.c -Wl,-rpath,/usr/local/lib -Wl,-L,/usr/local/lib -lssl -lcrypto

您仍然需要正确排列库的顺序,因为 LD 是单通道链接器。

您的命令与系统的 OpenSSL 版本相关联,即 1.0.2。

 gcc digest_example.c -lcrypto -lssl

但是,库的顺序是错误的。这些库应该被称为-lssl -lcrypto

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-07-24
    • 2016-01-29
    • 2017-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-19
    • 1970-01-01
    相关资源
    最近更新 更多