8. C Code for SHAs, HMAC, and HKDF (SHA、HMAC和HKDF的C代码)
以下是这些安全哈希函数在C语言中的示范实现. 第8.1节包含头文件sha.h,该文件声明了SHA和HMAC函数使用的所有常量、结构和函数. 它包含基于USE_32BIT_ONLY定义状态的条件编译指令,如果在编译时定义了该符号,则避免64位操作. 它还包含sha-private.h,提供了所有SHA函数共用的一些声明. 第8.2节包含sha1.c、sha224-256.c、sha384-512.c和usha.c的C代码. 第8.3节包含HMAC函数的C代码,第8.4节包含HKDF的C代码. 第8.5节包含用于测试代码的测试驱动程序.
API概述 (API Overview)
对于每个摘要长度$$$,都有以下常量集、结构和函数:
常量 (Constants):
SHA$$$HashSize- 哈希中的八位字节数SHA$$$HashSizeBits- 哈希中的位数SHA$$$_Message_Block_Size- 中间消息块中使用的八位字节数
大多数函数返回以下枚举值之一:
shaSuccess(0)- 成功shaNull(1)- 当传入空指针参数时shaInputTooLong(2)- 当输入数据过长时shaStateError(3)- 当在SHA$$$FinalBits或SHA$$$Result之后调用SHA$$$Input时
结构 (Structure):
typedef SHA$$$Context
一个不透明结构,保存用于生成哈希的完整状态
函数 (Functions):
int SHA$$$Reset(SHA$$$Context *context);
重置哈希上下文状态.
int SHA$$$Input(SHA$$$Context *context, const uint8_t *octets,
unsigned int bytecount);
将bytecount个八位字节合并到哈希中.
int SHA$$$FinalBits(SHA$$$Context *, const uint8_t octet,
unsigned int bitcount);
将bitcount位合并到哈希中. 这些位位于八位字节的高位部分. 此后不能再调用SHA$$$Input().
int SHA$$$Result(SHA$$$Context *,
uint8_t Message_Digest[SHA$$$HashSize]);
对哈希执行最终计算并将值复制到Message_Digest中.
USHA接口 (USHA Interface)
此外,还提供了带有USHA前缀的函数,这些函数采用SHAversion值(SHA$$$)来选择SHA函数套件. 它们添加了以下常量、结构和函数:
常量 (Constants):
shaBadParam(4)- 当USHA函数接收到错误的SHAversion(SHA$$$)参数或其他非法参数值时返回的常量USAMaxHashSize- SHA哈希大小的最大值SHA$$$- SHAversion枚举值,由USHA、HMAC和HKDF函数使用以选择SHA函数套件
结构 (Structure):
typedef USHAContext
一个不透明结构,保存用于生成哈希的完整状态
函数 (Functions):
int USHAReset(USHAContext *context, SHAversion whichSha);
重置哈希上下文状态.
int USHAInput(USHAContext context*,
const uint8_t *bytes, unsigned int bytecount);
将bytecount个八位字节合并到哈希中.
int USHAFinalBits(USHAContext *context,
const uint8_t bits, unsigned int bitcount);
将bitcount位合并到哈希中.
int USHAResult(USHAContext *context,
uint8_t Message_Digest[USHAMaxHashSize]);
对哈希执行最终计算并将值复制到Message_Digest中. Message_Digest中超出USHAHashSize(whichSha)的八位字节保持不变.
int USHAHashSize(enum SHAversion whichSha);
给定哈希中的八位字节数.
int USHAHashSizeBits(enum SHAversion whichSha);
给定哈希中的位数.
int USHABlockSize(enum SHAversion whichSha);
给定哈希的内部块大小.
const char *USHAHashName(enum SHAversion whichSha);
此函数将以字符串形式返回给定SHA算法的名称.
HMAC接口 (HMAC Interface)
HMAC函数遵循相同的模式,允许使用任意长度的文本输入.
结构 (Structure):
typedef HMACContext
一个不透明结构,保存用于生成密钥消息摘要(MAC)的完整状态
函数 (Functions):
int hmacReset(HMACContext *ctx, enum SHAversion whichSha,
const unsigned char *key, int key_len);
重置MAC上下文状态.
int hmacInput(HMACContext *ctx, const unsigned char *text,
int text_len);
将text_len个八位字节合并到MAC中.
int hmacFinalBits(HMACContext *ctx, const uint8_t bits,
unsigned int bitcount);
将bitcount位合并到MAC中.
int hmacResult(HMACContext *ctx,
uint8_t Message_Digest[USHAMaxHashSize]);
对MAC执行最终计算并将值复制到Message_Digest中.
此外,还提供了类似于[RFC2104]中所示的组合接口,允许使用固定长度的文本输入:
int hmac(SHAversion whichSha,
const unsigned char *text, int text_len,
const unsigned char *key, int key_len,
uint8_t digest[USHAMaxHashSize])
此组合接口执行完整的HMAC计算. 变量与上述单独调用中的相同.
HKDF接口 (HKDF Interface)
HKDF函数与HMAC函数的模式相似.
结构 (Structure):
typedef HKDFContext
一个不透明结构,保存用于执行HKDF提取-扩展密钥派生的完整状态
函数 (Functions):
int hkdfReset(HKDFContext *context, enum SHAversion whichSha,
const unsigned char *salt, int salt_len);
重置HKDF上下文状态.
int hkdfInput(HKDFContext *context, const unsigned char *ikm,
int ikm_len);
将ikm_len个八位字节合并到熵提取器中.
int hkdfFinalBits(HKDFContext *context, uint8_t ikm_bits,
unsigned int ikm_bit_count)
将ikm_bit_count位合并到熵提取器中.
int hkdfResult(HKDFContext *context,
uint8_t prk[USHAMaxHashSize],
const unsigned char *info, int info_len,
uint8_t okm[ ], int okm_len)
完成HKDF提取并执行最终的HKDF扩展,将okm_len个八位字节存储到输出密钥材料(okm)中. 可选择存储内部生成的伪随机密钥(prk).
此外,还提供了类似于[RFC5869]中所示的组合接口,允许使用固定长度的文本输入:
int hkdfExtract(SHAversion whichSha,
const unsigned char *salt, int salt_len,
const unsigned char *ikm, int ikm_len,
uint8_t prk[USHAMaxHashSize])
执行HKDF提取,将可选盐的salt_len个八位字节与输入密钥材料(ikm)的ikm_len个八位字节组合以形成伪随机密钥prk. 输出prk必须足够大以容纳适用于给定哈希类型的八位字节.
int hkdfExpand(SHAversion whichSha,
const uint8_t prk[ ], int prk_len,
const unsigned char *info, int info_len,
uint8_t okm[ ], int okm_len)
执行HKDF扩展,将伪随机密钥prk的prk_len个八位字节与info的info_len个八位字节组合,形成存储在okm中的okm_len个八位字节.
int hkdf(SHAversion whichSha,
const unsigned char *salt, int salt_len,
const unsigned char *ikm, int ikm_len,
const unsigned char *info, int info_len,
uint8_t okm[ ], int okm_len)
此组合接口同时执行HKDF提取和扩展. 变量与hkdfExtract()和hkdfExpand()中的相同.
子章节 (Subsections)
- 8.1. The Header Files (头文件)
- 8.1.1. sha.h
- 8.1.2. stdint-example.h
- 8.1.3. sha-private.h
- 8.2. The SHA Code (SHA代码)
- 8.2.1. sha1.c
- 8.2.2. sha224-256.c
- 8.2.3. sha384-512.c
- 8.2.4. usha.c
- 8.3. The HMAC Code (HMAC代码)
- 8.4. The HKDF Code (HKDF代码)
- 8.5. The Test Driver (测试驱动程序)