摘要算法:AIX 5.3 使用 openssl 實現 md5 等
環境:
$ uname -a
AIX aix68112 3 5 00F7CAA94C00
查看 openssl 庫:
$ ll /usr/lib/*ssl*
lrwxrwxrwx 1 root system 41 Jul 24 2017 /usr/lib/libgsk7ssl_64.so -> /usr/opt/ibm/gsksa/lib64/libgsk7ssl_64.so
-r-xr-xr-x 1 root system 8595301 May 19 02:09 /usr/lib/libssl.a
-r-xr-xr-x 1 root system 3400639 May 19 02:09 /usr/lib/libssl_compat.a
注意:此處 openssl 在 AIX 5.3 中是以靜態庫形式存在的。
代碼:
$ cat main.c
#include <stdio.h>
#include <string.h>
#include <openssl/evp.h>
int main(int argc, char *argv[])
{
EVP_MD_CTX mdctx;
const EVP_MD *md;
unsigned char md_value[EVP_MAX_MD_SIZE];
int md_len, i;
OpenSSL_add_all_digests();
/*********************************************************************/
char *algorithm = "md5";
char *msg = "0123456789abcdef";
md = EVP_get_digestbyname(algorithm);
if(!md) {
fprintf(stderr, "Unknown message digest %s\n", algorithm);
exit(1);
}
EVP_MD_CTX_init(&mdctx);
EVP_DigestInit_ex(&mdctx, md, NULL);
EVP_DigestUpdate(&mdctx, msg, strlen(msg));
EVP_DigestFinal_ex(&mdctx, md_value, &md_len);
EVP_MD_CTX_cleanup(&mdctx);
for(i = 0; i < md_len; i++) {
fprintf(stdout, "%02x", md_value[i]);
}
fprintf(stdout, "\n");
return 0;
}
編譯 && 鏈接:
$ xlc -o main main.c -lssl
"main.c", line 26.46: 1506-280 (W) Function argument assignment between types "unsigned int*" and "int*" is not allowed.
ld: 0711-317 ERROR: Undefined symbol: .OpenSSL_add_all_digests
ld: 0711-317 ERROR: Undefined symbol: .EVP_get_digestbyname
ld: 0711-317 ERROR: Undefined symbol: .EVP_MD_CTX_init
ld: 0711-317 ERROR: Undefined symbol: .EVP_DigestInit_ex
ld: 0711-317 ERROR: Undefined symbol: .EVP_DigestUpdate
ld: 0711-317 ERROR: Undefined symbol: .EVP_DigestFinal_ex
ld: 0711-317 ERROR: Undefined symbol: .EVP_MD_CTX_cleanup
ld: 0711-345 Use the -bloadmap or -bnoquiet option to obtain more information.
問題:找不到符號定義(函數)。
嘗試從 libssl.a 中查找 EVP_get_digestbyname 的符號定義:
$ nm /usr/lib/libssl.a | grep OpenSSL_add_all_digests
$
確實沒有此函數的全局符號定義。
AIX 5.3 中的 openssl 命令是如何工作的呢?
$ ldd `which openssl`
/usr/bin/openssl needs:
/usr/lib/libc.a(shr.o)
/usr/lib/libcrypto.a(libcrypto.so.1.0.0)
/usr/lib/libssl.a(libssl.so.1.0.0)
/unix
/usr/lib/libcrypt.a(shr.o)
查看到一個特殊的庫:libcrypto.a。
嘗試添加 -lcrypto 庫進行編譯鏈接:
$ xlc -o main main.c -lssl -lcrypto
"main.c", line 26.46: 1506-280 (W) Function argument assignment between types "unsigned int*" and "int*" is not allowed.
$ ./main
4032af8d61035123906e58e067140cc5
編譯、鏈接、執行成功!
我們看看 libcrypto.a 庫是否有 OpenSSL_add_all_digests 符號定義:
$ nm /usr/lib/libcrypto.a | grep OpenSSL_add_all_digests
.OpenSSL_add_all_digests T 269522904
OpenSSL_add_all_digests D 536987800 12
.OpenSSL_add_all_digests T 269522904
OpenSSL_add_all_digests D 536987800 12
.OpenSSL_add_all_digests T 269125248
OpenSSL_add_all_digests D 536979844 12
.OpenSSL_add_all_digests T 269522904
OpenSSL_add_all_digests D 536987800 12
既然 libssl.a 中沒有此函數定義,而 libcrypto.a 中有此函數定義,嘗試單獨使用 libcrypto.a 鏈接:
$ xlc -o main main.c -lcrypto
"main.c", line 26.46: 1506-280 (W) Function argument assignment between types "unsigned int*" and "int*" is not allowed.
$ ./main
4032af8d61035123906e58e067140cc5
OK!!!
AIX 5.3 中使用 openssl 實現相關算法時在鏈接處需要指明 libcrypto.a 靜態庫。否則將找不到符號定義。