在项目中遇到需要使用sm4加密的功能,同事在一个动态库(C库)里面使用了openssl中的sm4加密,成功编译并功能正常。我也需要在项目(QT程序)中同样的方式使用sm4加密与之通讯,结果我卡在链接的位置无法编程完成,下面是摘出来的demo:

#include <stdio.h>
#include <memory.h>
#include <malloc.h>
#include <openssl/ossl_typ.h>
#include <openssl/aes.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <openssl/sm2.h>
#include <openssl/sm4.h>
#include <openssl/evp.h>
#include <openssl/ec.h>#define PKCS1_HEADER "-----BEGIN RSA PUBLIC KEY-----"
#define PKCS8_HEADER "-----BEGIN PUBLIC KEY-----"enum EncryptType {ET_RSA = 0,ET_SM2
};int main(int argc, char *argv[])
{const int tokenSize = 256;const int padding = AES_BLOCK_SIZE - tokenSize % AES_BLOCK_SIZE;const int blockCount = 256;const int bufferSize = blockCount * AES_BLOCK_SIZE;char *tokenBuffer = new char[static_cast<size_t>(bufferSize)];memset(tokenBuffer, padding, static_cast<size_t>(bufferSize));char *ciphertext = new char[static_cast<size_t>(bufferSize)];memset(ciphertext, 0, static_cast<size_t>(bufferSize));char *symmetricKey = new char[static_cast<size_t>(bufferSize)];SM4_KEY sm4;AES_KEY aes;int ret = 0;EncryptType m_encryptType = ET_SM2;if (ET_SM2 == m_encryptType) {SM4_set_key(reinterpret_cast<uint8_t *>(symmetricKey), &sm4);} else {AES_set_encrypt_key(reinterpret_cast<unsigned char *>(symmetricKey), strlen(symmetricKey), &aes);}if (ret < 0) {delete[] tokenBuffer;delete[] ciphertext;return 0;}unsigned char *iv = new unsigned char[AES_BLOCK_SIZE];memset(iv, 0, AES_BLOCK_SIZE);if (ET_SM2 == m_encryptType) {SM4_encrypt(reinterpret_cast<uint8_t *>(tokenBuffer), reinterpret_cast<uint8_t *>(ciphertext), &sm4);} else {AES_cbc_encrypt(reinterpret_cast<unsigned char *>(tokenBuffer), reinterpret_cast<unsigned char *>(ciphertext), static_cast<size_t>(bufferSize), &aes, iv, AES_ENCRYPT);}delete[] ciphertext;delete[] tokenBuffer;delete[] iv;return 0;
}

报错如下:

