You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:35:18