OpenSSL中CTR_DRBG实现确定性输出的技术问题咨询
解决OpenSSL EVP API调用CTR-DRBG的确定性输出问题
要让CTR-DRBG输出确定性结果,核心是让OpenSSL的CTR-DRBG进入测试模式,允许你传入固定的熵、Nonce等参数,而不依赖系统熵源。以下是针对你提供的测试向量的完整实现:
关键要点
- 直接获取CTR-DRBG算法实例,通过提供者参数启用测试模式,而非使用TEST-RAND包装
- 手动设置所有配置参数(派生函数、预测抵抗、自动重新播种)匹配测试向量要求
- 用
EVP_RAND_CTX_set_params传入固定的熵、Nonce和个性化字符串
完整代码实现
#include <openssl/evp.h> #include <openssl/core_names.h> #include <string.h> #include <stdio.h> // 十六进制字符串转字节数组 int hex2bin(const char *hex, unsigned char *bin, size_t bin_len) { size_t hex_len = strlen(hex); if (hex_len % 2 != 0 || bin_len < hex_len / 2) return 0; for (size_t i = 0; i < hex_len; i += 2) { sscanf(hex + i, "%2hhx", &bin[i / 2]); } return 1; } int main() { // 初始化OpenSSL(按需) OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL); // 测试向量参数 const char *entropy_hex = "890eb067acf7382eff80b0c73bc872c6"; const char *nonce_hex = "aad471ef3ef1d203"; const char *expected_hex = "a5514ed7095f64f3d0d3a5760394ab42062f373a25072a6ea6bcfd8489e94af6cf18659fea22ed1ca0a9e33f718b115ee536b12809c31b72b08ddd8be1910fa3"; const size_t output_len = 64; // 512 bits = 64 bytes // 转换为字节数组 unsigned char entropy[16], nonce[8], expected[64], output[64]; if (!hex2bin(entropy_hex, entropy, sizeof(entropy)) || !hex2bin(nonce_hex, nonce, sizeof(nonce)) || !hex2bin(expected_hex, expected, sizeof(expected))) { fprintf(stderr, "Hex to binary conversion failed\n"); return 1; } // 获取测试模式下的CTR-DRBG(AES-128) OSSL_PROV_PARAM prov_params[] = { {OSSL_PROV_PARAM_TEST, "1"}, {NULL, NULL} }; EVP_RAND *rand = EVP_RAND_fetch(NULL, "CTR-DRBG:AES-128", prov_params); if (!rand) { fprintf(stderr, "Failed to fetch CTR-DRBG\n"); return 1; } // 创建RAND上下文 EVP_RAND_CTX *ctx = EVP_RAND_CTX_new(rand); EVP_RAND_free(rand); if (!ctx) { fprintf(stderr, "Failed to create RAND context\n"); return 1; } // 设置CTR-DRBG配置参数:启用派生函数,关闭预测抵抗,关闭自动重新播种 OSSL_PARAM params[] = { {OSSL_CTRDRBG_PARAM_DF, OSSL_PARAM_INTEGER, &(int){1}, sizeof(int), 0}, {OSSL_CTRDRBG_PARAM_PREDICTION_RESISTANCE, OSSL_PARAM_INTEGER, &(int){0}, sizeof(int), 0}, {OSSL_CTRDRBG_PARAM_RESEED_INTERVAL, OSSL_PARAM_INTEGER, &(unsigned long){0}, sizeof(unsigned long), 0}, {NULL, 0, NULL, 0, 0} }; if (!EVP_RAND_CTX_set_params(ctx, params)) { fprintf(stderr, "Failed to set DRBG config params\n"); EVP_RAND_CTX_free(ctx); return 1; } // 设置测试熵、Nonce、个性化字符串(空) OSSL_PARAM test_params[] = { {OSSL_RAND_PARAM_TEST_ENTROPY, OSSL_PARAM_OCTET_STRING, entropy, sizeof(entropy), 0}, {OSSL_RAND_PARAM_NONCE, OSSL_PARAM_OCTET_STRING, nonce, sizeof(nonce), 0}, {OSSL_RAND_PARAM_PERSONALIZATION, OSSL_PARAM_OCTET_STRING, "", 0, 0}, {NULL, 0, NULL, 0, 0} }; if (!EVP_RAND_CTX_set_params(ctx, test_params)) { fprintf(stderr, "Failed to set test params\n"); EVP_RAND_CTX_free(ctx); return 1; } // 实例化DRBG if (EVP_RAND_instantiate(ctx, 0, NULL, 0, NULL) <= 0) { fprintf(stderr, "Failed to instantiate DRBG\n"); EVP_RAND_CTX_free(ctx); return 1; } // 生成随机数(无附加输入) if (EVP_RAND_generate(ctx, output, output_len, 0, NULL, 0) <= 0) { fprintf(stderr, "Failed to generate random bytes\n"); EVP_RAND_CTX_free(ctx); return 1; } // 验证结果 if (memcmp(output, expected, output_len) == 0) { printf("Success! Output matches expected result.\n"); } else { printf("Error: Output does not match expected result.\n"); printf("Expected: "); for (size_t i = 0; i < output_len; i++) printf("%02x", expected[i]); printf("\nGot: "); for (size_t i = 0; i < output_len; i++) printf("%02x", output[i]); printf("\n"); } // 清理资源 EVP_RAND_CTX_free(ctx); return 0; }
代码说明
- 测试模式启用:通过
OSSL_PROV_PARAM_TEST参数让CTR-DRBG进入测试模式,允许传入自定义熵而非依赖系统熵源 - 配置参数匹配:
OSSL_CTRDRBG_PARAM_DF=1:启用派生函数,匹配测试向量要求OSSL_CTRDRBG_PARAM_PREDICTION_RESISTANCE=0:关闭预测抵抗OSSL_CTRDRBG_PARAM_RESEED_INTERVAL=0:禁用自动重新播种
- 参数传入:通过
OSSL_RAND_PARAM_TEST_ENTROPY、OSSL_RAND_PARAM_NONCE传入固定值,个性化字符串设为空 - 结果验证:对比生成的字节数组与测试向量的预期值
编译时需链接OpenSSL库:
gcc -o ctr_drbg_test ctr_drbg_test.c -lcrypto
内容的提问来源于stack exchange,提问作者Francisco Abelardo Garcia Avil
相关产品推荐
相关产品推荐

