Zum Hauptinhalt springen

8. C Code for SHAs, HMAC, and HKDF (C-Code für SHA, HMAC und HKDF)

Im Folgenden finden Sie eine Demonstrationsimplementierung dieser sicheren Hash-Funktionen in C. Abschnitt 8.1 enthält die Header-Datei sha.h, die alle Konstanten, Strukturen und Funktionen deklariert, die von den SHA- und HMAC-Funktionen verwendet werden. Sie enthält Bedingungen basierend auf dem Definitionszustand von USE_32BIT_ONLY, die, wenn dieses Symbol zur Kompilierungszeit definiert ist, 64-Bit-Operationen vermeiden. Sie enthält auch sha-private.h, das einige Deklarationen bereitstellt, die allen SHA-Funktionen gemeinsam sind. Abschnitt 8.2 enthält den C-Code für sha1.c, sha224-256.c, sha384-512.c und usha.c. Abschnitt 8.3 enthält den C-Code für die HMAC-Funktionen, und Abschnitt 8.4 enthält den C-Code für HKDF. Abschnitt 8.5 enthält einen Testtreiber zum Testen des Codes.

API-Übersicht (API Overview)

Für jede der Digest-Längen $$$ gibt es den folgenden Satz von Konstanten, eine Struktur und Funktionen:

Konstanten (Constants):

  • SHA$$$HashSize - Anzahl der Oktette im Hash
  • SHA$$$HashSizeBits - Anzahl der Bits im Hash
  • SHA$$$_Message_Block_Size - Anzahl der in den Zwischennachrichtenblöcken verwendeten Oktette

Die meisten Funktionen geben einen Aufzählungswert zurück, der einer der folgenden ist:

  • shaSuccess(0) - bei Erfolg
  • shaNull(1) - wenn ein Null-Zeiger-Parameter übergeben wird
  • shaInputTooLong(2) - wenn die Eingabedaten zu lang sind
  • shaStateError(3) - wenn SHA$$$Input nach SHA$$$FinalBits oder SHA$$$Result aufgerufen wird

Struktur (Structure):

typedef SHA$$$Context

Eine opake Struktur, die den vollständigen Zustand für die Erzeugung des Hashs enthält

Funktionen (Functions):

int SHA$$$Reset(SHA$$$Context *context);

Zurücksetzen des Hash-Kontextzustands.

int SHA$$$Input(SHA$$$Context *context, const uint8_t *octets,
unsigned int bytecount);

Einbeziehen von bytecount Oktetten in den Hash.

int SHA$$$FinalBits(SHA$$$Context *, const uint8_t octet,
unsigned int bitcount);

Einbeziehen von bitcount Bits in den Hash. Die Bits befinden sich im oberen Teil des Oktetts. SHA$$$Input() kann danach nicht mehr aufgerufen werden.

int SHA$$$Result(SHA$$$Context *,
uint8_t Message_Digest[SHA$$$HashSize]);

Durchführen der endgültigen Berechnungen für den Hash und Kopieren des Werts in Message_Digest.

USHA-Schnittstelle (USHA Interface)

Darüber hinaus werden Funktionen mit dem Präfix USHA bereitgestellt, die einen SHAversion-Wert (SHA$$$) annehmen, um die SHA-Funktionssuite auszuwählen. Sie fügen die folgenden Konstanten, Struktur und Funktionen hinzu:

Konstanten (Constants):

  • shaBadParam(4) - Konstante, die von USHA-Funktionen zurückgegeben wird, wenn ein ungültiger SHAversion-Parameter (SHA$$$) oder andere illegale Parameterwerte übergeben werden
  • USAMaxHashSize - Maximum der SHA-Hash-Größen
  • SHA$$$ - SHAversion-Aufzählungswerte, die von USHA-, HMAC- und HKDF-Funktionen verwendet werden, um die SHA-Funktionssuite auszuwählen

Struktur (Structure):

typedef USHAContext

Eine opake Struktur, die den vollständigen Zustand für die Erzeugung des Hashs enthält

Funktionen (Functions):

int USHAReset(USHAContext *context, SHAversion whichSha);

Zurücksetzen des Hash-Kontextzustands.

int USHAInput(USHAContext context*,
const uint8_t *bytes, unsigned int bytecount);

Einbeziehen von bytecount Oktetten in den Hash.

int USHAFinalBits(USHAContext *context,
const uint8_t bits, unsigned int bitcount);

Einbeziehen von bitcount Bits in den Hash.

int USHAResult(USHAContext *context,
uint8_t Message_Digest[USHAMaxHashSize]);

Durchführen der endgültigen Berechnungen für den Hash und Kopieren des Werts in Message_Digest. Oktette in Message_Digest jenseits von USHAHashSize(whichSha) bleiben unberührt.

int USHAHashSize(enum SHAversion whichSha);

