附录 A. KDF 示例 (OpenSSL)
中文导读: 本节对应 RFC 9946 的 附录 A. KDF 示例 (OpenSSL) 部分, 对应文档标题为 RFC 9946 - 用于单向 IP 容量度量测量的 UDP Speed Test Protocol (UDPSTP). 下方若包含英文 RFC 原文, 注册表名称, 字段名, 算法名, 对象标识符, 媒体类型, 邮箱地址, URL, 代码, ABNF, ASN.1, YANG, JSON, XML, 测试向量或参考文献条目, 均按规范原样保留, 因为这些内容需要与 RFC 文本, IANA 注册表, 实现代码或验证工具逐字一致. 中文段落用于说明本节的作用, 阅读重点和实现含义, 不改变任何协议语义或注册值.
本页中的示例, 测试向量和样例报文用于帮助实现者验证编码, 解析, 互操作或错误处理行为. 示例值, 二进制串, Base64, 十六进制, JSON/XML 成员, HTTP/邮件头字段, 域名和地址均属于可复制测试材料, 因此不翻译. 中文说明只解释示例目的, 字段关系和使用注意事项.
<CODE BEGINS>
//
// Output individual authentication keys of length SHA256_KEY_LEN
// from derived key material.
//
// Return Values: 0 = Failure, 1 = Success
//
int kdf_hmac_sha256(char *Kin, uint32_t authUnixTime,
unsigned char *cAuthKey, // Client key
unsigned char *sAuthKey) { // Server key
int var, keylen = SHA256_KEY_LEN * 2;
char context[16];
unsigned char *keyptr, keybuf[keylen];
EVP_KDF *kdf = NULL;
EVP_KDF_CTX *kctx = NULL;
OSSL_PARAM params[16], *p = params;
//
// Fetch KDF algorithm and create context
//
if ((kdf = EVP_KDF_fetch(NULL, "KBKDF", NULL)) == NULL) {
return 0;
}
if ((kctx = EVP_KDF_CTX_new(kdf)) == NULL) {
EVP_KDF_free(kdf);
return 0;
}
//
// Set parameters for KBKDF
// ---------------------------------------------------------
*p++ = OSSL_PARAM_construct_utf8_string(
OSSL_KDF_PARAM_MODE, "COUNTER", 0);
*p++ = OSSL_PARAM_construct_utf8_string(
OSSL_KDF_PARAM_MAC, "HMAC", 0);
*p++ = OSSL_PARAM_construct_utf8_string(
OSSL_KDF_PARAM_DIGEST, "SHA256", 0);
*p++ = OSSL_PARAM_construct_octet_string(
OSSL_KDF_PARAM_KEY, Kin, strlen(Kin));
*p++ = OSSL_PARAM_construct_octet_string(
OSSL_KDF_PARAM_SALT, "UDPSTP", 6);
var = snprintf(context, sizeof(context), "%u", authUnixTime);
*p++ = OSSL_PARAM_construct_octet_string(
OSSL_KDF_PARAM_INFO, context, var);
//
// Confirm the following are enabled
//
var = 1;
*p++ = OSSL_PARAM_construct_int(OSSL_KDF_PARAM_KBKDF_USE_L, &var);
*p++ = OSSL_PARAM_construct_int(
OSSL_KDF_PARAM_KBKDF_USE_SEPARATOR, &var);
//
// Set counter length in bits (available as of OpenSSL 3.1)
//
var = 32; // Length of 32 is backward compatible with OpenSSL 3.0
*p++ = OSSL_PARAM_construct_int(OSSL_KDF_PARAM_KBKDF_R, &var);
*p++ = OSSL_PARAM_construct_end();
// ---------------------------------------------------------
//
// Derive key material
//
if (EVP_KDF_derive(kctx, keybuf, keylen, params) < 1) {
EVP_KDF_CTX_free(kctx);
EVP_KDF_free(kdf);
return 0;
}
//
// Output individual keys
//
keyptr = keybuf;
memcpy(cAuthKey, keyptr, SHA256_KEY_LEN);
keyptr += SHA256_KEY_LEN;
memcpy(sAuthKey, keyptr, SHA256_KEY_LEN);
//
// Cleanup
//
EVP_KDF_CTX_free(kctx);
EVP_KDF_free(kdf);
return 1;
}
<CODE ENDS>
图 12: KDF 示例代码片段