Secure Hash Algorithmen

Page Shortcuts

Geschichte

Die Secure Hash Algorithmen ist eine Gruppe von vier Hashing-Algorithmen, welche vom National Institute of Standards and Technology (NIST) veröffentlicht wurden.

Der erste Algorithmus der SHA-Gruppe ist der im Jahre 1993 veröffentlichte, damals genannte, SHA-Algorithmus. Der Algorithmus wurde schnell wieder zurückgezogen, da ein signifikanter Fehler darin entdeckt wurde.

Der neuste SHA3-Algorithmus gewann im Oktober 2012 einen von NIST organisierten Wettbewerb. Damals war er als Keccak-Algorithmus bekannt.

Gebrauch

Die neueren, sicheren Algorithmen der SHA-Gruppe werden oft gebraucht, um Passwörter zu hashen und so auf Servern abzuspeichern.

Der SHA-256-Algorithmus wird beim Generieren von digitalen Signaturen für HTTPS-Certificates benutzt.

Bei der Cryptocurrency Ethereum wird mit dem SHA3-Algorithmus die Adresse eines Users generiert.

Funktionsweise

  Hier wird die Funktion des SHA3- (bzw. Keccak-) Algorithmus erläutert.

  Bitwise XOR wird als ^ geschrieben und ein Bitwise AND als &.

Das Hashen

Um eine Nachricht S zu hashen, wird sie zuerst zu einem Binarystring konvertiert. Zu diesem Binarystring wird dann der für den SHA-3 charakteristischen Suffix [0, 1] angehängt.

Der Binarystring wird dann in Chunks geteilt, dessen Länge der Rate entspricht (2 × die Outputlänge).

Diese Chunks werden dann Gepaddet und zu States konvertiert.

Auf jeden State A wird dann das Five-Step-Mapping angewendet.

Ab dem zweiten State wird er jeweils vor dem Five-Step-Mapping mit dem vorherig modifizierten State ge-XOR-t.

Nachdem alle States modifiziert wurden und somit die Nachricht gehasht, wird der State zurück zu einem Binarystring konvertiert und dessen erste Outputlänge Bits werden schlussendlich zu einem Little-Endian-Hexstring konvertiert und als Hashvalue der Nachricht zurückgegeben.

Variablen

Hier werden die wichtigsten Variablen des SHA3-Algorithmus aufgelistet.

  • A: Der State.
  • b: Die Breite der Keccak-Permutation, bei SHA3 1600.
  • w: Die Lane-Size, bzw. b / 25.
  • l: Der Logarithmus Basis 2 von w, bei SHA3 6.
  • nr: Wie viele Male das Five-Step-Mapping auf einen State angewendet wird, 12 + 2 × l, bei SHA3 24.
  • Outputlänge: Wie lange das Hashvalue in Bits sein soll, bei SHA3 entweder 224, 256, 384 oder 512.
  • Kapazität: Wie viele Bits einer Nachricht in einen State aufgenommen werden, 2 × die Outputlänge.
  • Rate: Wie viele Bits das Padding eines States ausmachen sollen, b - die Kapazität.

Padding

Beim SHA3-Algorithmus wird der Input mit dem pad10*1-Algorithmus gepaddet.

Beim pad10*1-Algorithmus wird zuerst ein Bit mit Wert 1 angehängt, danach so viele Bits mit Wert 0, dass die Länge des Inputs + 1 Modulo die Rate (b - 2 × die Outputlänge) Null entspricht und schlussendlich wird nochmals ein Bit mit Wert 1 angehängt.

Konvertierung von Strings zu State-Arrays

Die Konvertierung eines Strings S zu einem State-Array A läuft wie folgt ab:

  Für alle Triplets (x, y, z), so dass 0 ≤ x < 5, 0 ≤ y < 5 und 0 ≤ z < w, lass

    A[x, y, z] = S[w × (5 × y + x) + z].

Konvertierung von State-Arrays zu Strings

Die Konvertierung eines States A zu einem String S läuft wie folgt ab:

  Für die Konvertierung werden genestete For-Loops gebraucht, welche zuerst über alle z iterieren, dann x und schlussendlich y.

  Für alle Triplets (x, y, z), so dass 0 ≤ x < 5, 0 ≤ y < 5 und 0 ≤ z < w, lass

    S += A[x, y, z].

Five-Step-Mapping