$ gcc -o libtest.so test.cpp -lstdc++ -lcrypto    /usr/bin/ld: /tmp/ccR5x6An.o: in function `main':
test.cpp:(.text+0xb0): undefined reference to `SM4_set_key(unsigned char const*, SM4_KEY_st*)'
/usr/bin/ld: test.cpp:(.text+0x14f): undefined reference to `SM4_encrypt(unsigned char const*, unsigned char*, SM4_KEY_st const*)'
collect2: error: ld returned 1 exit status

库肯定是link成功了 ,因为其他的函数都没有报错,只有sm4的程序报了。我也是百思不得其解,我尝试使用同事编译过的项目,发现,加上-shared就能编译通过

gcc -shared -o libtest.so test.cpp -lstdc++ -lcrypto

很离谱,我的QT界面项目当然不能加这个参数。

我就仔细看了下sm4.h,忽然发现头文件中没有用extern "C"修复函数!

C++在编译的过程中会改变函数的名称,与C语言的规则不一致,这样在链接的时候就无法找到C语言对应的函数,从而导致undefined reference!

在需要使用源文件中将原来的include 用extern "C"修饰就可以编译通过了。

#ifdef __cplusplus
extern "C" {
#endif
#include <openssl/sm2.h>
#include <openssl/sm4.h>
#ifdef __cplusplus
}
#endif

CMakeLists

需要注意的几个地方:

# cmake > 3.12 详见https://cmake.org/cmake/help/latest/module/FindOpenSSL.html
find_package(OpenSSL REQUIRED) target_link_libraries(${ProjectName} PRIVATE${OPENSSL_CRYPTO_LIBRARY}
)

总结

在C++中使用C库的时候,如果遇到链接问题,要注意C库的头文件中是否使用extern "C"修饰了函数。

OpenSSL SM4加密 CMake工程链接失败相关推荐

  1. 初识CMake,如何编写一个CMake工程(上)

    如何编写一个CMake工程 笔者想分享CMake工程的原因? 1 接触CMake 1.1 认识CMake被广泛的使用? 1.2 了解CMake运行流程 1.3 Make和Makefile是什么关系? ...

  2. 初识CMake,如何编写一个CMake工程(下)

    如何编写一个CMake工程 上文分析了针对一个源文件.多个源文件.多个目录的情况 1 CMake自定义编译选项Demo4 1.1 效果展示 2 CMake安装(make install)与测试(mak ...

  3. c++/c SM4加密解密算法代码实现

    #include <openssl/sms4.h>int main(void) {//加密参数初始化sms4_key_t sms4_key_enc;unsigned char *plain ...

  4. Linux下CMake工程中gtestgmock的安装与使用

    Linux下CMake工程中gtest&gmock的安装与使用 gtest和gmock是什么和功能以及用法可参考以下两篇文章,都相当给力! gtest <玩转Google开源C++单元测 ...

  5. 使用加密锁加密Unity工程插件源码

    使用加密锁加密Unity工程插件源码 最近在unity3D中开发了一款插件,需要卖给客户,但是公司需要隐藏插件的源码,而且保证客户只有指定的电脑才能使用该插件开发!针对这个问题,分为两个步骤:1.隐藏 ...

  6. 安卓和php接口数据传输加密,安卓与PHP间的RSA(openssl)交互加密的坑

    这几天在写一个安卓的RSA公钥加密算法,用于跟PHP后台接口进行交互.在实践过程中发现了几个坑.其中我的公钥和私钥都是通过openssl生成的pem格式. 遇到的坑: 1.通过java的RSA公钥加密 ...

  7. C#.NET 国密SM4加密解密 CBC ECB 2种模式

    注意点: 1.加密时,明文转 byte[] 时,不要用 Encoding.Default,一定要指定编码,如:UTF-8. 解密时,解出的 byte[] 转 string 同样要指定相同的编码. 2. ...

  8. python SM4加密

    import binascii #导入国密算法sm4包 from gmssl import sm4 def sm4_encode(key, data):     """ ...

  9. 解决“libboost_regex-vc120-mt-gd-1_59.lib“链接失败问题

    在VS2013 64位+Boost 64 位 v1.59编程中,有时会遇到*.lib链接失败的问题.通常该问题有2种情况:         A)电脑里没有安装Boost v1.59,或者安装的版本不对 ...

最新文章

  1. Centos7 编译安装 Nginx、MariaDB、PHP
  2. java class 生成对象_Java反射机制(创建Class对象的三种方式)
  3. UA MATH571B 试验设计 QE练习题 不使用代码分析试验结果I
  4. 【Java】15 输入输出
  5. zipaligin不是内部或外部命令,也不是可运行的程序
  6. 安卓开发中的USB转串口通讯
  7. Linux基础入门学习笔记之二
  8. pil 图像最大值_第97天:图像库 PIL(二)
  9. 七、线性表的链式存储结构
  10. python大学教程 pdf_『Python核心编程(第二版)PDF和Python基础教程(第二版)PDF?』python大学教程pdf下载...
  11. linux系统安装java环境_linux系统java环境配置
  12. 动态爬虫之qzone空间自动秒赞 - qq空间自动点赞
  13. VMWARE 之 分布式网络交换机
  14. 婚纱摄影、影楼、照相馆流量制造工具预约系统之种草社区
  15. 宠物商店——三层架构
  16. 手机屏幕驱动板HDMI调光触摸旋转说明Fondar
  17. PCL中采样一致性算法
  18. CSS常见选择器的用法
  19. SVG中年月日相关的表达式
  20. JAVA JDK8的介绍下载和安装(附网盘地址)

热门文章

  1. 冰河指南AI技术社区基于ChatGPT正式启动运营
  2. 对话屏幕Dynpro(se51)
  3. 修复LSP 解决不能上网问题
  4. (一)傅里叶变换:傅里叶级数(Fourier Series)
  5. 微信H5页面禁用复制链接
  6. python爬虫登录微博_为爬虫获取登录cookies: 使用Charles和requests模拟微博登录
  7. 九安医疗上半年净利152亿:同比增27728% 李志毅减持
  8. 实用教程 | 如何查看微信朋友圈访客
  9. 破解AI开课难题!2021 全国人工智能师资培训落地厦门大学
  10. matlab纹理柱状图程序