5. Hashing auf ein endliches Feld
Die Funktion hash_to_field hasht einen Byte-String msg beliebiger Länge auf ein oder mehrere Elemente eines Feldes F. Diese Funktion arbeitet in zwei Schritten: Sie hasht zunächst den Eingabe-Byte-String, um einen gleichmäßig zufälligen Byte-String zu erzeugen, und interpretiert dann diesen Byte-String als ein oder mehrere Elemente von F.
Für den ersten Schritt ruft hash_to_field eine Hilfsfunktion expand_message auf. Dieses Dokument definiert zwei Varianten von expand_message: eine geeignet für Hash-Funktionen wie SHA-2 [FIPS180-4] oder SHA-3 [FIPS202], und eine andere geeignet für erweiterbare Ausgabefunktionen wie SHAKE128 [FIPS202]. Sicherheitsüberlegungen für jede expand_message-Variante werden unten diskutiert (Abschnitte 5.3.1 und 5.3.2).
Implementierer DÜRFEN NICHT Rejection-Sampling verwenden, um ein gleichmäßig zufälliges Element von F zu erzeugen, um sicherzustellen, dass die hash_to_field-Funktion für eine Implementierung in konstanter Zeit geeignet ist. Der Grund dafür ist, dass Rejection-Sampling-Verfahren schwierig in konstanter Zeit zu implementieren sind, und spätere gut gemeinte "Optimierungen" eine Implementierung stillschweigend nicht-konstant-zeitig machen können. Dies bedeutet, dass jede auf Rejection-Sampling basierende hash_to_field-Funktion mit einer Implementierung in konstanter Zeit inkompatibel wäre.
Die hash_to_field-Funktion eignet sich auch zum sicheren Hashing auf Skalare. Zum Beispiel genügt es beim Hashing auf das Skalarfeld für eine elliptische Kurven-(Unter-)Gruppe mit Primzahlordnung r, hash_to_field mit dem Zielfeld GF(r) zu instanziieren.
Die hash_to_field-Funktion ist so konzipiert, dass sie von einem Zufallsorakel [MRH04] ununterscheidbar ist, wenn expand_message (Abschnitt 5.3) als Zufallsorakel modelliert wird (siehe Abschnitt 10.5 für Details zur Ununterscheidbarkeit). Die Gewährleistung der Ununterscheidbarkeit erfordert Sorgfalt; um zu verstehen warum, betrachten Sie eine Primzahl p, die nahe bei 3/4 * 2^256 liegt. Die Reduktion einer zufälligen 256-Bit-Ganzzahl modulo diesem p ergibt einen Wert, der mit einer Wahrscheinlichkeit von etwa 1/2 im Bereich [0, p / 3] liegt, was bedeutet, dass dieser Wert statistisch weit von gleichmäßig in [0, p - 1] entfernt ist.
Um Verzerrungen zu kontrollieren, verwendet hash_to_field stattdessen zufällige Ganzzahlen, deren Länge mindestens ceil(log2(p)) + k Bits beträgt, wobei k das Zielsicherheitsniveau für die Suite in Bits ist. Die Reduktion solcher Ganzzahlen mod p ergibt eine Verzerrung von höchstens 2^-k für jedes p; diese Verzerrung ist angemessen, wenn k-Bit-Sicherheit angestrebt wird. Für jede solche Ganzzahl verwendet hash_to_field expand_message, um L gleichmäßige Bytes zu erhalten, wobei:
L = ceil((ceil(log2(p)) + k) / 8)
Diese gleichmäßigen Bytes werden dann über OS2IP als Ganzzahl interpretiert. Zum Beispiel für eine 255-Bit-Primzahl p und k = 128-Bit-Sicherheit, L = ceil((255 + 128) / 8) = 48 Bytes.
Beachten Sie, dass k eine obere Grenze für das Sicherheitsniveau der entsprechenden Kurve ist. Siehe Abschnitt 10.8 für weitere Details und Abschnitt 8.9 für Richtlinien zur Wahl von k für eine gegebene Kurve.
5.1. Effizienzüberlegungen in Erweiterungsfeldern
Die in diesem Abschnitt beschriebene hash_to_field-Funktion ist für bestimmte Erweiterungsfelder ineffizient. Insbesondere beim Hashing auf ein Element des Erweiterungsfeldes GF(p^m) erfordert hash_to_field die Erweiterung von msg auf m * L Bytes (für L wie oben definiert). Für Erweiterungsfelder, bei denen log2(p) deutlich kleiner als das Sicherheitsniveau k ist, ist dieser Ansatz ineffizient: Er erfordert, dass expand_message etwa m * log2(p) + m * k Bits ausgibt, während m * log2(p) + k Bytes ausreichen, um ein Element von GF(p^m) mit einer Verzerrung von höchstens 2^-k zu erzeugen. In solchen Fällen KÖNNEN Anwendungen eine alternative hash_to_field-Funktion verwenden, vorausgesetzt, sie erfüllt die folgenden Sicherheitsanforderungen:
-
Die Funktion MUSS ein oder mehrere Feldelemente ausgeben, die gleichmäßig zufällig sind, mit Ausnahme einer Verzerrung von höchstens 2^-k.
-
Die Funktion DARF NICHT Rejection-Sampling verwenden.
-
Die Funktion SOLLTE für Straight-Line-Implementierungen geeignet sein.
Zum Beispiel beschreibt Pornin [P20] eine Methode zum Hashing auf GF(9767^19), die diese Anforderungen erfüllt und dabei weniger Ausgabebits von expand_message verwendet als hash_to_field für dieses Feld verwenden würde.
5.2. hash_to_field-Implementierung
Das folgende Verfahren implementiert hash_to_field.
Der expand_message-Parameter für diese Funktion MUSS den in Abschnitt 5.3 angegebenen Anforderungen entsprechen. Abschnitt 3.1 behandelt die ERFORDERLICHE Methode zur Konstruktion von DST, dem Domänentrennungs-Tag. Beachten Sie, dass hash_to_field fehlschlagen kann (ABORT), wenn expand_message fehlschlägt.
hash_to_field(msg, count)
Parameter:
- DST, ein Domänentrennungs-Tag (siehe Abschnitt 3.1).
- F, ein endliches Feld der Charakteristik p und Ordnung q = p^m.
- p, die Charakteristik von F (siehe unmittelbar oben).
- m, der Erweiterungsgrad von F, m >= 1 (siehe unmittelbar oben).
- L = ceil((ceil(log2(p)) + k) / 8), wobei k der Sicherheitsparameter der Suite ist (z. B. k = 128).
- expand_message, eine Funktion, die einen Byte-String und ein Domänentrennungs-Tag auf einen gleichmäßig zufälligen Byte-String erweitert (siehe Abschnitt 5.3).
Eingabe:
- msg, ein Byte-String, der die zu hashende Nachricht enthält.
- count, die Anzahl der zu erzeugenden Elemente von F.
Ausgabe:
- (u_0, ..., u_(count - 1)), eine Liste von Feldelementen.
Schritte:
- len_in_bytes = count * m * L
- uniform_bytes = expand_message(msg, DST, len_in_bytes)
- für i in (0, ..., count - 1):
- für j in (0, ..., m - 1):
-
elm_offset = L * (j + i * m) -
tv = substr(uniform_bytes, elm_offset, L) -
e_j = OS2IP(tv) mod p - u_i = (e_0, ..., e_(m - 1))
- return (u_0, ..., u_(count - 1))
5.3. expand_message
expand_message ist eine Funktion, die einen gleichmäßig zufälligen Byte-String erzeugt. Sie nimmt drei Argumente:
-
msg, ein Byte-String, der die zu hashende Nachricht enthält,
-
DST, ein Byte-String, der als Domänentrennungs-Tag fungiert, und
-
len_in_bytes, die Anzahl der zu erzeugenden Bytes.
Dieses Dokument definiert die folgenden zwei Varianten von expand_message:
-
expand_message_xmd (Abschnitt 5.3.1) ist geeignet für die Verwendung mit einer breiten Palette von Hash-Funktionen, einschließlich SHA-2 [FIPS180-4], SHA-3 [FIPS202], BLAKE2 [RFC7693] und anderen.
-
expand_message_xof (Abschnitt 5.3.2) ist geeignet für die Verwendung mit erweiterbaren Ausgabefunktionen (XOFs), einschließlich Funktionen aus den SHAKE [FIPS202]- oder BLAKE2X [BLAKE2X]-Familien.
Diese Varianten sollten für die überwiegende Mehrheit der Anwendungsfälle ausreichen, aber andere Varianten sind möglich; Abschnitt 5.3.4 behandelt die Anforderungen.
5.3.1. expand_message_xmd
Die Funktion expand_message_xmd erzeugt einen gleichmäßig zufälligen Byte-String unter Verwendung einer kryptografischen Hash-Funktion H, die b Bits ausgibt. Für die Sicherheit MUSS H die folgenden Anforderungen erfüllen:
-
Die Anzahl der von H ausgegebenen Bits MUSS b >= 2 * k sein, wobei k das Zielsicherheitsniveau in Bits ist, und b MUSS durch 8 teilbar sein. Die erste Anforderung gewährleistet k-Bit-Kollisionsresistenz; die zweite gewährleistet die Gleichmäßigkeit der Ausgabe von expand_message_xmd.
-
H KANN eine Merkle-Damgaard-Hash-Funktion wie SHA-2 sein. In diesem Fall gilt die Sicherheit, wenn die zugrunde liegende Kompressionsfunktion als Zufallsorakel modelliert wird [CDMP05]. (Siehe Abschnitt 10.6 zur Diskussion.)
-
H KANN eine schwammbasierte Hash-Funktion wie SHA-3 oder BLAKE2 sein. In diesem Fall gilt die Sicherheit, wenn die innere Funktion als zufällige Transformation oder als zufällige Permutation modelliert wird [BDPV08].
-
Andernfalls MUSS H eine Hash-Funktion sein, die nachweislich von einem Zufallsorakel [MRH04] unter einer vernünftigen kryptografischen Annahme ununterscheidbar ist.
SHA-2 [FIPS180-4] und SHA-3 [FIPS202] sind typische und EMPFOHLENE Wahlen. Als Beispiel wäre für das 128-Bit-Sicherheitsniveau b >= 256 Bits und entweder SHA-256 oder SHA3-256 eine geeignete Wahl.
Die Hash-Funktion H arbeitet, indem sie wiederholt Datenblöcke fester Länge aufnimmt. Die Länge dieser Blöcke in Bits wird als Eingabeblockgröße (s) bezeichnet. Als Beispiele: s = 1024 für SHA-512 [FIPS180-4] und s = 576 für SHA3-512 [FIPS202]. Für die Korrektheit erfordert H b <= s.
Das folgende Verfahren implementiert expand_message_xmd.
expand_message_xmd(msg, DST, len_in_bytes)
Parameter:
- H, eine Hash-Funktion (siehe Anforderungen oben).
- b_in_bytes, b / 8 für b die Ausgabegröße von H in Bits. Zum Beispiel für b = 256, b_in_bytes = 32.
- s_in_bytes, die Eingabeblockgröße von H, gemessen in Bytes (siehe Diskussion oben). Zum Beispiel für SHA-256, s_in_bytes = 64.
Eingabe:
- msg, ein Byte-String.
- DST, ein Byte-String von höchstens 255 Bytes. Siehe unten für Informationen zur Verwendung längerer DSTs.
- len_in_bytes, die Länge der angeforderten Ausgabe in Bytes, nicht größer als das Minimum von (255 * b_in_bytes) oder 2^16-1.
Ausgabe:
- uniform_bytes, ein Byte-String.
Schritte:
- ell = ceil(len_in_bytes / b_in_bytes)
- ABORT wenn ell > 255 oder len_in_bytes > 65535 oder len(DST) > 255
- DST_prime = DST || I2OSP(len(DST), 1)
- Z_pad = I2OSP(0, s_in_bytes)
- l_i_b_str = I2OSP(len_in_bytes, 2)
- msg_prime = Z_pad || msg || l_i_b_str || I2OSP(0, 1) || DST_prime
- b_0 = H(msg_prime)
- b_1 = H(b_0 || I2OSP(1, 1) || DST_prime)
- für i in (2, ..., ell):
- b_i = H(strxor(b_0, b_(i - 1)) || I2OSP(i, 1) || DST_prime)
- uniform_bytes = b_1 || ... || b_ell
- return substr(uniform_bytes, 0, len_in_bytes)
Beachten Sie, dass der String Z_pad (Schritt 6) msg vorangestellt wird, bevor b_0 berechnet wird (Schritt 7). Dies ist für die Sicherheit notwendig, wenn H ein Merkle-Damgaard-Hash ist, z. B. SHA-2 (siehe Abschnitt 10.6). Das Hashing dieser zusätzlichen Daten bedeutet, dass die Kosten für die Berechnung von b_0 höher sind als die Kosten für die einfache Berechnung von H(msg). In den meisten Fällen ist dieser Overhead vernachlässigbar, da die Kosten für die Auswertung von H viel geringer sind als die anderen Kosten, die beim Hashing auf eine Kurve anfallen.
Es ist jedoch möglich, diesen Overhead vollständig zu vermeiden, indem man die Tatsache ausnutzt, dass Z_pad nur von H abhängt und nicht von den Argumenten von expand_message_xmd. Dazu berechnen Sie zunächst den internen Zustand von H nach der Aufnahme von Z_pad vor und speichern ihn. Dann initialisieren Sie bei der Berechnung von b_0 H mit dem gespeicherten Zustand. Weitere Details sind implementierungsabhängig und liegen außerhalb des Umfangs dieses Dokuments.
5.3.2. expand_message_xof
Die Funktion expand_message_xof erzeugt einen gleichmäßig zufälligen Byte-String unter Verwendung einer erweiterbaren Ausgabefunktion (XOF) H. Für die Sicherheit MUSS H die folgenden Kriterien erfüllen:
-
Die Kollisionsresistenz von H MUSS mindestens k Bits betragen.
-
H MUSS eine XOF sein, die nachweislich von einem Zufallsorakel unter einer vernünftigen kryptografischen Annahme ununterscheidbar ist.
Die SHAKE-XOF-Familie [FIPS202] ist eine typische und EMPFOHLENE Wahl. Als Beispiel wäre für 128-Bit-Sicherheit SHAKE128 eine geeignete Wahl.
Das folgende Verfahren implementiert expand_message_xof.
expand_message_xof(msg, DST, len_in_bytes)
Parameter:
- H(m, d), eine erweiterbare Ausgabefunktion, die die Eingabenachricht m verarbeitet und d Bytes zurückgibt.
Eingabe:
- msg, ein Byte-String.
- DST, ein Byte-String von höchstens 255 Bytes. Siehe unten für Informationen zur Verwendung längerer DSTs.
- len_in_bytes, die Länge der angeforderten Ausgabe in Bytes.
Ausgabe:
- uniform_bytes, ein Byte-String.
Schritte:
- ABORT wenn len_in_bytes > 65535 oder len(DST) > 255
- DST_prime = DST || I2OSP(len(DST), 1)
- msg_prime = msg || I2OSP(len_in_bytes, 2) || DST_prime
- uniform_bytes = H(msg_prime, len_in_bytes)
- return uniform_bytes
5.3.3. Verwendung von DSTs länger als 255 Bytes
Die in diesem Abschnitt definierten expand_message-Varianten akzeptieren Domänentrennungs-Tags von höchstens 255 Bytes. Wenn Anwendungen ein Domänentrennungs-Tag von mehr als 255 Bytes benötigen, z. B. aufgrund von Anforderungen eines aufrufenden Protokolls, MÜSSEN Implementierer ein kurzes Domänentrennungs-Tag durch Hashing berechnen, wie folgt:
-
Für expand_message_xmd mit Hash-Funktion H wird DST wie folgt berechnet:
DST = H("H2C-OVERSIZE-DST-" || a_very_long_DST)
-
Für expand_message_xof mit erweiterbarer Ausgabefunktion H wird DST wie folgt berechnet:
DST = H("H2C-OVERSIZE-DST-" || a_very_long_DST, ceil(2 * k / 8))
Hier ist a_very_long_DST das DST, dessen Länge größer als 255 Bytes ist, "H2C-OVERSIZE-DST-" ist ein 17-Byte-ASCII-String-Literal, und k ist das Zielsicherheitsniveau in Bits.
5.3.4. Definition anderer expand_message-Varianten
Bei der Definition einer neuen expand_message-Variante ist die wichtigste Überlegung, dass hash_to_field expand_message als Zufallsorakel modelliert. Daher SOLLTEN Implementierer die Ununterscheidbarkeit von einem Zufallsorakel unter einer geeigneten Annahme über die zugrunde liegenden kryptografischen Primitive nachweisen; siehe Abschnitt 10.5 für weitere Informationen.
Darüber hinaus expand_message-Varianten:
-
MÜSSEN Kollisionsresistenz bieten, die dem Sicherheitsniveau der Ziel-elliptischen Kurve entspricht.
-
MÜSSEN auf Primitiven aufbauen, die für die Verwendung in Anwendungen entwickelt wurden, die kryptografische Zufälligkeit erfordern. Als Beispiele ist eine sichere Stream-Cipher eine geeignete Primitive, während ein Mersenne-Twister-Pseudozufallszahlengenerator [MT98] es nicht ist.
-
DÜRFEN NICHT Rejection-Sampling verwenden.
-
MÜSSEN unabhängige Werte für unterschiedliche (msg, DST, Länge)-Eingaben liefern. Diese Anforderung zu erfüllen ist subtil. Als vereinfachtes Beispiel funktioniert das Hashing von msg || DST nicht, da in diesem Fall unterschiedliche (msg, DST)-Paare, deren Verkettungen gleich sind, dieselbe Ausgabe zurückgeben (z. B. ("AB", "CDEF") und ("ABC", "DEF")). Die in diesem Dokument definierten Varianten verwenden eine suffix-freie Kodierung von DST, um dieses Problem zu vermeiden.
-
MÜSSEN das Domänentrennungs-Tag DST verwenden, um sicherzustellen, dass Aufrufe kryptografischer Primitive innerhalb von expand_message domänengetrennt von Aufrufen außerhalb von expand_message sind. Wenn beispielsweise die expand_message-Variante eine Hash-Funktion H verwendet, MUSS eine Kodierung von DST entweder als Präfix oder als Suffix der Eingabe für jeden Aufruf von H hinzugefügt werden. Das Hinzufügen von DST als Suffix ist der EMPFOHLENE Ansatz.
-
SOLLTEN msg genau einmal lesen, aus Effizienzgründen, wenn msg lang ist.
Darüber hinaus MUSS jede expand_message-Variante ein eindeutiges EXP_TAG angeben, das diese Variante in einer Suite-ID identifiziert. Siehe Abschnitt 8.10 für weitere Informationen.