Das Five-Step-Mapping modifiziert den State so, dass nach dem Mapping nicht mehr auf den originalen State zurückzuführen ist.

Pro State wird nr (12 + 2 × l, bzw beim SHA3-Algorithmus 24) mal das Five-Step-Mapping auf den State angewendet.

Die Funktion des Five-Step-Mappings sieht wie folgt aus:

iota(chi(pi(rho(theta(A)))), i)

Wobei A der State ist, welcher modifiziert wird und i der Index der momentanen Runde.

  1. θ (Theta)

    1. Für alle Paare (x, z), so dass 0 ≤ x < 5 und 0 ≤ z < w, lass
      1. C[x, z] = A[x, 0, z] ^ A[x, 1, z] ^ A[x, 2, z] ^ A[x, 3, z] ^ A[x, 4, z].
    2. Für alle Paare (x, z), so dass 0 ≤ x < 5 und 0 ≤ z < w, lass
      1. D[x, z] = C[(x - 1) mod 5, z] ^ C[(x + 1) mod 5, (z – 1) mod w].
    3. Für alle Triplets (x, y, z), so dass 0 ≤ x < 5, 0 ≤ y < 5 und 0 ≤ z < w, lass
      1. A'[x, y, z] = A[x, y, z] ^ D[x, z].
    4. Gib A' zurück.
  2. ρ (Rho)

    1. Für alle z, so dass 0 ≤ z < w, lass A'[0, 0, z] = A[0, 0, z].
    2. Lass (x, y) = (1, 0).
    3. Für t von 0 bis und mit 23
      1. Für alle z, so dass 0 ≤ z < w, lass A'[x, y, z] = A[x, y, (z – (t + 1)(t + 2) / 2) mod w].
      2. Lass (x, y) = (y, (2 × x + 3 × y) mod 5).
    4. Gib A' zurück.
  3. π (Pi)

    1. Für alle Triplets (x, y, z), so dass 0 ≤ x < 5, 0 ≤ y < 5 und 0 ≤ z < w, lass
      1. A'[x, y, z] = A[(x + 3 × y) mod 5, x, z].
    2. Gib A' zurück.
  4. χ (Chi)

    1. Für alle Triplets (x, y, z), so dass 0 ≤ x < 5, 0 ≤ y < 5 und 0 ≤ z < w, lass
      1. A'[x, y, z] = A[x, y, z] ^ ((A[x + 1 mod 5, y, z] ^ 1) & A[(x + 2) mod 5, y, z]).
    2. Gib A' zurück.
  5. RC (Round-Constant - Hilfsfunktion für ι (Iota))

    Diese Funktion nimmt, alles als die Anderen des Five-Step-Mapping, eine Zahl t entgegen (Anstatt einen State A) und gibt ein Bit zurück (Anstatt ein modifizierter State A').

    1. Falls t mod 255 == 0, gib 1 zurück.
    2. Lass R = [1, 0, 0, 0, 0, 0, 0, 0].
    3. Für alle i von 1 bis t mod 255, lass
      1. R = [0] + R
      2. R[0] = R[0] ^ R[8]
      3. R[4] = R[4] ^ R[8]
      4. R[5] = R[5] ^ R[8]
      5. R[6] = R[6] ^ R[8]
      6. R = R[0] bis R[8]
    4. Gib R[0] zurück.
  6. ι (Iota)

    1. Für alle Triplets (x, y, z), so dass 0 ≤ x < 5, 0 ≤ y < 5 und 0 ≤ z < w, lass
      1. A'[x, y, z] = A[x, y, z].
    2. Lass RC = 0w (Ein Array mit Länge w, gefüllt mit Nullen).
    3. Für alle j von 0 bis und mit l, lass RC[2j - 1] = rc(j + 7 × ir).
    4. Für alle z, so dass 0 ≤ z < w, lass A'[0, 0, z] = A'[0, 0, z] ^ RC[z].
    5. Gib A' zurück.

Beispielcode

Diese Beispielcodes zeigen mögliche Implementierungen des SHA3-Algorithmus.

Die Namen der Variablen sind meist identisch deren der Federal Information Processing Standards (NIST).

Dies ist ein in Python geschriebener Beispielcode:

# Nötiger Import from copy import deepcopy # Die meisten Variablen sind benannt nach den FEDERAL INFORMATION PROCESSING STANDARDS (NIST) (https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf) # A' wird als aA geschrieben # Konstanten für die Hash-Funktion b = 1600; w = 64; l = 6; nr = 12 + 2 * l # Die Länge des produzierten Hash-Values in Bits outputLength = 224 # oder: 256 / 384 / 512 # Diese Funktion nimmt einen String entgegen und gibt dessen Hash-Value zurück def hashSHA(message): # Die Bits des Parameters mit dem für den SHA3-Algorithmus charakteristischen Suffix [0, 1] inputBits = stringToBitArray(message) + [0, 1] # Der momentane State A = [] # Der Array inputBits wird in (b - 2 * outputLength) grosse Chunks geteilt und an den Array Chunks angehängt chunks = [] for i in range(len(inputBits) // (b - 2 * outputLength) + 1): chunks.append(inputBits[i * (b - 2 * outputLength):(i + 1) * (b - 2 * outputLength)]) # Über die Chunks wird iteriert for chunk in chunks: # Der Chunk wird zu einem State modifiziert aA = messageBitsToState(chunk) # Falls bereits über ein Chunk iteriert wurde, wird jedes Bit von aA ge-XOR-t mit dem Bit des momentanen States if len(A) != 0: for x in range(5): for y in range(5): for z in range(w): aA[x][y][z] ^= A[x][y][z] # Der momentane State ist nun der neue State A = aA # nr mal wird das five step mapping auf den neuen State angewendet for i in range(nr): A = keccakRound(A, i) # Der Hash-Value wird zurückgegeben return stateToLittleEndianHexString(A)[:outputLength // 4] # Dividiert durch vier, da ein Hex-String zurückgegeben wird # Diese Funktion gibt einen Little-Endian-Hex-String des States A zurück def stateToLittleEndianHexString(A): # Der State als Binary-String binString = stateToBinString(A) hexString = '' # Über jedes Byte wird iteriert for i in range(len(binString) // 8): # Das Byte wird zu einem Little-Endian-Hex-Value konvertiert byte = hex(int((binString[i * 8:(i + 1) * 8])[::-1], 2))[2:] # Das Byte wird gepaddet, damit es zwei Characters lang ist byte = (2 - len(byte)) * '0' + byte # Das Byte wird zum hexString hinzugefügt hexString += byte return hexString # Diese Funktion konvertiert einen State zu einem Binary-String def stateToBinString(A): # Der Algorithmus gemäss den FEDERAL INFORMATION PROCESSING STANDARDS binStr = '' for y in range(5): for x in range(5): binStr += ''.join(str(i) for i in A[x][y]) return binStr # Diese Funktion konvertiert die Bits einer Nachricht, mit maximaler Länge (b - 2 * outputLength), zu einem State def messageBitsToState(bitArray): # Der Input wird gepaddet aA = bitPadding(bitArray) # Der State A = [] # Der Algorithmus gemäss den FEDERAL INFORMATION PROCESSING STANDARDS for x in range(5): yArr = [] for y in range(5): zArr = [] for z in range(w): zArr.append(aA[w * (5 * y + x) + z]) yArr.append(zArr) A.append(yArr) # Der neue State wird zurückgegeben return A # Diese Funktion konvertiert einen String zu einem Binary-Array def stringToBitArray(string): # Der Binary-Array arr = [] # Über jeden Character des Strings wird iteriert for char in string: # Der Character als Little-Endian-Binary-String byte = (bin(ord(char))[2:])[::-1] # Das Byte wird gepaddet while len(byte) < 8: byte += '0' # Zum Array wird jedes Bit des Bytes angehängt arr += [int(bit) for bit in byte] return arr # Diese Funktion gibt den Array zurück, nachdem die pad10*1 Funktion darauf angewendet wurde def bitPadding(arr): # Die Kapazität des Algorithmus capacity = 2 * outputLength # Die Rate des Algorithmus rate = b - capacity # Falls der Array schon rate Bits lange ist, muss die Rate nicht gepaddet werden if len(arr) != rate: # Zum Array wird ein Bit mit Wert 1 angehängt, danach so viele Bits mit Wert 0, bis die Länge des Arrays der Rate entspricht # danach wird nochmals ein Bit mit Wert 1angehängt zeros = (-len(arr) - 2) % rate arr.append(1) arr += zeros * [0] arr.append(1) # Der Array wird mit Bits mit Wert 0 gefüllt, bis dessen Länge b entspricht while len(arr) % b != 0: arr.append(0) return arr # Gibt den State zurück, nachdem das five step mapping darauf angewendet wurde keccakRound = lambda A, i: iota(chi(pi(rho(theta(A)))), i) # Die erste Funktion des five step mappings def theta(A): C = [] for x in range(5): CArr = [] for z in range(w): num = 0 for y in range(5): num ^= A[x][y][z] CArr.append(num) C.append(CArr) D = [] for x in range(5): zArr = [] for z in range(w): zArr.append(C[(((x - 1) % 5) + 5) % 5][z] ^ C[(x + 1) % 5][(((z - 1) % w) + w) % w]) D.append(zArr) aA = A for x in range(5): for y in range(5): for z in range(w): aA[x][y][z] = A[x][y][z] ^ D[x][z] return aA # Die zweite Funktion des five step mappings def rho(A): aA = deepcopy(A) x = 1; y = 0 for t in range(24): for z in range(w): aA[x][y][(z + (t + 1) * (t + 2) // 2) % w] = A[x][y][z] x, y = y, (2 * x + 3 * y) % 5 return aA # Die dritte Funktion des five step mappings def pi(A): aA = deepcopy(A) for x in range(5): for y in range(5): for z in range(w): aA[x][y][z] = A[(x + 3 * y) % 5][x][z] return aA # Die vierte Funktion des five step mappings def chi(A): aA = deepcopy(A) for x in range(5): for y in range(5): for z in range(w): aA[x][y][z] ^= (A[(x + 1) % 5][y][z] ^ 1) & A[(x + 2) % 5][y][z] return aA # Die fünfte Funktion des five step mappings def iota(A, i): RC = w * [0] for j in range(l + 1): RC[2 ** j - 1] = roundConstant(j + 7 * i) for z in range(w): A[0][0][z] ^= RC[z] return A # Diese Funktion gibt eine Konstante zurück, welche von der Rundennummer abhängt. Wird von der Funktion iota gerufen def roundConstant(t): if t % 255 == 0: return 1 R = [1, 0, 0, 0, 0, 0, 0, 0] for i in range(t % 255): R = [0] + R R[0] ^= R[8] R[4] ^= R[8] R[5] ^= R[8] R[6] ^= R[8] R = R[:-1] return R[0]

Es werden Booleans gebraucht, um die Bits darzustellen, um den nötigen Speicherplatz zu minimieren. True ist ein Bit mit Wert 1, während False ein Bit mit Wert 0 ist.

Dies ist ein in Java geschriebener Beispielcode:

// Nötige Imports import java.util.Arrays; import java.lang.Math; . . . // Die meisten Variablen sind benannt nach den FEDERAL INFORMATION PROCESSING STANDARDS (NIST) (https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf) // A' wird als aA geschrieben // Konstanten für die Hash-Funktion public static final int b = 1600, w = 64, l = 6, nr = 12 + 2 * l; // Die Länge des produzierten Hash-Values in Bits public static final int outputLength = 224; // oder : 256 / 384 / 512 // Diese Funktion nimmt einen String entgegen und gibt dessen Hash-Value zurück public static String hashSHA(String message) { // Kreierung des Arrays inputBits, die message als Bits mit dem für den SHA3-Algorithmus charakteristischen Suffix [0, 1] boolean[] messageBits = stringToBitArray(message); boolean[] inputBits = new boolean[messageBits.length + 2]; System.arraycopy(messageBits, 0, inputBits, 0, messageBits.length); System.arraycopy(new boolean[] {false, true}, 0, inputBits, messageBits.length, 2); // Der momentane State boolean[][][] A = new boolean[5][5][w]; // Der Array inputBits wird in (b - 2 * outputLength) grosse Chunks geteilt und zum Array Chunks angehängt String[] chunks = new String[inputBits.length / (b - 2 * outputLength) + 1]; for (int i = 0; i < inputBits.length / (b - 2 * outputLength) + 1; i++) { // Der i-te Teil des Arrays inputBits mit Länge (b - 2 * outputLength) wird in chunks[i] kopiert chunks[i] = ""; int strLength = (inputBits.length - i * (b - 2 * outputLength)) % (b - 2 * outputLength); for (int j = 0; j < b - 2 * outputLength && i * (b - 2 * outputLength) + j < inputBits.length; j++) chunks[i] += inputBits[i * (b - 2 * outputLength) + j] ? '1' : '0'; } // Iteriere über die Chunks for (String chunk : chunks) { // Der Chunks wird zu einem State modifiziert boolean[][][] aA = messageBitsToState(chunk); // Jedes bit von aA wird ge-XOR-t mit dem Bit des momentanen States for (int x = 0; x < 5; x++) { for (int y = 0; y < 5; y++) { for (int z = 0; z < w; z++) aA[x][y][z] ^= A[x][y][z]; } } // Der momentane State ist nun der neue State A = aA; // nr mal wird das five step mapping auf den neuen State angewendet for (int i = 0; i < nr; i++) A = keccakRound(A, i); } // Der Hash-Value wird zurückgegeben return stateToLittleEndianHexString(A).substring(0, outputLength / 4); } // Diese Funktion gibt einen Little-Endian-Hex-String des States A zurück public static String stateToLittleEndianHexString(boolean[][][] A) { // Der State als Binary-String String binString = stateToBinString(A); String hexString = ""; // Über jedes Byte wird iteriert for (int i = 0; i < binString.length() / 8; i++) { // Das byte wird zu einem Little-Endian-Hex-Value konvertiert String curByte = binString.substring(i * 8, (i + 1) * 8); // Der curByte wird reversed, bzw. zu Little-Endian konvertiert String reversedByte = ""; for (int j = 7; j >= 0; j--) reversedByte += curByte.charAt(j); curByte = reversedByte; // Konvertiere den Binary String zu einem Hex String curByte = Integer.toHexString(Integer.parseInt(curByte, 2)); // Das Byte wird gepaddet, damit es zwei Characters lang ist curByte = "0".repeat(2 - curByte.length()) + curByte; // Das Byte wird zum HexString hinzugefügt hexString += curByte; } return hexString; } // Diese Funktion konvertiert einen State zu einem Binary-String public static String stateToBinString(boolean[][][] A) { // Der Algorithmus gemäss den FEDERAL INFORMATION PROCESSING STANDARDS String binStr = ""; for (int y = 0; y < 5; y++) { for (int x = 0; x < 5; x++) { for (int z = 0; z < w; z++) { binStr += Integer.toBinaryString(A[x][y][z] ? 1 : 0); } } } return binStr; } // Diese Funktion konvertiert die Bits einer Nachricht, mit maximaler Länge (b - 2 * outputLength), zu einem State public static boolean[][][] messageBitsToState(String bitString) { boolean[] bitArray = new boolean[bitString.length()]; for (int i = 0; i < bitArray.length; i++) bitArray[i] = bitString.charAt(i) == '1'; // Der Input wird gepaddet boolean[] aA = bitPadding(bitArray); // Der State boolean[][][] A = new boolean[5][5][w]; // Der Algorithmus gemäss den FEDERAL INFORMATION PROCESSING STANDARDS for (int x = 0; x < 5; x++) { for (int y = 0; y < 5; y++) { for (int z = 0; z < w; z++) A[x][y][z] = aA[w * (5 * y + x) + z]; } } // Der neue State wird zurückgegeben return A; } // Diese Funktion konvertiert einen String zu einem Binary-Array public static boolean[] stringToBitArray(String str) { // Der Binary-Array boolean[] arr = new boolean[str.length() * 8]; int index = 0; // Über jeden Character des Strings wird iteriert for (int i = 0; i < str.length(); i++) { // Der Character als Binary-String String binStr = Integer.toBinaryString((int)str.charAt(i)); // Der Character wird zu Little-Endian konvertiert String reversedbinStr = ""; for (int j = binStr.length() - 1; j >= 0; j--) reversedbinStr += binStr.charAt(j); binStr = reversedbinStr; // Das Byte wird gepaddet while (binStr.length() < 8) binStr += "0"; // Zum Array arr wird jedes Bit des Bytes appendet for (int j = 0; j < binStr.length(); j++, index++) arr[index] = binStr.charAt(j) == '1'; } return arr; } // Diese Funktion gibt den Array zurück, nachdem die pad10*1 Funktion darauf angewendet wurde public static boolean[] bitPadding(boolean[] arr) { // Der gepaddete Array, welcher am Schluss zurückgegeben wird boolean[] paddedArr = new boolean[b]; System.arraycopy(arr, 0, paddedArr, 0, arr.length); // Die Kapazität des Algorithmus int capacity = 2 * outputLength; // Die Rate des Algorithmus int rate = b - capacity; // Falls der Array schon rate Bits lange ist, muss die Rate nicht gepaddet werden if (arr.length != rate) { // Zum Array wird ein Bit mit Wert 1 angehängt, danach so viele Bits mit Wert 0, bis die Länge des Arrays der Rate entspricht // danach wird nochmals ein Bit mit Wert 1 angehängt int zeros = (-arr.length - 2) % rate; paddedArr[arr.length] = true; for (int i = arr.length + 2; i < b - 1; i++) paddedArr[i] = false; paddedArr[rate - 1] = true; } for (int i = rate; i < b; i++) paddedArr[i] = false; return paddedArr; } // Gibt den State zurück, nachdem das five step mapping darauf angewendet wurde public static boolean[][][] keccakRound(boolean[][][] A, int i) { return iota(chi(pi(rho(theta(A)))), i); } // Die erste Funktion des five step mappings public static boolean[][][] theta(boolean[][][] A) { boolean[][] C = new boolean[5][w]; for (int x = 0; x < 5; x++) { for (int z = 0; z < w; z++) { // Der momentane Bit, welcher bei C[x][z] eingefügt wird boolean currBit = false; for (int i = 0; i < 5; i++) currBit ^= A[x][i][z]; C[x][z] = currBit; } } boolean[][] D = new boolean[5][w]; for (int x = 0; x < 5; x++) { for (int z = 0; z < w; z++) { D[x][z] = C[(((x - 1) % 5) + 5) % 5][z] ^ C[(x + 1) % 5][((z - 1) % w + w) % w]; } } boolean[][][] aA = new boolean[5][5][w]; for (int x = 0; x < 5; x++) { for (int y = 0; y < 5; y++) { for (int z = 0; z < w; z++) aA[x][y][z] = A[x][y][z] ^ D[x][z]; } } return aA; } // Die zweite Funktion des five step mappings public static boolean[][][] rho(boolean[][][] A) { boolean[][][] aA = new boolean[5][5][w]; for (int z = 0; z < w; z++) aA[0][0][z] = A[0][0][z]; int x = 1, y = 0, xTemp; for (int t = 0; t < 24; t++) { for (int z = 0; z < w; z++) aA[x][y][(z + (t + 1) * (t + 2) / 2) % w] = A[x][y][z]; xTemp = x; x = y; y = (2 * xTemp + 3 * y) % 5; } return aA; } // Die dritte Funktion des five step mappings public static boolean[][][] pi(boolean[][][] A) { boolean[][][] aA = new boolean[5][5][w]; for (int x = 0; x < 5; x++) { for (int y = 0; y < 5; y++) { for (int z = 0; z < w; z++) aA[x][y][z] = A[(x + 3 * y) % 5][x][z]; } } return aA; } // Die vierte Funktion des five step mappings public static boolean[][][] chi(boolean[][][] A) { boolean[][][] aA = new boolean[5][5][w]; for (int x = 0; x < 5; x++) { for (int y = 0; y < 5; y++) { for (int z = 0; z < w; z++) aA[x][y][z] = A[x][y][z] ^ (A[(x + 1) % 5][y][z] ^ true) & A[(x + 2) % 5][y][z]; } } return aA; } // Die fünfte Funktion des five step mappings public static boolean[][][] iota(boolean[][][] A, int i) { // Automatisch ausgefüllt mit false (Bits von Wert 0) boolean[] RC = new boolean[w]; for (int j = 0; j <= l; j++) RC[(int)Math.pow(2, j) - 1] = roundConstant(j + 7 * i); for (int z = 0; z < w; z++) A[0][0][z] ^= RC[z]; return A; } // Diese Funktion gibt eine Konstante zurück, welche von der Rundennummer abhängt. Wird von der Funktion iota gerufen public static boolean roundConstant(int t) { if (t % 255 == 0) return true; // R verkörpert ein Byte mit Startwert 10000000 boolean[] R = {true, false, false, false, false, false, false, false}; for (int i = 0; i < t % 255; i++) { // Das Bit, welches verloren geht nach dem Verschieben des Arrays boolean lostBit = R[7]; // Shifte jeden Wert von R um eins nach rechts for (int j = 6; j >= 0; j--) R[j + 1] = R[j]; R[0] = false; R[0] ^= lostBit; R[4] ^= lostBit; R[5] ^= lostBit; R[6] ^= lostBit; } return R[0]; }

Input-Hasher

Deine mit dem SHA3--Algorithmus gehashte Nachricht: