如何将自定义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
相关产品推荐
相关产品推荐

