メインコンテンツまでスキップ

8. C Code for SHAs, HMAC, and HKDF (SHA、HMAC、HKDFのCコード)

以下は、これらのセキュアハッシュ関数のC言語での実装例です。セクション8.1には、SHA関数とHMAC関数で使用されるすべての定数、構造体、関数を宣言するヘッダーファイルsha.hが含まれています。これには、USE_32BIT_ONLYの定義状態に基づく条件付きコンパイルが含まれており、そのシンボルがコンパイル時に定義されている場合は64ビット演算を回避します。また、すべてのSHA関数に共通するいくつかの宣言を提供するsha-private.hも含まれています。セクション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) - nullポインタパラメータが渡された場合
  • 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) - 不正なSHAversion(SHA$$$)パラメータまたはその他の不正なパラメータ値が渡された場合にUSHA関数が返す定数
  • 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にコピーします。USHAHashSize(whichSha)を超えるMessage_Digest内のオクテットは変更されません。

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の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)