前言
许久未更新,实在没想到这一拖就是几个月,小半年也过去了。这段时间,没能坚持写一下内容出来,也是没办法。工作了,就没有了上学时的清闲,但是这都是主观的。客观上还是有时间的,只不过是自己懒了,嘿嘿,不辩解了,回到正文吧,看看有没有小伙伴遇到这个问题。
问题描述
问题来源是现在空闲着写来玩的一个项目,主要是做U盘文件加密解密的一个小软件。这个时候,就需要加密算法了,我这么懒不可能手撸加密算法的,而且要是在加密的过程中,可以采用多种加密算法的话,就更好了。有OPENSSL和Cryptopp给我选,然后快乐的选择了Cryptopp,以为OPENSSL在大一我编译它的时候,给我留下了不少阴影,哈哈哈,当年可真菜,虽然现在也一样。
看一下导致问题的代码,摘抄一部分如下
1 2 3 4 5 6
| typedef EAX_Final<AES, true> aes_encryption; typedef EAX_Final<AES, false> aes_decryption; aes_encryption* encoder_; aes_decryption* decoder_; encoder_ = new aes_encryption(); encoder_->SetKeyWithIV(aes_key_, aes_key_.size(), iv_);
|
然后,编译的时候,快乐的报错就来了
1 2 3 4 5 6
| 1>symmetryEncrypt.obj : error LNK2001: 无法解析的外部符号 "protected: virtual void __cdecl CryptoPP::EAX_Base::SetKeyWithoutResync(unsigned char const *,unsigned __int64,class CryptoPP::NameValuePairs const &)" (?SetKeyWithoutResync@EAX_Base@CryptoPP@@MEAAXPEBE_KAEBVNameValuePairs@2@@Z) 1>symmetryEncrypt.obj : error LNK2001: 无法解析的外部符号 "protected: virtual void __cdecl CryptoPP::EAX_Base::Resync(unsigned char const *,unsigned __int64)" (?Resync@EAX_Base@CryptoPP@@MEAAXPEBE_K@Z) 1>symmetryEncrypt.obj : error LNK2001: 无法解析的外部符号 "protected: virtual unsigned __int64 __cdecl CryptoPP::EAX_Base::AuthenticateBlocks(unsigned char const *,unsigned __int64)" (?AuthenticateBlocks@EAX_Base@CryptoPP@@MEAA_KPEBE_K@Z) 1>symmetryEncrypt.obj : error LNK2001: 无法解析的外部符号 "protected: virtual void __cdecl CryptoPP::EAX_Base::AuthenticateLastHeaderBlock(void)" (?AuthenticateLastHeaderBlock@EAX_Base@CryptoPP@@MEAAXXZ) 1>symmetryEncrypt.obj : error LNK2001: 无法解析的外部符号 "protected: virtual void __cdecl CryptoPP::EAX_Base::AuthenticateLastFooterBlock(unsigned char *,unsigned __int64)" (?AuthenticateLastFooterBlock@EAX_Base@CryptoPP@@MEAAXPEAE_K@Z) 1>E:\UdiskEncryptTools.exe : fatal error LNK1120: 5 个无法解析的外部命令
|
分析问题
在这里可以清楚的看到它提示,缺少EAX_Base类下面的SetKeyWithoutResync、AuthenticateBlocks、Resync…这些函数。
跟进一下 EAX_Final 这个类,可以看到他是继承自 EAX_Base,而 EAX_Base 又继承自 AuthenticatedSymmetricCipherBase, 然后缺失的函数都在这里类里面。
部分代码摘抄如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| class CRYPTOPP_NO_VTABLE EAX_Base : public AuthenticatedSymmetricCipherBase { public: std::string AlgorithmName() const ...
template <class T_BlockCipher, bool T_IsEncryption> class EAX_Final : public EAX_Base { public: static std::string StaticAlgorithmName() ...
protected: void SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs ¶ms); void Resync(const byte *iv, size_t len); size_t AuthenticateBlocks(const byte *data, size_t len); void AuthenticateLastHeaderBlock();
|
好的,有定义和声明的话,肯定是没问题的。再编译一次这个cryptopp.dll看看,然后再编译咱们的项目。依旧是提示缺失这几个东西。我。。。。
不急,一步一步来,看看dll里面有没有这个EAX的东西,用DLL Export Viewer 打开 cryptopp.dll看看
太多了不想翻,直接搜 EAX
还真没有 -_-
那就说明了,编译dll的时候,就没有导出这个函数,那肯定找不到符号嗦。那我们只要将它声明导出函数就可啦。
解决之路
来打开cryptopp的项目,找到编译dll的项目
然后会发现找不到eax.h 和 eax.cpp
所以,手动添加进来,添加现有项即可
添加好之后,兴冲冲的编译dll,然后去编我的exe,然后还是没找到
淦
所以还是有问题的,回去看eax的源码,比对一下其它有导出函数的类的区别
答案是一目了然的,它缺了一个宏来修饰,以下是这个宏的声明,是用来声明导出的
1
| # define CRYPTOPP_DLL __declspec(dllexport)
|
那解决方案也呼之欲出了,将这个宏加上就可
1 2 3 4 5 6 7
| class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE EAX_Base : public AuthenticatedSymmetricCipherBase { public: std::string AlgorithmName() const ...
|
编译
编译一手
8核16线程的U跑起编译来简直不要太舒服
用工具看看是否有导出函数了,可以看到找到了,稳了
编译项目EXE去看看,也正常起来了
嗯,差不多了,问题解决了,文字也到这里了,要是能帮到遇到同样问题的同学就最好了,没的话,我下次扑街了也好看博客来找到解决方案