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

如何将自定义Seed Provider设置为OpenSSL v3默认随机源?

在OpenSSL v3中让自定义Seed Provider支持RAND_bytes调用的实现方法

你已经实现了自定义Seed Provider,但RAND_bytes无法触发它的核心原因是:RAND_bytes默认使用OpenSSL内置的默认DRBG上下文,该上下文的种子源是系统默认熵源,而非你的自定义实现。要解决这个问题,需要将自定义Seed Provider注入到默认DRBG的种子源流程中,具体步骤如下:

核心原理

OpenSSL 3.x中,RAND_bytes/RAND_priv_bytes最终会调用全局默认的EVP_RAND_CTX(分别对应公钥/私钥随机上下文)。默认DRBG(如CTR-DRBG)会从配置的种子源获取熵值,我们需要修改这个默认上下文的种子源参数,替换为自定义的Seed Provider实例。

具体实现步骤

1. 确保自定义Seed Provider的关键接口正确实现

你的代码已经实现了OSSL_FUNC_RAND_GET_SEED(seedGetSeed函数),这是DRBG获取种子时会调用的核心接口,确保该函数能正确返回自定义熵源的数据即可。

2. 修改main函数,注入自定义种子源到默认流程

调整main函数逻辑,加载自定义Provider后,将自定义种子源绑定到OpenSSL的默认随机上下文:

int main(){
    const char* name = "trng-seed";

    OSSL_LIB_CTX* ctx = OSSL_LIB_CTX_new();
    OSSL_PROVIDER_add_builtin(ctx, name, seedProviderInit);

    // 加载自定义Seed Provider
    OSSL_PROVIDER* seedProvider = OSSL_PROVIDER_load(ctx, name);
    if(seedProvider == nullptr){
        printf("TRNG-SEED: DRBG set trng seed provider error\n");
        return 0;
    }

    // 创建并初始化自定义种子源的EVP_RAND_CTX
    EVP_RAND* rand_seed = EVP_RAND_fetch(ctx, name, nullptr);
    EVP_RAND_CTX* seed_ctx = EVP_RAND_CTX_new(rand_seed, nullptr);
    EVP_RAND_free(rand_seed);

    if (!EVP_RAND_instantiate(seed_ctx, 0, 0, nullptr, 0, nullptr)) {
        printf("TRNG-SEED: Failed to instantiate seed source\n");
        return 0;
    }

    // 获取RAND_bytes使用的默认公钥随机上下文
    EVP_RAND_CTX* default_public_ctx = RAND_get0_public();
    if (default_public_ctx == nullptr) {
        printf("TRNG-SEED: Failed to get default public RAND ctx\n");
        return 0;
    }

    // 设置默认DRBG的种子源为自定义实例
    OSSL_PARAM params[2];
    params[0] = OSSL_PARAM_construct_ptr(OSSL_DRBG_PARAM_SEED_SOURCE, seed_ctx);
    params[1] = OSSL_PARAM_construct_end();

    // 重新实例化默认DRBG,使新种子源生效
    if (!EVP_RAND_reinstantiate(default_public_ctx, 0, 0, nullptr, 0, params)) {
        printf("TRNG-SEED: Failed to reinstantiate default DRBG\n");
        return 0;
    }

    // 测试RAND_bytes是否调用自定义Seed Provider
    uint8_t bytes[1000000];
    while(1){
        if (RAND_bytes(bytes, sizeof(bytes)) != 1) {
            printf("TRNG-SEED: RAND_bytes failed\n");
            break;
        }
        // sleep(1);
    }

    // 资源释放
    EVP_RAND_CTX_free(seed_ctx);
    OSSL_PROVIDER_unload(seedProvider);
    OSSL_LIB_CTX_free(ctx);

    return 0;
}

3. 关键细节说明

  • 获取默认上下文:RAND_get0_public()获取RAND_bytes使用的全局上下文,RAND_get0_private()对应RAND_priv_bytes的上下文,若需要支持私钥场景,需对两个上下文都做配置。
  • 设置种子源参数:通过OSSL_DRBG_PARAM_SEED_SOURCE参数将自定义种子源的EVP_RAND_CTX传递给默认DRBG。
  • 重新实例化:默认DRBG在初始化后需要调用EVP_RAND_reinstantiate才能加载新的种子源配置。

验证效果

运行修改后的代码,你会看到TRNG-SEED: seedGetSeed等自定义Seed Provider的日志输出,说明RAND_bytes已经成功调用你的自定义熵源。

内容的提问来源于stack exchange,提问作者Özkan Eren

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 03:25:56