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

基于OpenSSL 0.9.8a API验证4096位RSA签名的技术问询

验证4096位RSA SHA512签名(OpenSSL 0.9.8a实现)

首先得给你提个关键的点:你的代码里最后一步用了EVP_DigestFinal_ex,这是个错误——在签名验证流程中,最后应该调用EVP_DigestVerifyFinal来完成验证,而不是生成摘要的EVP_DigestFinal_ex。这是很容易踩的坑,先帮你纠正过来,再给你完整的可运行实现。

完整代码实现

下面是补全并修正后的代码,包含完整的错误处理和内存管理,适配OpenSSL 0.9.8a的API:

#include <openssl/evp.h>
#include <openssl/rsa.h>
#include <openssl/err.h>
#include <stdio.h>
#include <stdbool.h>

// 加载RSA公钥(从PEM格式文件)
EVP_PKEY* load_rsa_public_key(const char* pub_key_path) {
    FILE* fp = fopen(pub_key_path, "rb");
    if (!fp) {
        perror("Failed to open public key file");
        return NULL;
    }

    EVP_PKEY* pubKey = PEM_read_PUBKEY(fp, NULL, NULL, NULL);
    fclose(fp);

    if (!pubKey) {
        fprintf(stderr, "Failed to load public key: ");
        ERR_print_errors_fp(stderr);
    }
    return pubKey;
}

// 验证4096位RSA SHA512签名
bool verify_rsa_sha512_signature(EVP_PKEY* pubKey, const unsigned char* msg, size_t msg_len, 
                                 const unsigned char* signature, size_t sig_len) {
    // 创建EVP消息摘要上下文
    EVP_MD_CTX* ctx = EVP_MD_CTX_create();
    if (!ctx) {
        fprintf(stderr, "Failed to create EVP_MD_CTX: ");
        ERR_print_errors_fp(stderr);
        return false;
    }

    // 获取SHA512摘要算法
    const EVP_MD* md = EVP_get_digestbyname("SHA512");
    if (!md) {
        fprintf(stderr, "Failed to get SHA512 digest: ");
        ERR_print_errors_fp(stderr);
        EVP_MD_CTX_destroy(ctx);
        return false;
    }

    // 初始化签名验证上下文
    if (EVP_DigestVerifyInit(ctx, NULL, md, NULL, pubKey) <= 0) {
        fprintf(stderr, "Failed to init digest verify: ");
        ERR_print_errors_fp(stderr);
        EVP_MD_CTX_destroy(ctx);
        return false;
    }

    // 传入待验证的消息内容
    if (EVP_DigestUpdate(ctx, msg, msg_len) <= 0) {
        fprintf(stderr, "Failed to update digest: ");
        ERR_print_errors_fp(stderr);
        EVP_MD_CTX_destroy(ctx);
        return false;
    }

    // 完成签名验证
    int verify_result = EVP_DigestVerifyFinal(ctx, signature, sig_len);

    // 释放上下文资源
    EVP_MD_CTX_destroy(ctx);

    // 解析验证结果
    if (verify_result == 1) {
        printf("Signature verified successfully!\n");
        return true;
    } else if (verify_result == 0) {
        fprintf(stderr, "Signature verification failed: signature does not match\n");
    } else {
        fprintf(stderr, "Error during signature verification: ");
        ERR_print_errors_fp(stderr);
    }
    return false;
}

// 示例调用
int main() {
    // 初始化OpenSSL错误库
    ERR_load_crypto_strings();
    OpenSSL_add_all_algorithms();

    EVP_PKEY* pubKey = load_rsa_public_key("public_key.pem");
    if (!pubKey) {
        return 1;
    }

    // 假设这里是你的消息和签名数据
    unsigned char msg[] = "Your message to verify";
    size_t msg_len = sizeof(msg) - 1;
    unsigned char signature[512]; // 4096位RSA签名长度是512字节
    size_t sig_len = 512;

    // 实际场景中需要从文件或网络读取签名数据
    // ...

    bool result = verify_rsa_sha512_signature(pubKey, msg, msg_len, signature, sig_len);

    // 释放公钥资源
    EVP_PKEY_free(pubKey);

    // 清理OpenSSL资源
    EVP_cleanup();
    ERR_free_strings();

    return result ? 0 : 1;
}

关键注意事项(针对OpenSSL 0.9.8a)

  • 签名格式默认值:OpenSSL 0.9.8a的EVP_DigestVerifyInit默认使用PKCS#1 v1.5填充方案。如果你的签名是用PSS填充生成的,需要手动设置填充模式——但要注意,0.9.8a的EVP接口对PSS的支持有限,可能需要直接使用RSA底层函数(比如RSA_verify)来处理PSS签名。
  • 4096位RSA支持:0.9.8a默认支持4096位RSA密钥,但如果是嵌入式环境编译,需要确保编译时开启了大整数支持(通常默认是开启的)。
  • 错误调试:一定要用上ERR_print_errors_fp打印错误信息,OpenSSL的函数返回值只会告诉你失败,但具体原因都存在错误队列里,这个函数能帮你快速定位问题。
  • 资源管理:所有创建的OpenSSL对象(EVP_MD_CTX、EVP_PKEY)都要记得用对应的销毁函数释放,避免内存泄漏。

内容的提问来源于stack exchange,提问作者MBA_BAT88

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:42:40