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 HashSHA$$$HashSizeBits- Anzahl der Bits im HashSHA$$$_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 ErfolgshaNull(1)- wenn ein Null-Zeiger-Parameter übergeben wirdshaInputTooLong(2)- wenn die Eingabedaten zu lang sindshaStateError(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 werdenUSAMaxHashSize- Maximum der SHA-Hash-GrößenSHA$$$- 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)
- 8.1. The Header Files (Header-Dateien)
- 8.1.1. sha.h
- 8.1.2. stdint-example.h
- 8.1.3. sha-private.h
- 8.2. The SHA Code (SHA-Code)
- 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-Code)
- 8.4. The HKDF Code (HKDF-Code)
- 8.5. The Test Driver (Testtreiber)