使用OpenSSL API通过TPM私钥解密时OSSL_STORE_CTX类型不兼容问题
解决OpenSSL中OSSL_STORE_CTX与EVP_PKEY_decrypt_init不兼容的问题
错误根源很明确:EVP_PKEY_decrypt_init() 要求传入EVP_PKEY_CTX*类型的解密上下文,但你传入的是用于加载密钥的OSSL_STORE_CTX*——这俩是OpenSSL里完全独立的上下文对象,根本不能混用。
修正后的代码示例
OSSL_STORE_CTX *store_ctx = OSSL_STORE_open(tpm_key_path, nullptr, nullptr, nullptr, nullptr); if (!store_ctx) { printf("Failed to open OSSL_STORE\n"); return; } EVP_PKEY *key = nullptr; OSSL_STORE_INFO *info; while (!OSSL_STORE_eof(store_ctx)) { info = OSSL_STORE_load(store_ctx); if (!info) { printf("Failed in OSSL_STORE_load\n"); break; } key = OSSL_STORE_INFO_get1_PKEY(info); OSSL_STORE_INFO_free(info); // 加载密钥后立即释放info if (!key) { printf("Failed in OSSL_STORE_INFO_get1_PKEY\n"); break; } break; } OSSL_STORE_close(store_ctx); // 密钥加载完成后关闭store上下文 if (key) { // 基于加载到的密钥创建专门的解密上下文 EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(key, nullptr); if (!pctx) { printf("Failed to create EVP_PKEY_CTX\n"); EVP_PKEY_free(key); return; } // 初始化解密操作 if (EVP_PKEY_decrypt_init(pctx) <= 0) { printf("Failed in EVP_PKEY_decrypt_init\n"); EVP_PKEY_CTX_free(pctx); EVP_PKEY_free(key); return; } // 设置RSA填充模式(根据你的实际需求调整) if (EVP_PKEY_CTX_set_rsa_padding(pctx, padding) <= 0) { printf("Failed to set RSA padding\n"); EVP_PKEY_CTX_free(pctx); EVP_PKEY_free(key); return; } // -------------------------- // 这里添加实际的解密逻辑: // 1. 先调用EVP_PKEY_decrypt获取输出缓冲区长度 // 2. 分配缓冲区后执行真正的解密 // -------------------------- // 释放所有资源 EVP_PKEY_CTX_free(pctx); EVP_PKEY_free(key); }
关键修正点
- 把原代码里的
ctx重命名为store_ctx,明确区分密钥加载上下文和解密上下文,避免混淆 - 加载完密钥后立即关闭
OSSL_STORE_CTX,它的作用只是加载密钥,用完就可以释放 - 用
EVP_PKEY_CTX_new()基于拿到的EVP_PKEY创建专门的解密上下文,这才是EVP_PKEY_decrypt_init()需要的参数 - 补充了完整的资源释放和错误处理,避免内存泄漏和隐性bug
内容的提问来源于stack exchange,提问作者vidyadhar
相关产品推荐
相关产品推荐

