From ef794a2308a648b4f4005551d2dc53c3b7a3a531 Mon Sep 17 00:00:00 2001
From: dd86k
Date: Mon, 18 Dec 2023 13:47:49 -0500
Subject: [PATCH] Update doc, prep work for #9
---
source/sha3d.d | 95 ++++++++++++++++++++++++++------------------------
1 file changed, 50 insertions(+), 45 deletions(-)
diff --git a/source/sha3d.d b/source/sha3d.d
index ec06dcb..dece7a1 100644
--- a/source/sha3d.d
+++ b/source/sha3d.d
@@ -30,12 +30,12 @@ version (SHA3D_Trace)
/// Params:
/// digestSize = Digest size in bits.
/// shake = SHAKE XOF digest size in bits. Defaults to 0 for SHA-3.
-/// sponge = Sponge size in bits, must be a multiple of 25. Defaults to 1600.
+/// width = (b parameter) WIdth size in bits, must be a multiple of 25 up to 1600. Defaults to 1600.
/// rounds = Number of rounds for transformation function. Defaults to 24.
///
/// Throws: No exceptions are thrown.
public struct KECCAK(uint digestSize,
- uint shake = 0, uint sponge = 1600, size_t rounds = 24)
+ uint shake = 0, uint width = 1600, size_t rounds = 24)
{
version (SHA3D_Trace) {}
else
@@ -43,9 +43,11 @@ public struct KECCAK(uint digestSize,
@safe: @nogc: nothrow: pure:
}
- static assert(sponge <= 1600, "Sponge can't be over 1600 bits.");
- static assert(sponge % 25 == 0, "Sponge must be a power of 25.");
- static assert(rounds <= 24, "Rounds can't be over 24.");
+ static assert(width % 25 == 0, "Width must be a power of 25.");
+ static assert(width <= 1600, "Width can't be over 1600 bits.");
+ static assert(width >= 200, "Widths under 200 bits is currently not supported.");
+ static assert(rounds <= 24, "Rounds can't be over 24.");
+ static assert(rounds > 0, "Must have one or more rounds.");
static if (shake)
{
@@ -86,7 +88,9 @@ public struct KECCAK(uint digestSize,
];
/// Digest size in bits.
- enum blockSize = (sponge - digestSize * 2); // Required for HMAC.
+ ///
+ /// This is not the size of the held state.
+ enum blockSize = (width - digestSize * 2); // Required for HMAC.
// ...0: Reserved
// 01: SHA-3
@@ -94,18 +98,18 @@ public struct KECCAK(uint digestSize,
// 1111: SHAKE
private enum delim = shake ? 0x1f : 0x06; /// Delimiter suffix when finishing
private enum rate = blockSize / 8; /// Sponge rate in bytes
- private enum stateSize = 200; /// Constant for any derivatives
- private enum state64Size = stateSize / ulong.sizeof;
- private enum statezSize = stateSize / size_t.sizeof;
+ private enum state8Size = width / 8; /// Constant for any derivatives
+ private enum stateSize = state8Size / ulong.sizeof;
+ private enum statezSize = state8Size / size_t.sizeof;
union
{
- private size_t[statezSize] statez; // state (size_t)
- private ulong[state64Size] state64; // state (ulong)
- private ubyte[stateSize] state; // state (ubyte)
+ private size_t[statezSize] statez; // state (size_t)
+ private ulong[stateSize] state; // state
+ private ubyte[state8Size] state8; // state (ubyte)
}
- static assert(state64.sizeof == state.sizeof);
- static assert(statez.sizeof == state.sizeof);
+ static assert(state.sizeof == state8.sizeof);
+ static assert(statez.sizeof == state8.sizeof);
private ulong[5] bc; // Transformation data
private ulong t; // Transformation temporary
@@ -145,7 +149,7 @@ public struct KECCAK(uint digestSize,
// Process remainder bytewise.
foreach (const b; input)
{
- state.ptr[i++] ^= b;
+ state8.ptr[i++] ^= b;
if (i >= rate)
{
transform;
@@ -161,8 +165,9 @@ public struct KECCAK(uint digestSize,
/// Returns: Raw digest data.
ubyte[digestSizeBytes] finish()
{
- state[pt] ^= delim;
- state[rate - 1] ^= 0x80;
+ // Mark delimiter at end of sponge
+ state8[pt] ^= delim;
+ state8[rate - 1] ^= 0x80;
static if (shake)
{
@@ -177,15 +182,15 @@ public struct KECCAK(uint digestSize,
size_t end = i + rate;
if (end > digestSizeBytes)
{
- output[i..$] = state[0..digestSizeBytes - i];
+ output[i..$] = state8[0..digestSizeBytes - i];
break;
}
- output[i..end] = state[0..rate];
+ output[i..end] = state8[0..rate];
i += rate;
} while (true);
// Clear state of potential sensitive data.
- state64[] = 0;
+ state[] = 0;
bc[] = t = 0;
return output;
@@ -198,7 +203,7 @@ public struct KECCAK(uint digestSize,
// State sanitized only if digestSize is less than state
// of 1600 bits, so 200 Bytes.
static if (digestSizeBytes < stateSize)
- state[digestSizeBytes..$] = 0;
+ state8[digestSizeBytes..$] = 0;
bc[] = t = 0;
version (SHA3D_Trace)
@@ -209,7 +214,7 @@ public struct KECCAK(uint digestSize,
}
else
{
- return state[0..digestSizeBytes];
+ return state8[0..digestSizeBytes];
}
}
}
@@ -225,7 +230,7 @@ private:
// Theta
THETA1(0); THETA1(1); THETA1(2); THETA1(3); THETA1(4);
THETA2(0); THETA2(1); THETA2(2); THETA2(3); THETA2(4);
- t = state64[1];
+ t = state[1];
// Rho
RHO(0); RHO(1); RHO(2); RHO(3); RHO(4);
RHO(5); RHO(6); RHO(7); RHO(8); RHO(9);
@@ -235,13 +240,13 @@ private:
// Chi
CHI(0); CHI(5); CHI(10); CHI(15); CHI(20);
// Iota
- state64[0] ^= K_RC[round];
+ state[0] ^= K_RC[round];
version (SHA3D_Trace)
{
writefln("ROUND=%d", round);
int i;
- foreach (ulong s; state64)
+ foreach (ulong s; state)
if (i & 1)
writefln(" v[%2d]=%16x", i++, s);
else
@@ -256,44 +261,44 @@ private:
pragma(inline, true)
void THETA1(size_t i)
{
- bc[i] = state64[i] ^ state64[i + 5] ^ state64[i + 10] ^
- state64[i + 15] ^ state64[i + 20];
+ bc[i] = state[i] ^ state[i + 5] ^ state[i + 10] ^
+ state[i + 15] ^ state[i + 20];
}
pragma(inline, true)
void THETA2(size_t i)
{
t = bc[(i + 4) % 5] ^ rol(bc[(i + 1) % 5], 1);
- state64[ i] ^= t;
- state64[ 5 + i] ^= t;
- state64[10 + i] ^= t;
- state64[15 + i] ^= t;
- state64[20 + i] ^= t;
+ state[ i] ^= t;
+ state[ 5 + i] ^= t;
+ state[10 + i] ^= t;
+ state[15 + i] ^= t;
+ state[20 + i] ^= t;
}
pragma(inline, true)
void RHO(size_t i)
{
size_t j = K_PI[i];
- bc[0] = state64[j];
- state64[j] = rol(t, K_RHO[i]);
+ bc[0] = state[j];
+ state[j] = rol(t, K_RHO[i]);
t = bc[0];
}
pragma(inline, true)
void CHI(size_t j)
{
- bc[0] = state64[j];
- bc[1] = state64[j + 1];
- bc[2] = state64[j + 2];
- bc[3] = state64[j + 3];
- bc[4] = state64[j + 4];
-
- state64[j] ^= (~bc[1]) & bc[2];
- state64[j + 1] ^= (~bc[2]) & bc[3];
- state64[j + 2] ^= (~bc[3]) & bc[4];
- state64[j + 3] ^= (~bc[4]) & bc[0];
- state64[j + 4] ^= (~bc[0]) & bc[1];
+ bc[0] = state[j];
+ bc[1] = state[j + 1];
+ bc[2] = state[j + 2];
+ bc[3] = state[j + 3];
+ bc[4] = state[j + 4];
+
+ state[j] ^= (~bc[1]) & bc[2];
+ state[j + 1] ^= (~bc[2]) & bc[3];
+ state[j + 2] ^= (~bc[3]) & bc[4];
+ state[j + 3] ^= (~bc[4]) & bc[0];
+ state[j + 4] ^= (~bc[0]) & bc[1];
}
version (BigEndian)