Skip to main content

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)