Die Anzahl der Oktette im gegebenen Hash.

int USHAHashSizeBits(enum SHAversion whichSha);

Die Anzahl der Bits im gegebenen Hash.

int USHABlockSize(enum SHAversion whichSha);

Die interne Blockgröße für den gegebenen Hash.

const char *USHAHashName(enum SHAversion whichSha);

Diese Funktion gibt den Namen des gegebenen SHA-Algorithmus als Zeichenkette zurück.

HMAC-Schnittstelle (HMAC Interface)

Die HMAC-Funktionen folgen dem gleichen Muster, um die Verwendung jeder Textlänge zu ermöglichen.

Struktur (Structure):

typedef HMACContext

Eine opake Struktur, die den vollständigen Zustand für die Erzeugung des schlüsselbasierten Nachrichtendigests (MAC) enthält

Funktionen (Functions):

int hmacReset(HMACContext *ctx, enum SHAversion whichSha,
const unsigned char *key, int key_len);

Zurücksetzen des MAC-Kontextzustands.

int hmacInput(HMACContext *ctx, const unsigned char *text,
int text_len);

Einbeziehen von text_len Oktetten in den MAC.

int hmacFinalBits(HMACContext *ctx, const uint8_t bits,
unsigned int bitcount);

Einbeziehen von bitcount Bits in den MAC.

int hmacResult(HMACContext *ctx,
uint8_t Message_Digest[USHAMaxHashSize]);

Durchführen der endgültigen Berechnungen für den MAC und Kopieren des Werts in Message_Digest.

Darüber hinaus werden kombinierte Schnittstellen bereitgestellt, ähnlich denen in [RFC2104], die die Verwendung einer Texteingabe fester Länge ermöglichen:

int hmac(SHAversion whichSha,
const unsigned char *text, int text_len,
const unsigned char *key, int key_len,
uint8_t digest[USHAMaxHashSize])

Diese kombinierte Schnittstelle führt die vollständige HMAC-Berechnung durch. Die Variablen sind die gleichen wie in den obigen separaten Aufrufen.

HKDF-Schnittstelle (HKDF Interface)

Die HKDF-Funktionen sind ähnlich wie die HMAC-Funktionen strukturiert.

Struktur (Structure):

typedef HKDFContext

Eine opake Struktur, die den vollständigen Zustand für die Durchführung der HKDF-Extrahier-und-Erweitern-Schlüsselableitung enthält

Funktionen (Functions):

int hkdfReset(HKDFContext *context, enum SHAversion whichSha,
const unsigned char *salt, int salt_len);

Zurücksetzen des HKDF-Kontextzustands.

int hkdfInput(HKDFContext *context, const unsigned char *ikm,
int ikm_len);

Einbeziehen von ikm_len Oktetten in den Entropie-Extraktor.

int hkdfFinalBits(HKDFContext *context, uint8_t ikm_bits,
unsigned int ikm_bit_count)

Einbeziehen von ikm_bit_count Bits in den Entropie-Extraktor.

int hkdfResult(HKDFContext *context,
uint8_t prk[USHAMaxHashSize],
const unsigned char *info, int info_len,
uint8_t okm[ ], int okm_len)

Abschließen der HKDF-Extraktion und Durchführen der endgültigen HKDF-Erweiterung, wobei die okm_len Oktette im Ausgabeschlüsselmaterial (okm) gespeichert werden. Optional den intern generierten Pseudozufallsschlüssel (prk) speichern.

Darüber hinaus werden kombinierte Schnittstellen bereitgestellt, ähnlich denen in [RFC5869], die die Verwendung einer Texteingabe fester Länge ermöglichen:

int hkdfExtract(SHAversion whichSha,
const unsigned char *salt, int salt_len,
const unsigned char *ikm, int ikm_len,
uint8_t prk[USHAMaxHashSize])

Durchführen der HKDF-Extraktion, Kombinieren der salt_len Oktette des optionalen Salzes mit den ikm_len Oktetten des Eingabeschlüsselmaterials (ikm), um den Pseudozufallsschlüssel prk zu bilden. Die Ausgabe prk muss groß genug sein, um die Oktette zu halten, die für den gegebenen Hash-Typ geeignet sind.

int hkdfExpand(SHAversion whichSha,
const uint8_t prk[ ], int prk_len,
const unsigned char *info, int info_len,
uint8_t okm[ ], int okm_len)

Durchführen der HKDF-Erweiterung, Kombinieren der prk_len Oktette des Pseudozufallsschlüssels prk mit den info_len Oktetten von info, um die okm_len Oktette zu bilden, die in okm gespeichert werden.

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)

Diese kombinierte Schnittstelle führt sowohl HKDF-Extraktion als auch -Erweiterung durch. Die Variablen sind die gleichen wie in hkdfExtract() und hkdfExpand().

Unterabschnitte (Subsections)