编译Litecoind时出现EVP_EncryptInit_ex函数匹配错误,求解决方案
解决莱特币litecoind编译时OpenSSL版本兼容错误
问题背景
编译最新版莱特币litecoind源码时,因OpenSSL版本差异触发编译错误:
- 最初遇到
error: field 'ctx' has incomplete type EVP_CIPHER_CTX,将EVP_CIPHER_CTX ctx;改为EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();后该错误消除; - 随后出现新错误:
error: no matching function for call to 'EVP_EncryptInit_ex'(注:实际代码中调用的是EVP_DecryptInit_ex,错误提示源于API参数不匹配的连锁反应)。
核心原因
OpenSSL 1.1.0及以上版本对EVP_CIPHER_CTX做了不透明化处理:
- 必须通过
EVP_CIPHER_CTX_new()创建实例,EVP_CIPHER_CTX_free()释放资源; - 加密/解密系列函数(如
EVP_DecryptInit_ex)的第一个参数类型从旧版的EVP_CIPHER_CTX**改为EVP_CIPHER_CTX*,旧代码中传递&ctx(指针的指针)会导致参数类型不匹配; - 新版中
EVP_CIPHER_CTX_new()已完成初始化,无需再调用EVP_CIPHER_CTX_init。
解决方案
对代码做两处关键修改:
- 移除冗余的
EVP_CIPHER_CTX_init(ctx)调用; - 将
EVP_DecryptInit_ex、EVP_DecryptUpdate、EVP_DecryptFinal_ex的第一个参数从&ctx改为ctx。
同时新增空指针检查,提升代码健壮性。
修正后的代码
bool CCrypter::Decrypt(const std::vector<unsigned char>& vchCiphertext, CKeyingMaterial& vchPlaintext) { if (!fKeySet) return false; // plaintext will always be equal to or lesser than length of ciphertext int nLen = vchCiphertext.size(); int nPLen = nLen, nFLen = 0; vchPlaintext = CKeyingMaterial(nPLen); EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); if (!ctx) return false; bool fOk = true; if (fOk) fOk = EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, chKey, chIV); if (fOk) fOk = EVP_DecryptUpdate(ctx, &vchPlaintext[0], &nPLen, &vchCiphertext[0], nLen); if (fOk) fOk = EVP_DecryptFinal_ex(ctx, (&vchPlaintext[0])+nPLen, &nFLen); EVP_CIPHER_CTX_free(ctx); if (!fOk) return false; vchPlaintext.resize(nPLen + nFLen); return true; }
额外说明
- 若仍出现
EVP_EncryptInit_ex相关错误,需检查代码中其他加密逻辑的调用方式,同样遵循“直接传递EVP_CIPHER_CTX*指针”的规则; - 确保编译环境的OpenSSL版本符合莱特币源码的兼容要求,若源码未全面适配新版OpenSSL,需同步修改其他使用
EVP_CIPHER_CTX的代码片段。
内容的提问来源于stack exchange,提问作者Mikhail Gryaznov
相关产品推荐
相关产品推荐

