EVP_PKEY_encrypt()返回输出大小为0的问题求助
解决EVP_PKEY_encrypt获取输出大小返回0的问题
先给你梳理清楚问题的核心:你遇到的第一个情况(直接用公钥调用EVP_PKEY_encrypt传空out返回0)大概率是加密上下文的关键配置步骤缺失;而第二个情况(存PEM再加载后得到128字节输出)其实是完全正常的——1024位RSA的加密输出长度本来就是128字节,和明文长短无关,这点先给你明确下来。
为什么第一次调用会返回0?
EVP_PKEY_encrypt返回0通常意味着上下文配置存在致命问题,最常见的两个原因:
- 未设置RSA填充模式:RSA加密必须依赖填充(除非你用极其特殊的裸RSA场景,几乎没人这么做),如果没调用
EVP_PKEY_CTX_set_rsa_padding指定填充方式,OpenSSL会直接拒绝执行,导致返回0,输出长度也不会被正确设置。 - 加密上下文初始化不完整:比如调用
EVP_PKEY_encrypt_init后,公钥关联失败、算法参数未正确加载等。
正确的EVP_PKEY加密流程(针对1024位RSA)
给你贴一个标准流程示例,你可以对照自己的代码排查:
// 假设pubkey是你已生成/获取的EVP_PKEY公钥对象 EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pubkey, NULL); if (!ctx) { // 处理上下文创建错误 } // 初始化加密上下文 if (EVP_PKEY_encrypt_init(ctx) <= 0) { // 处理初始化错误 EVP_PKEY_CTX_free(ctx); } // 设置RSA填充模式(必须!这里用最常用的PKCS#1 v1.5填充) if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0) { // 处理填充模式设置错误 EVP_PKEY_CTX_free(ctx); } // 第一步:获取输出缓冲区大小 size_t outlen; if (EVP_PKEY_encrypt(ctx, NULL, &outlen, plaintext, plaintext_len) <= 0) { // 此前返回0,大概率是因为没设置填充模式 EVP_PKEY_CTX_free(ctx); } // 分配输出缓冲区 unsigned char *outbuf = malloc(outlen); if (!outbuf) { // 处理内存分配错误 EVP_PKEY_CTX_free(ctx); } // 第二步:执行加密 if (EVP_PKEY_encrypt(ctx, outbuf, &outlen, plaintext, plaintext_len) <= 0) { // 处理加密错误 free(outbuf); EVP_PKEY_CTX_free(ctx); } // 此时outlen即为加密后数据长度,1024位RSA+PKCS1填充下就是128字节 // 记得释放资源 free(outbuf); EVP_PKEY_CTX_free(ctx);
为什么存PEM再加载后得到128是正常的?
RSA加密的输出长度严格等于密钥的字节长度(1024位对应128字节),不管你的明文是1个字符还是100个字符(只要明文长度不超过密钥长度减填充长度——1024位PKCS1填充下,明文最多117字节)。填充机制会自动把明文扩展到密钥长度,所以输出固定为128字节,这完全符合预期,不是问题。
额外排查建议
如果按照上面的流程还是有问题,可以试试这两个方向:
- 验证公钥有效性:用
EVP_PKEY_get_bits(pubkey)确认生成的公钥确实是1024位。 - 查看详细错误:调用
ERR_print_errors_fp(stderr)打印OpenSSL错误栈,能帮你定位具体哪里出了问题,比只看返回值有用得多。
内容的提问来源于stack exchange,提问作者void.pointer
相关产品推荐
相关产品推荐

