aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias Andrée <maandree@operamail.com>2013-06-16 23:48:26 +0200
committerMattias Andrée <maandree@operamail.com>2013-06-16 23:48:26 +0200
commit42c0197d1858200b09d4e0523b44dc1e150cb2df (patch)
treed5f4215ca3716abde3b9f949dbb6053d6ed6bb80
parentm (diff)
downloadsha3sum-42c0197d1858200b09d4e0523b44dc1e150cb2df.tar.gz
sha3sum-42c0197d1858200b09d4e0523b44dc1e150cb2df.tar.bz2
sha3sum-42c0197d1858200b09d4e0523b44dc1e150cb2df.tar.xz
misc
Signed-off-by: Mattias Andrée <maandree@operamail.com>
-rw-r--r--c/sha3.c99
-rw-r--r--c/sha3.h32
-rw-r--r--c/sha3sum.c517
-rw-r--r--java-c-jni/SHA3.java97
l---------[-rw-r--r--]java-c-jni/sha3sum.java273
-rw-r--r--pure-java/SHA3.java4
-rw-r--r--pure-java/sha3sum.java118
-rwxr-xr-xpython3/sha3sum.py398
8 files changed, 1041 insertions, 497 deletions
diff --git a/c/sha3.c b/c/sha3.c
index 1dea0d9..ebaa59b 100644
--- a/c/sha3.c
+++ b/c/sha3.c
@@ -611,10 +611,12 @@ extern void update(byte* msg, long msglen)
/**
* Absorb the last part of the message and squeeze the Keccak sponge
*
- * @param msg The rest of the message, may be {@code null}
- * @param msglen The length of the partial message
+ * @param msg The rest of the message, may be {@code null}
+ * @param msglen The length of the partial message
+ * @param withReturn Whether to return the hash instead of just do a quick squeeze phrase and return {@code null}
+ * @return The hash sum, or {@code null} if <tt>withReturn</tt> is {@code false}
*/
-extern byte* digest(byte* msg, long msglen)
+extern byte* digest(byte* msg, long msglen, boolean withReturn)
{
byte* message;
byte* rc;
@@ -671,17 +673,98 @@ extern byte* digest(byte* msg, long msglen)
/* Squeezing phase */
olen = n;
- ni = min(25, rr);
+ if (withReturn)
+ {
+ ni = min(25, rr);
+ while (olen > 0)
+ {
+ i = 0;
+ while ((i < ni) && (j < nn))
+ {
+ llong v = S[(i % 5) * 5 + i / 5];
+ for (_ = 0; _ < ww; _++)
+ {
+ if (j < nn)
+ rc[ptr++] = (byte)v;
+ v >>= 8;
+ j += 1;
+ }
+ i += 1;
+ }
+ olen -= r;
+ if (olen > 0)
+ keccakF(S);
+ }
+ if ((n & 7))
+ rc[n >> 3] &= (1 << (n & 7)) - 1;
+
+ return rc;
+ }
+ while ((olen -= r) > 0)
+ keccakF(S);
+ return null;
+}
+
+
+/**
+ * Force some rounds of Keccak-f
+ *
+ * @param times The number of rounds
+ */
+extern void simpleSqueeze(long times)
+{
+ long i;
+ for (i = 0; i < times; i++)
+ keccakF(S);
+}
+
+
+/**
+ * Squeeze as much as is needed to get a digest a number of times
+ *
+ * @param times The number of digests
+ */
+extern void fastSqueeze(long times)
+{
+ long i, olen;
+ for (i = 0; i < times; i++)
+ {
+ keccakF(S); /* Last squeeze did not do a ending squeeze */
+ olen = n;
+ while ((olen -= r) > 0)
+ keccakF(S);
+ }
+}
+
+
+/**
+ * Squeeze out another digest
+ *
+ * @return The hash sum
+ */
+extern byte* squeeze()
+{
+ long nn, ww, olen, i, j, ptr, ni;
+ byte* rc;
+
+ keccakF(S); /* Last squeeze did not do a ending squeeze */
+
+ ww = w >> 3;
+ rc = (byte*)malloc(nn = (n + 7) >> 3);
+ olen = n;
+ j = ptr = 0;
+ ni = (25 < r >> 3) ? 25 : (r >> 3);
+
while (olen > 0)
{
i = 0;
while ((i < ni) && (j < nn))
{
- llong v = S[(i % 5) * 5 + i / 5];
+ long _, v = S[(i % 5) * 5 + i / 5];
for (_ = 0; _ < ww; _++)
{
if (j < nn)
- rc[ptr++] = (byte)v;
+ *(rc + ptr++) = (byte)v;
v >>= 8;
j += 1;
}
@@ -691,8 +774,8 @@ extern byte* digest(byte* msg, long msglen)
if (olen > 0)
keccakF(S);
}
- if ((n & 7))
- rc[n >> 3] &= (1 << (n & 7)) - 1;
+ if (n & 7)
+ rc[nn - 1] &= (1 << (n & 7)) - 1;
return rc;
}
diff --git a/c/sha3.h b/c/sha3.h
index faf94d1..fbcf346 100644
--- a/c/sha3.h
+++ b/c/sha3.h
@@ -48,8 +48,34 @@ extern void update(char* msg, long msglen);
/**
* Absorb the last part of the message and squeeze the Keccak sponge
*
- * @param msg The rest of the message, may be {@code null}
- * @param msglen The length of the partial message
+ * @param msg The rest of the message, may be {@code null}
+ * @param msglen The length of the partial message
+ * @param withReturn Whether to return the hash instead of just do a quick squeeze phrase and return {@code null}
+ * @return The hash sum, or {@code null} if <tt>withReturn</tt> is {@code false}
+ */
+extern char* digest(char* msg, long msglen, long withReturn);
+
+
+/**
+ * Force some rounds of Keccak-f
+ *
+ * @param times The number of rounds
+ */
+extern void simpleSqueeze(long times);
+
+
+/**
+ * Squeeze as much as is needed to get a digest a number of times
+ *
+ * @param times The number of digests
+ */
+extern void fastSqueeze(long times);
+
+
+/**
+ * Squeeze out another digest
+ *
+ * @return The hash sum
*/
-extern char* digest(char* msg, long msglen);
+extern char* squeeze();
diff --git a/c/sha3sum.c b/c/sha3sum.c
index b5d0c6a..d3657d7 100644
--- a/c/sha3sum.c
+++ b/c/sha3sum.c
@@ -26,10 +26,116 @@
#define true 1
#define null 0
+#define SET void**
+
#define HEXADECA "0123456789ABCDEF"
/**
+ * Prints a number of bytes to stdout
+ *
+ * @param bytes The bytes to print
+ * @param n The number of bytes
+ */
+inline void putchars(char* bytes, long n)
+{
+ fwrite(bytes, 1, n, stdout);
+}
+
+
+/**
+ * Creates a new set
+ *
+ * @return The set
+ */
+SET set_new()
+{
+ return (void**)malloc(sizeof(void*) << 4);
+}
+
+
+/**
+ * Frees a set
+ *
+ * @param set The set
+ */
+void set_free(SET set)
+{
+ if (*(set + 0)) set_free((void**)*(set + 0));
+ if (*(set + 1)) set_free((void**)*(set + 1));
+ if (*(set + 2)) set_free((void**)*(set + 2));
+ if (*(set + 3)) set_free((void**)*(set + 3));
+ if (*(set + 4)) set_free((void**)*(set + 4));
+ if (*(set + 5)) set_free((void**)*(set + 5));
+ if (*(set + 6)) set_free((void**)*(set + 6));
+ if (*(set + 7)) set_free((void**)*(set + 7));
+ if (*(set + 8)) set_free((void**)*(set + 8));
+ if (*(set + 9)) set_free((void**)*(set + 9));
+ if (*(set + 10)) set_free((void**)*(set + 10));
+ if (*(set + 11)) set_free((void**)*(set + 11));
+ if (*(set + 12)) set_free((void**)*(set + 12));
+ if (*(set + 13)) set_free((void**)*(set + 13));
+ if (*(set + 14)) set_free((void**)*(set + 14));
+ if (*(set + 15)) set_free((void**)*(set + 15));
+ free(set);
+}
+
+
+/**
+ * Adds an item to a set
+ *
+ * @param set The set
+ * @param item The item
+ * @param n The length of the item
+ */
+void set_add(SET set, char* item, long n)
+{
+ long i;
+ void** at = set;
+ for (i = 0; i < n; i++)
+ {
+ long a = (long)((*(item + i)) & 15), b = (long)((*(item + i) >> 4) & 15);
+ if (*(at + a))
+ at = (void**)*(at + a);
+ else
+ at = (void**)(*(at + a) = (void*)malloc(sizeof(void*) << 4));
+ if (*(at + b))
+ at = (void**)*(at + b);
+ else
+ at = (void**)(*(at + b) = (void*)malloc(sizeof(void*) << 4));
+ }
+}
+
+
+/**
+ * Checks if a set contains an item
+ *
+ * @param set The set
+ * @param item The item
+ * @param n The length of the item
+ * @return Whether the set contains the item
+ */
+long set_contains(SET set, char* item, long n)
+{
+ long i;
+ void** at = set;
+ for (i = 0; i < n; i++)
+ {
+ long a = (long)((*(item + i)) & 15), b = (long)((*(item + i) >> 4) & 15);
+ if (*(at + a))
+ at = (void**)*(at + a);
+ else
+ return false;
+ if (*(at + b))
+ at = (void**)*(at + b);
+ else
+ return false;
+ }
+ return true;
+}
+
+
+/**
* String equality comparator
*
* @param a First comparand
@@ -70,8 +176,11 @@ long parseInt(char* str)
int main(int argc, char** argv)
{
char* cmd = *argv;
- long _o, o, _s, s, _r, r, _c, c, _w, w, _i, i;
- long binary = false, dashed = false, fptr = 0, freelinger = true;
+
+ long _o, o, _s, s, _r, r, _c, c, _w, w, _i, i, _j, j;
+ long _O, O, _S, S, _R, R, _C, C, _W, W, _I, I, _J, J;
+ long binary = false, hex = false, dashed = false, freelinger = true;
+ long multi = 0, fptr = 0, bn;
char** files = (char**)malloc(argc * sizeof(char*));
char** linger = (char**)malloc(sizeof(char*) << 1);
@@ -79,6 +188,11 @@ int main(int argc, char** argv)
long a = 0, an = argc - 1;
char** args = argv + 1;
+
+ _O = _S = _R = _C = _W = _I = false;
+ O = S = R = C = W = I = J = 0;
+ o = s = r = c = w = i = j = 0;
+
*linger = 0;
@@ -89,25 +203,26 @@ int main(int argc, char** argv)
if (s >= 0)
cmd += s + 1;
- o = _o = 512; /* --outputsize */
+ _o = 512; /* --outputsize */
if ((cmd[0] == 's') && (cmd[1] == 'h') && (cmd[2] == 'a') && (cmd[3] == '3') && (cmd[4] == '-'))
if ((cmd[5] != 0) && (cmd[6] != 0) && (cmd[7] != 0))
if ((cmd[8] == 's') && (cmd[9] == 'u') && (cmd[10] == 'm') && (cmd[11] == 0))
{
if ((cmd[5] == '2') && (cmd[6] == '2') && (cmd[7] == '4'))
- o = _o = 224;
+ _o = 224;
else if ((cmd[5] == '2') && (cmd[6] == '5') && (cmd[7] == '6'))
- o = _o = 256;
+ _o = 256;
else if ((cmd[5] == '3') && (cmd[6] == '8') && (cmd[7] == '4'))
- o = _o = 384;
+ _o = 384;
else if ((cmd[5] == '5') && (cmd[6] == '1') && (cmd[7] == '2'))
- o = _o = 512;
+ _o = 512;
}
- s = _s = 1600; /* --statesize */
- r = _r = s - (o << 1); /* --bitrate */
- c = _c = s - r; /* --capacity */
- w = _w = s / 25; /* --wordsize */
- i = _i = 1; /* --iterations */
+ _s = 1600; /* --statesize */
+ _r = _s - (_o << 1); /* --bitrate */
+ _c = _s - _r; /* --capacity */
+ _w = _s / 25; /* --wordsize */
+ _i = 1; /* --iterations */
+ _j = 1; /* --squeezes */
for (; a <= an; a++)
@@ -143,8 +258,17 @@ int main(int argc, char** argv)
printf(" -i ITERATIONS\n");
printf(" --iterations The number of hash iterations to run. (default: %li)\n", _i);
printf(" \n");
+ printf(" -j SQUEEZES\n");
+ printf(" --squeezes The number of hash squeezes to run. (default: %li)\n", _j);
+ printf(" \n");
+ printf(" -h\n");
+ printf(" --hex Read the input in hexadecimal, rather than binary.\n");
+ printf(" \n");
printf(" -b\n");
printf(" --binary Print the checksum in binary, rather than hexadecimal.\n");
+ printf(" \n");
+ printf(" -m\n");
+ printf(" --multi Print the chechsum at all iterations.\n");
printf("\n");
printf("\n");
printf("COPYRIGHT:\n");
@@ -180,17 +304,19 @@ int main(int argc, char** argv)
arg = null;
}
if (eq(*linger, "-r") || eq(*linger, "--bitrate"))
- o = (s - (r = parseInt(linger[1]))) >> 1;
+ _R = 1 | (R = parseInt(linger[1]));
else if (eq(*linger, "-c") || eq(*linger, "--capacity"))
- r = s - (c = parseInt(linger[1]));
+ _C = 1 | (C = parseInt(linger[1]));
else if (eq(*linger, "-w") || eq(*linger, "--wordsize"))
- s = (w = parseInt(linger[1])) * 25;
+ _W = 1 | (W = parseInt(linger[1]));
else if (eq(*linger, "-o") || eq(*linger, "--outputsize"))
- r = s - ((o = parseInt(linger[1])) << 1);
+ _O = 1 | (O = parseInt(linger[1]));
else if (eq(*linger, "-s") || eq(*linger, "--statesize"))
- r = (s = parseInt(linger[1])) - (o << 1);
+ _S = 1 | (S = parseInt(linger[1]));
else if (eq(*linger, "-i") || eq(*linger, "--iterations"))
- i = parseInt(linger[1]);
+ _I = 1 | (I = parseInt(linger[1]));
+ else if (eq(*linger, "-j") || eq(*linger, "--squeezes"))
+ _J = 1 | (J = parseInt(linger[1]));
else
{
fprintf(stderr, "%s: unrecognised option: %s\n", cmd, *linger);
@@ -237,6 +363,10 @@ int main(int argc, char** argv)
else
if (eq(arg, "--binary"))
binary = true;
+ else if (eq(arg, "--multi"))
+ multi++;
+ else if (eq(arg, "--hex"))
+ hex = true;
else
{
linger[0] = arg;
@@ -252,6 +382,16 @@ int main(int argc, char** argv)
binary = true;
arg++;
}
+ else if (*arg == 'm')
+ {
+ multi++;
+ arg++;
+ }
+ else if (*arg == 'h')
+ {
+ hex = true;
+ arg++;
+ }
else
{
{
@@ -274,22 +414,151 @@ int main(int argc, char** argv)
free(linger);
+ i = _I ? I : _i;
+ j = _J ? J : _j;
+
+ #define ERR(text) fprintf(stderr, "%s: " text "\n", cmd); fflush(stdout); fflush(stderr)
+
+ if (_S)
+ {
+ s = S;
+ if ((s <= 0) || (s > 1600) || (s % 25))
+ {
+ ERR("the state size must be a positive multiple of 25 and is limited to 1600.");
+ return 6;
+ }
+ }
+
+ if (_W)
+ {
+ w = W;
+ if ((w <= 0) || (w > 64))
+ {
+ ERR("the word size must be positive and is limited to 64.");
+ return 6;
+ }
+ if (_S && (s != w * 25))
+ {
+ ERR("the state size must be 25 times of the word size.");
+ return 6;
+ }
+ else if (_S == null)
+ _S = 1 | (S = w * 25);
+ }
+
+ if (_C)
+ {
+ c = C;
+ if ((c <= 0) || (c & 7))
+ {
+ ERR("the capacity must be a positive multiple of 8.");
+ return 6;
+ }
+ }
+
+ if (_R)
+ {
+ r = R;
+ if ((r <= 0) || (r & 7))
+ {
+ ERR("the bitrate must be a positive multiple of 8.");
+ return 6;
+ }
+ }
+
+ if (_O)
+ {
+ o = o;
+ if (o <= 0)
+ {
+ ERR("the output size must be positive.");
+ return 6;
+ }
+ }
+
+ if ((_R & _C & _O) == null) /* s? */
+ {
+ s = _S ? s : _s;
+ r = -((c = (o = (((s << 5) / 100 + 7) >> 3) << 3) << 1) - s);
+ o = o < 8 ? 8 : o;
+ }
+ else if ((_R & _C) == null) /* !o s? */
+ {
+ r = _r;
+ c = _c;
+ s = _S ? s : (r + c);
+ }
+ else if (_R == null) /* !c o? s? */
+ {
+ r = (s = _S ? s : _s) - c;
+ o = _O ? o : (c == 8 ? 8 : (c << 1));
+ }
+ else if (_C == null) /* !r o? s? */
+ {
+ c = (s = _S ? s : _s) - r;
+ o = _O ? o : (c == 8 ? 8 : (c << 1));
+ }
+ else /* !r !c o? s? */
+ {
+ s = _S ? s : (r + c);
+ o = _O ? o : (c == 8 ? 8 : (c << 1));
+ }
+
+
+ if (r > s)
+ {
+ ERR("the bitrate must not be higher than the state size.");
+ return 6;
+ }
+ if (c > s)
+ {
+ ERR("the capacity must not be higher than the state size.");
+ return 6;
+ }
+ if (r + c != s)
+ {
+ ERR("the sum of the bitrate and the capacity must equal the state size.");
+ return 6;
+ }
+
+
+ fprintf(stderr, "Bitrate: %li", r);
+ fprintf(stderr, "Capacity: %li", c);
+ fprintf(stderr, "Word size: %li", w);
+ fprintf(stderr, "State size: %li", s);
+ fprintf(stderr, "Output Size: %li", o);
+ fprintf(stderr, "Iterations: %li", i);
+ fprintf(stderr, "Squeezes: %li", j);
+
+
if (fptr == 0)
files[fptr++] = null;
if (i < 1)
{
- fprintf(stderr, "%s: sorry, I will only do at least one iteration!\n", cmd);
- fflush(stdout);
- fflush(stderr);
+ ERR("sorry, I will only do at least one hash iteration!");
free(files);
return 3;
}
+ if (j < 1)
+ {
+ ERR("sorry, I will only do at least one squeeze iteration!");
+ free(files);
+ return 3;
+ }
+
+ #undef ERR
+ bn = (o + 7) >> 3;
{
- char* stdin = null;
+ char* stdin;
char* filename;
char* fn;
- long f, fail = false, _, bn;
+ long f, fail, _;
+
+ char* out = binary ? null : (char*)malloc(bn * 2);
+
+ fail = false;
+ stdin = null;
for (f = 0; f < fptr; f++)
{
@@ -311,80 +580,176 @@ int main(int argc, char** argv)
fail = true;
continue;
}
- initialise(r, c, o);
- blksize = 4096; /** XXX os.stat(os.path.realpath(fn)).st_size; **/
- chunk = (char*)malloc(blksize);
- for (;;)
+ if ((filename != null) || (stdin == null))
{
- long read = fread(chunk, 1, blksize, file);
- if (read <= 0)
- break;
- update(chunk, read);
- }
- free(chunk);
- bs = digest(null, 0);
- dispose();
- bn = (o + 7) >> 3;
- for (_ = 1; _ < i; _++)
- {
- char* _ = bs;
initialise(r, c, o);
- bs = digest(bs, bn);
- free(_);
+ blksize = 4096; /** XXX os.stat(os.path.realpath(fn)).st_size; **/
+ chunk = (char*)malloc(blksize);
+ for (;;)
+ {
+ long read = fread(chunk, 1, blksize, file);
+ if (read <= 0)
+ break;
+ if (hex == false)
+ update(chunk, read);
+ else
+ {
+ int n = read >> 1;
+ for (_ = 0; _ < n; _++)
+ {
+ char a = *(chunk + (_ << 1)), b = *(chunk + ((_ << 1) | 1));
+ a = (a & 15) + (a <= '9' ? 0 : 9);
+ b = (b & 15) + (b <= '9' ? 0 : 9);
+ *(chunk + _) = (a << 4) | b;
+ }
+ update(chunk, n);
+ }
+ }
+ free(chunk);
+ bs = digest(null, 0, j == 1);
+ if (j > 2)
+ fastSqueeze(j - 2);
+ if (j > 1)
+ bs = squeeze(1);
dispose();
- }
-
- if (binary)
- {
- long j;
- for (j = 0; j < bn; j++)
- putchar(*(bs + j));
+
if (filename == null)
{
- stdin = bs;
- bs = null;
+ stdin = (char*)malloc(bn * sizeof(char));
+ for (_ = 0; _ < bn; _++)
+ *(stdin + _) = *(bs + _);
}
- fflush(stdout);
- }
+ }
else
+ bs = stdin;
+
+ if (multi == 0)
{
- long flen = 0, rcptr = 0, b = 0;
- char* rc;
- if (filename != null)
- while (*(filename + flen))
- flen++;
- rc = malloc((bn << 1) + 3 + (filename == null ? 1 : 0) + flen);
- for (b = 0; b < bn; b++)
+ for (_ = 1; _ < i; _++)
{
- char v = bs[b];
- *(rc + rcptr++) = HEXADECA[(v >> 4) & 15];
- *(rc + rcptr++) = HEXADECA[v & 15];
+ char* _bs = bs;
+ initialise(r, c, o);
+ bs = digest(bs, bn, j == 1);
+ if (j > 2)
+ fastSqueeze(j - 2);
+ if (j > 1)
+ bs = squeeze();
+ free(_bs);
+ dispose();
}
- *(rc + rcptr++) = ' ';
- if (filename == null)
- *(rc + rcptr++) = '-';
+ if (binary)
+ putchars(bs, bn);
else
{
- flen = 0;
- while (*(filename + flen))
- *(rc + rcptr++) = *(filename + flen++);
+ long b, outptr = 0;
+ for (b = 0; b < bn; b++)
+ {
+ char v = bs[b];
+ *(out + outptr++) = HEXADECA[(v >> 4) & 15];
+ *(out + outptr++) = HEXADECA[v & 15];
+ }
+ printf("%s %s\n", out, filename ? filename : "-");
}
- *(rc + rcptr++) = '\n';
- *(rc + rcptr++) = 0;
- printf("%s", rc);
- fflush(stdout);
- if (filename == null)
- stdin = rc;
+ }
+ else if (multi == 1)
+ {
+ long b;
+ if (binary)
+ putchars(bs, bn);
else
- free(rc);
+ {
+ for (b = 0; b < bn; b++)
+ {
+ char v = bs[b];
+ out[b * 2 ] = HEXADECA[(v >> 4) & 15];
+ out[b * 2 + 1] = HEXADECA[v & 15];
+ }
+ printf("%s %s\n", out, filename ? filename : "-");
+ }
+ for (_ = 1; _ < i; _++)
+ {
+ char* _bs = bs;
+ initialise(r, c, o);
+ bs = digest(bs, bn, j == 1);
+ if (j > 2)
+ fastSqueeze(j - 2);
+ if (j > 1)
+ bs = squeeze();
+ free(_bs);
+ dispose();
+ if (binary)
+ putchars(bs, bn);
+ else
+ {
+ for (b = 0; b < bn; b++)
+ {
+ char v = bs[b];
+ out[b * 2 ] = HEXADECA[(v >> 4) & 15];
+ out[b * 2 + 1] = HEXADECA[v & 15];
+ }
+ printf("%s\n", out);
+ }
+ }
+ }
+ else
+ {
+ long b, loophere;
+ char* loop = null;
+ SET got = set_new();
+ for (_ = 0; _ < i; _++)
+ {
+ if (_ > 0)
+ {
+ char* _bs = bs;
+ initialise(r, c, o);
+ bs = digest(bs, bn, j == 1);
+ if (j > 2)
+ fastSqueeze(j - 2);
+ if (j > 1)
+ bs = squeeze();
+ free(_bs);
+ dispose();
+ }
+ for (b = 0; b < bn; b++)
+ {
+ char v = bs[b];
+ out[b * 2 ] = HEXADECA[(v >> 4) & 15];
+ out[b * 2 + 1] = HEXADECA[v & 15];
+ }
+ if (loop == null)
+ {
+ if (set_contains(got, bs, bn))
+ {
+ loop = (char*)malloc(bn * 2);
+ for (b = 0; b < bn * 2; b++)
+ *(loop + b) = *(out + b);
+ }
+ else
+ set_add(got, out, bn);
+ }
+ loophere = loop && eq(loop, out);
+ if (loophere)
+ printf("\033[31m");
+ putchars(out, bn * 2);
+ if (loophere)
+ printf("\033[00m");
+ fflush(stdout);
+ }
+ if (loop)
+ {
+ fprintf(stderr, "\033[01;31mLoop found\033[00m\n");
+ free(loop);
+ }
+ set_free(got);
}
-
if (bs != null)
free(bs);
fclose(file);
}
+ if (out != null)
+ free(out);
if (stdin != null)
free(stdin);
diff --git a/java-c-jni/SHA3.java b/java-c-jni/SHA3.java
index afcb942..05da74c 100644
--- a/java-c-jni/SHA3.java
+++ b/java-c-jni/SHA3.java
@@ -86,31 +86,116 @@ public class SHA3
/**
* Squeeze the Keccak sponge
+ *
+ * @return The hash sum
*/
public static byte[] digest()
{
- return digest(null);
+ return digest(null, 0, true);
+ }
+
+
+ /**
+ * Squeeze the Keccak sponge
+ *
+ * @paran withReturn Whether to return the hash instead of just do a quick squeeze phrase and return {@code null}
+ * @return The hash sum, or {@code null} if <tt>withReturn</tt> is {@code false}
+ */
+ public static byte[] digest(boolean withReturn)
+ {
+ return digest(null, 0, withReturn);
}
/**
* Absorb the last part of the message and squeeze the Keccak sponge
*
- * @param msg The rest of the message
+ * @param msg The rest of the message
+ * @return The hash sum
*/
public static byte[] digest(byte[] msg)
{
- return digest(msg, msg == null ? 0 : msg.length);
+ return digest(msg, msg == null ? 0 : msg.length, true);
}
/**
* Absorb the last part of the message and squeeze the Keccak sponge
*
- * @param msg The rest of the message
- * @param msglen The length of the partial message
+ * @param msg The rest of the message
+ * @paran withReturn Whether to return the hash instead of just do a quick squeeze phrase and return {@code null}
+ * @return The hash sum, or {@code null} if <tt>withReturn</tt> is {@code false}
+ */
+ public static byte[] digest(byte[] msg, boolean withReturn)
+ {
+ return digest(msg, msg == null ? 0 : msg.length, withReturn);
+ }
+
+
+ /**
+ * Absorb the last part of the message and squeeze the Keccak sponge
+ *
+ * @param msg The rest of the message
+ * @param msglen The length of the partial message
+ * @return The hash sum
+ */
+ public static byte[] digest(byte[] msg, int msglen)
+ {
+ return digest(msg, msg == null ? 0 : msg.length, true);
+ }
+
+
+ /**
+ * Absorb the last part of the message and squeeze the Keccak sponge
+ *
+ * @param msg The rest of the message
+ * @param msglen The length of the partial message
+ * @param withReturn Whether to return the hash instead of just do a quick squeeze phrase and return {@code null}
+ * @return The hash sum, or {@code null} if <tt>withReturn</tt> is {@code false}
+ */
+ public static native byte[] digest(byte[] msg, int msglen, boolean withReturn);
+
+
+ /**
+ * Force a round of Keccak-f
+ */
+ public static void simpleSqueeze()
+ {
+ simpleSqueeze(1);
+ }
+
+
+ /**
+ * Force some rounds of Keccak-f
+ *
+ * @param times The number of rounds
+ */
+ public static native void simpleSqueeze(int times);
+
+
+ /**
+ * Squeeze as much as is needed to get a digest
+ */
+ public static void fastSqueeze()
+ {
+ fastSqueeze(1);
+ }
+
+
+ /**
+ * Squeeze as much as is needed to get a digest a number of times
+ *
+ * @param times The number of digests
+ */
+ public static native void fastSqueeze(int times);
+
+
+ /**
+ * Squeeze out another digest
+ *
+ * @return The hash sum
*/
- public static native byte[] digest(byte[] msg, int msglen);
+ public static native byte[] squeeze();
}
diff --git a/java-c-jni/sha3sum.java b/java-c-jni/sha3sum.java
index 080c4b6..27a2d3e 100644..120000
--- a/java-c-jni/sha3sum.java
+++ b/java-c-jni/sha3sum.java
@@ -1,272 +1 @@
-/**
- * sha3sum – SHA-3 (Keccak) checksum calculator
- *
- * Copyright © 2013 Mattias Andrée (maandree@member.fsf.org)
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-import java.io.*;
-import java.util.*;
-
-
-/**
- * SHA-3/Keccak checksum calculator
- *
- * @author Mattias Andrée <a href="mailto:maandree@member.fsf.org">maandree@member.fsf.org</a>
- */
-public class sha3sum
-{
- /**
- * This is the main entry point of the program
- *
- * @param args Command line arguments
- * @throws IOException On I/O error (such as broken pipes)
- */
- public static void main(String[] args) throws IOException
- {
- run("sha3sum", args);
- }
-
-
- /**
- * Run the program
- *
- * @param cmd The command
- * @param argv Command line arguments
- * @throws IOException On I/O error (such as broken pipes)
- */
- public static void run(String cmd, String[] argv) throws IOException
- {
- if (cmd.indexOf('/') >= 0)
- cmd = cmd.substring(cmd.lastIndexOf('/') + 1);
- if (cmd.endsWith(".jar"))
- cmd = cmd.substring(0, cmd.length() - 4);
- cmd = cmd.intern();
-
- int _o, o = _o = 512; /* --outputsize */
- if (cmd == "sha3-224sum") o = _o = 224;
- else if (cmd == "sha3-256sum") o = _o = 256;
- else if (cmd == "sha3-384sum") o = _o = 384;
- else if (cmd == "sha3-512sum") o = _o = 512;
- int _s, s = _s = 1600; /* --statesize */
- int _r, r = _r = s - (o << 1); /* --bitrate */
- int _c, c = _c = s - r; /* --capacity */
- int _w, w = _w = s / 25; /* --wordsize */
- int _i, i = _i = 1; /* --iterations */
- boolean binary = false;
-
- String[] files = new String[argv.length + 1];
- int fptr = 0;
- boolean dashed = false;
- String[] linger = null;
-
- String[] args = new String[argv.length + 1];
- System.arraycopy(argv, 0, args, 0, argv.length);
- for (int a = 0, an = args.length; a < an; a++)
- { String arg = args[a];
- arg = arg == null ? null : arg.intern();
- if (linger != null)
- {
- linger[0] = linger[0].intern();
- if ((linger[0] == "-h") || (linger[0] == "--help"))
- {
- System.out.println("");
- System.out.println("SHA-3/Keccak checksum calculator");
- System.out.println("");
- System.out.println("USAGE: sha3sum [option...] < file");
- System.out.println(" sha3sum [option...] file...");
- System.out.println("");
- System.out.println("");
- System.out.println("OPTIONS:");
- System.out.println(" -r BITRATE");
- System.out.println(" --bitrate The bitrate to use for SHA-3. (default: " + _r + ")");
- System.out.println(" ");
- System.out.println(" -c CAPACITY");
- System.out.println(" --capacity The capacity to use for SHA-3. (default: " + _c + ")");
- System.out.println(" ");
- System.out.println(" -w WORDSIZE");
- System.out.println(" --wordsize The word size to use for SHA-3. (default: " + _w + ")");
- System.out.println(" ");
- System.out.println(" -o OUTPUTSIZE");
- System.out.println(" --outputsize The output size to use for SHA-3. (default: " + _o + ")");
- System.out.println(" ");
- System.out.println(" -s STATESIZE");
- System.out.println(" --statesize The state size to use for SHA-3. (default: " + _s + ")");
- System.out.println(" ");
- System.out.println(" -i ITERATIONS");
- System.out.println(" --iterations The number of hash iterations to run. (default: " + _i + ")");
- System.out.println(" ");
- System.out.println(" -b");
- System.out.println(" --binary Print the checksum in binary, rather than hexadecimal.");
- System.out.println("");
- System.out.println("");
- System.out.println("COPYRIGHT:");
- System.out.println("");
- System.out.println("Copyright © 2013 Mattias Andrée (maandree@member.fsf.org)");
- System.out.println("");
- System.out.println("This program is free software: you can redistribute it and/or modify");
- System.out.println("it under the terms of the GNU General Public License as published by");
- System.out.println("the Free Software Foundation, either version 3 of the License, or");
- System.out.println("(at your option) any later version.");
- System.out.println("");
- System.out.println("This program is distributed in the hope that it will be useful,");
- System.out.println("but WITHOUT ANY WARRANTY; without even the implied warranty of");
- System.out.println("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the");
- System.out.println("GNU General Public License for more details.");
- System.out.println("");
- System.out.println("You should have received a copy of the GNU General Public License");
- System.out.println("along with this program. If not, see <http://www.gnu.org/licenses/>.");
- System.out.println("");
- System.exit(2);
- }
- else
- {
- if (linger[1] == null)
- {
- linger[1] = arg;
- arg = null;
- }
- if ((linger[0] == "-r") || (linger[0] == "--bitrate"))
- o = (s - (r = Integer.parseInt(linger[1]))) >> 1;
- else if ((linger[0] == "-c") || (linger[0] == "--capacity"))
- r = s - (c = Integer.parseInt(linger[1]));
- else if ((linger[0] == "-w") || (linger[0] == "--wordsize"))
- s = (w = Integer.parseInt(linger[1])) * 25;
- else if ((linger[0] == "-o") || (linger[0] == "--outputsize"))
- r = s - ((o = Integer.parseInt(linger[1])) << 1);
- else if ((linger[0] == "-s") || (linger[0] == "--statesize"))
- r = (s = Integer.parseInt(linger[1])) - (o << 1);
- else if ((linger[0] == "-i") || (linger[0] == "--iterations"))
- i = Integer.parseInt(linger[1]);
- else
- {
- System.err.println(cmd + ": unrecognised option: " + linger[0]);
- System.exit(1);
- }
- }
- linger = null;
- if (arg == null)
- continue;
- }
- if (arg == null)
- continue;
- if (dashed)
- files[fptr++] = arg == "-" ? null : arg;
- else if (arg == "--")
- dashed = true;
- else if (arg == "-")
- files[fptr++] = null;
- else if (arg.startsWith("--"))
- if (arg.indexOf('=') >= 0)
- linger = new String[] { arg.substring(0, arg.indexOf('=')), arg.substring(arg.indexOf('=') + 1) };
- else
- if (arg == "--binary")
- binary = true;
- else
- linger = new String[] { arg, null };
- else if (arg.startsWith("-"))
- {
- arg = arg.substring(1);
- if (arg.charAt(0) == 'b')
- {
- binary = true;
- arg = arg.substring(1);
- }
- else if (arg.length() == 1)
- linger = new String[] { "-" + arg, null };
- else
- linger = new String[] { "-" + arg.charAt(0), arg.substring(1) };
- }
- else
- files[fptr++] = arg;
- }
-
- if (fptr == 0)
- files[fptr++] = null;
- if (i < 1)
- {
- System.err.println(cmd + ": sorry, I will only do at least one iteration!");
- System.exit(3);
- }
-
- byte[] stdin = null;
- boolean fail = false;
- String filename;
-
- for (int f = 0; f < fptr; f++)
- { if (((filename = files[f]) == null) && (stdin != null))
- { System.out.write(stdin);
- continue;
- }
- String rc = "";
- String fn = filename == null ? "/dev/stdin" : filename;
- InputStream file = null;
- try
- {
- file = new FileInputStream(fn);
- SHA3.initialise(r, c, o);
- int blksize = 4096; /** XXX os.stat(os.path.realpath(fn)).st_size; **/
- byte[] chunk = new byte[blksize];
- for (;;)
- {
- int read = file.read(chunk, 0, blksize);
- if (read <= 0)
- break;
- SHA3.update(chunk, read);
- }
- byte[] bs = SHA3.digest();
- for (int _ = 1; _ < i; _++)
- {
- SHA3.initialise(r, c, o);
- bs = SHA3.digest(bs);
- }
- if (binary)
- { if (filename == null)
- stdin = bs;
- System.out.write(bs);
- System.out.flush();
- }
- else
- { for (int b = 0, bn = bs.length; b < bn; b++)
- { rc += "0123456789ABCDEF".charAt((bs[b] >> 4) & 15);
- rc += "0123456789ABCDEF".charAt(bs[b] & 15);
- }
- rc += " " + (filename == null ? "-" : filename) + "\n";
- if (filename == null)
- stdin = rc.getBytes("UTF-8");
- System.out.print(rc);
- System.out.flush();
- }
- }
- catch (final IOException err)
- { System.err.println(cmd + ": cannot read file: " + filename + ": " + err);
- fail = true;
- }
- finally
- { if (file != null)
- try
- { file.close();
- }
- catch (final Throwable ignore)
- { //ignore
- } } }
-
- System.out.flush();
- if (fail)
- System.exit(5);
- }
-
-}
-
+../pure-java/sha3sum.java \ No newline at end of file
diff --git a/pure-java/SHA3.java b/pure-java/SHA3.java
index 084c8c1..5cacc5f 100644
--- a/pure-java/SHA3.java
+++ b/pure-java/SHA3.java
@@ -478,7 +478,7 @@ public class SHA3
/**
* Squeeze the Keccak sponge
*
- * @paran withReturn Whether to return the hash instead of just do a quick squeeze phrase and return {@code null}
+ * @param withReturn Whether to return the hash instead of just do a quick squeeze phrase and return {@code null}
* @return The hash sum, or {@code null} if <tt>withReturn</tt> is {@code false}
*/
public static byte[] digest(boolean withReturn)
@@ -503,7 +503,7 @@ public class SHA3
* Absorb the last part of the message and squeeze the Keccak sponge
*
* @param msg The rest of the message
- * @paran withReturn Whether to return the hash instead of just do a quick squeeze phrase and return {@code null}
+ * @param withReturn Whether to return the hash instead of just do a quick squeeze phrase and return {@code null}
* @return The hash sum, or {@code null} if <tt>withReturn</tt> is {@code false}
*/
public static byte[] digest(byte[] msg, boolean withReturn)
diff --git a/pure-java/sha3sum.java b/pure-java/sha3sum.java
index e24657e..3b4cec9 100644
--- a/pure-java/sha3sum.java
+++ b/pure-java/sha3sum.java
@@ -56,6 +56,10 @@ public class sha3sum
cmd = cmd.intern();
Integer O = null; int _o = 512; /* --outputsize */
+ if (cmd == "sha3-224sum") _o = 224;
+ else if (cmd == "sha3-256sum") _o = 256;
+ else if (cmd == "sha3-384sum") _o = 384;
+ else if (cmd == "sha3-512sum") _o = 512;
Integer S = null; int _s = 1600; /* --statesize */
Integer R = null; int _r = _s - (_o << 1); /* --bitrate */
Integer C = null; int _c = _s - _r; /* --capacity */
@@ -64,10 +68,6 @@ public class sha3sum
Integer J = null; int _j = 1; /* --squeezes */
int o = 0, s = 0, r = 0, c = 0, w = 0, i = 0, j = 0;
- if (cmd == "sha3-224sum") o = _o = 224;
- else if (cmd == "sha3-256sum") o = _o = 256;
- else if (cmd == "sha3-384sum") o = _o = 384;
- else if (cmd == "sha3-512sum") o = _o = 512;
boolean binary = false, hex = false;
int multi = 0;
@@ -244,7 +244,7 @@ public class sha3sum
System.exit(6);
}
else if (S == null)
- s = new Integer(w * 25);
+ S = new Integer(w * 25);
}
if (C != null)
@@ -312,6 +312,7 @@ public class sha3sum
System.err.println("State size: " + s);
System.err.println("Output size: " + o);
System.err.println("Iterations: " + i);
+ System.err.println("Squeezes: " + j);
if (fptr == 0)
@@ -341,96 +342,95 @@ public class sha3sum
InputStream file = null;
try
{
- file = new FileInputStream(fn);
- SHA3.initialise(r, c, o);
- int blksize = 4096; /** XXX os.stat(os.path.realpath(fn)).st_size; **/
- byte[] chunk = new byte[blksize];
- for (;;)
+ byte[] bs;
+ if ((filename != null) || (stdin == null))
{
- int read = file.read(chunk, 0, blksize);
- if (read <= 0)
- break;
- if (hex == false)
- SHA3.update(chunk, read);
- else
+ file = new FileInputStream(fn);
+ SHA3.initialise(r, c, o);
+ int blksize = 4096; /** XXX os.stat(os.path.realpath(fn)).st_size; **/
+ byte[] chunk = new byte[blksize];
+ for (;;)
{
- int n = read << 1;
- for (int _ = 0; _ < n; _++)
+ int read = file.read(chunk, 0, blksize);
+ if (read <= 0)
+ break;
+ if (hex == false)
+ SHA3.update(chunk, read);
+ else
{
- byte a = chunk[_ << 1], b = chunk[(_ << 1) | 1];
- chunk[_] = (byte)((((a & 15) + (a <= '9' ? 0 : 9)) << 4) | ((b & 15) + (b <= '9' ? 0 : 9)));
+ int n = read >> 1;
+ for (int _ = 0; _ < n; _++)
+ { byte a = chunk[_ << 1], b = chunk[(_ << 1) | 1];
+ chunk[_] = (byte)((((a & 15) + (a <= '9' ? 0 : 9)) << 4) | ((b & 15) + (b <= '9' ? 0 : 9)));
+ }
+ SHA3.update(chunk, n);
}
- SHA3.update(chunk, n);
}
+ bs = SHA3.digest(j == 1);
+ if (j > 2)
+ SHA3.fastSqueeze(j - 2);
+ if (j > 1)
+ bs = SHA3.squeeze();
+ if (filename == null)
+ stdin = bs;
}
- byte[] bs = SHA3.digest(j > 1);
- if (j > 2)
- SHA3.fastSqueeze(j - 2);
- if (j > 1)
- bs = SHA3.squeeze();
+ else
+ bs = stdin;
if (multi == 0)
{
for (int _ = 1; _ < i; _++)
{
SHA3.initialise(r, c, o);
- bs = SHA3.digest(bs, j > 1);
+ bs = SHA3.digest(bs, j == 1);
if (j > 2)
SHA3.fastSqueeze(j - 2);
if (j > 1)
bs = SHA3.squeeze();
}
if (binary)
- { if (filename == null)
- stdin = bs;
System.out.write(bs);
- }
else
{ for (int b = 0, bn = bs.length; b < bn; b++)
{ rc += "0123456789ABCDEF".charAt((bs[b] >> 4) & 15);
rc += "0123456789ABCDEF".charAt(bs[b] & 15);
}
rc += " " + (filename == null ? "-" : filename) + "\n";
- if (filename == null)
- stdin = rc.getBytes("UTF-8");
System.out.print(rc);
}
}
- else if (binary)
- {
- System.out.write(bs);
- for (int _ = 1; _ < i; _++)
- {
- SHA3.initialise(r, c, o);
- bs = SHA3.digest(bs, j > 1);
- if (j > 2)
- SHA3.fastSqueeze(j - 2);
- if (j > 1)
- bs = SHA3.squeeze();
- System.out.write(bs);
- }
- }
else if (multi == 1)
{
- byte[] out = new byte[(bs.length << 1) + 1];
- for (int b = 0, bn = bs.length; b < bn; b++)
- { out[ b << 1 ] = (byte)("0123456789ABCDEF".charAt((bs[b] >> 4) & 15));
- out[(b << 1) | 1] = (byte)("0123456789ABCDEF".charAt(bs[b] & 15));
+ byte[] out = null;
+ if (binary)
+ System.out.write(bs);
+ else
+ {
+ out = new byte[(bs.length << 1) + 1];
+ for (int b = 0, bn = bs.length; b < bn; b++)
+ { out[ b << 1 ] = (byte)("0123456789ABCDEF".charAt((bs[b] >> 4) & 15));
+ out[(b << 1) | 1] = (byte)("0123456789ABCDEF".charAt(bs[b] & 15));
+ }
+ out[out.length - 1] = '\n';
+ System.out.write(out);
}
- out[out.length - 1] = '\n';
- System.out.write(out);
for (int _ = 1; _ < i; _++)
{
SHA3.initialise(r, c, o);
- bs = SHA3.digest(bs, j > 1);
+ bs = SHA3.digest(bs, j == 1);
if (j > 2)
SHA3.fastSqueeze(j - 2);
if (j > 1)
bs = SHA3.squeeze();
- for (int b = 0, bn = bs.length; b < bn; b++)
- { out[ b << 1 ] = (byte)("0123456789ABCDEF".charAt((bs[b] >> 4) & 15));
- out[(b << 1) | 1] = (byte)("0123456789ABCDEF".charAt(bs[b] & 15));
+ if (binary)
+ System.out.write(bs);
+ else
+ {
+ for (int b = 0, bn = bs.length; b < bn; b++)
+ { out[ b << 1 ] = (byte)("0123456789ABCDEF".charAt((bs[b] >> 4) & 15));
+ out[(b << 1) | 1] = (byte)("0123456789ABCDEF".charAt(bs[b] & 15));
+ }
+ System.out.write(out);
}
- System.out.write(out);
}
}
else
@@ -442,7 +442,7 @@ public class sha3sum
{
if (_ > 0)
{ SHA3.initialise(r, c, o);
- bs = SHA3.digest(bs, j > 1);
+ bs = SHA3.digest(bs, j == 1);
if (j > 2)
SHA3.fastSqueeze(j - 2);
if (j > 1)
@@ -463,7 +463,7 @@ public class sha3sum
System.out.println(now);
}
if (loop != null)
- System.out.println("\033[01;31mLoop found\033[00m");
+ System.err.println("\033[01;31mLoop found\033[00m");
}
System.out.flush();
}
diff --git a/python3/sha3sum.py b/python3/sha3sum.py
index ae863c2..32b09d1 100755
--- a/python3/sha3sum.py
+++ b/python3/sha3sum.py
@@ -23,6 +23,11 @@ import sys
import os
+def printerr(text, end = '\n'):
+ sys.stderr.buffer.write((text + end).encode('utf-8'))
+ sys.stderr.buffer.flush()
+
+
class SHA3:
'''
SHA-3/Keccak hash algorithm implementation
@@ -372,12 +377,16 @@ class SHA3:
@staticmethod
- def update(msg):
+ def update(msg, msglen = None):
'''
Absorb the more of the message message to the Keccak sponge
- @param msg:bytes The partial message
+ @param msg:bytes The partial message
+ @param msglen:int The length of the partial message
'''
+ if msglen is not None:
+ msg = msg[:msglen]
+
rr = SHA3.r >> 3
ww = SHA3.w >> 3
@@ -449,19 +458,24 @@ class SHA3:
@staticmethod
- def digest(msg = None):
+ def digest(msg = None, msglen = None, withReturn = None):
'''
Absorb the last part of the message and squeeze the Keccak sponge
- @param msg:bytes The rest of the message
+ @param msg:bytes? The rest of the message
+ @param msglen:int The length of the partial message
+ @param withReturn:bool Whether to return the hash instead of just do a quick squeeze phrase and return `None`
+ @return :bytes? The hash sum, or `None` if `withReturn` is `False`
'''
+ if (msglen is not None) and isinstance(msglen, bool):
+ (msglen, withReturn) = (withReturn, msglen)
if msg is None:
msg = bytes([])
+ elif msglen is not None:
+ msg = msg[:msglen]
message = SHA3.pad10star1(SHA3.M + msg, SHA3.r)
SHA3.M = None
nnn = len(message)
- rc = [0] * ((SHA3.n + 7) >> 3)
- ptr = 0
rr = SHA3.r >> 3
nn = (SHA3.n + 7) >> 3
@@ -528,16 +542,86 @@ class SHA3:
SHA3.keccakF(SHA3.S)
# Squeezing phase
+ if withReturn:
+ rc = [0] * ((SHA3.n + 7) >> 3)
+ ptr = 0
+
+ olen = SHA3.n
+ j = 0
+ ni = min(25, rr)
+ while olen > 0:
+ i = 0
+ while (i < ni) and (j < nn):
+ v = SHA3.S[(i % 5) * 5 + i // 5]
+ for _ in range(ww):
+ if j < nn:
+ rc[ptr] = v & 255
+ ptr += 1
+ v >>= 8
+ j += 1
+ i += 1
+ olen -= SHA3.r
+ if olen > 0:
+ SHA3.keccakF(SHA3.S)
+ if (SHA3.n & 7) != 0:
+ rc[len(rc) - 1] &= (1 << (SHA3.n & 7)) - 1
+
+ return bytes(rc)
+
+ olen = SHA3.n
+ while olen > SHA3.r:
+ olen -= SHA3.r
+ SHA3.keccakF(SHA3.S)
+ return None
+
+
+ def simpleSqueeze(times = 1):
+ '''
+ Force some rounds of Keccak-f
+
+ @param times:int The number of rounds
+ '''
+ for i in range(times):
+ SHA3.keccakF(SHA3.S)
+
+
+ def fastSqueeze(times = 1):
+ '''
+ Squeeze as much as is needed to get a digest a number of times
+
+ @param times:int The number of digests
+ '''
+ for i in range(times):
+ SHA3.keccakF(SHA3.S) # Last squeeze did not do a ending squeeze
+ int olen = SHA3.n
+ while olen > SHA3.r:
+ olen -= SHA3.r
+ SHA3.keccakF(SHA3.S)
+
+
+ def squeeze():
+ '''
+ Squeeze out another digest
+
+ @return :bytes The hash sum
+ '''
+ SHA3.keccakF(SHA3.S) # Last squeeze did not do a ending squeeze
+
+ nn = (SHA3.n + 7) >> 3
+ ww = SHA3.w >> 3
+ rc = [0] * nn
olen = SHA3.n
j = 0
- ni = min(25, rr)
- while (olen > 0):
+ ptr = 0
+ ni = min(25, SHA3.r >> 3)
+
+ while olen > 0:
i = 0
while (i < ni) and (j < nn):
v = SHA3.S[(i % 5) * 5 + i // 5]
for _ in range(ww):
- if (j < nn):
- rc[ptr] = v & 255
+ if j < nn:
+ rc[ptr] = v
ptr += 1
v >>= 8
j += 1
@@ -545,11 +629,12 @@ class SHA3:
olen -= SHA3.r
if olen > 0:
SHA3.keccakF(SHA3.S)
+
if (SHA3.n & 7) != 0:
rc[len(rc) - 1] &= (1 << (SHA3.n & 7)) - 1
return bytes(rc)
-
+
if __name__ == '__main__':
@@ -560,19 +645,20 @@ if __name__ == '__main__':
if cmd.endswith('.py'):
cmd = cmd[:-3]
- o = 512 # --outputsize
- if cmd == 'sha3-224sum': o = 224
- elif cmd == 'sha3-256sum': o = 256
- elif cmd == 'sha3-384sum': o = 384
- elif cmd == 'sha3-512sum': o = 512
- s = 1600 # --statesize
- r = s - (o << 1) # --bitrate
- c = s - r # --capacity
- w = s // 25 # --wordsize
- i = 1 # --iterations
- binary = False
-
- (_r, _c, _w, _o, _s, _i) = (r, c, w, o, s, i)
+ (O, S, R, C, W, I, J) = (None, None, None, None, None, None, None)
+ (o, s, r, c, w, i, j) = (0, 0, 0, 0, 0, 0, 0)
+ _o = 512 # --outputsize
+ if cmd == 'sha3-224sum': _o = 224
+ elif cmd == 'sha3-256sum': _o = 256
+ elif cmd == 'sha3-384sum': _o = 384
+ elif cmd == 'sha3-512sum': _o = 512
+ _s = 1600 # --statesize
+ _r = _s - (_o << 1) # --bitrate
+ _c = _s - _r # --capacity
+ _w = _s / 25 # --wordsize
+ _i = 1 # --iterations
+ _j = 1 # --squeezes
+ (binary, hex, multi) = (False, False, 0)
files = []
dashed = False
@@ -606,9 +692,18 @@ OPTIONS:
-i ITERATIONS
--iterations The number of hash iterations to run. (default: %d)
-
+
+ -j SQUEEZES
+ --squeezes The number of hash squeezes to run. (default: %d)
+
+ -h
+ --hex Read the input in hexadecimal, rather than binary.
+
-b
--binary Print the checksum in binary, rather than hexadecimal.
+
+ -m
+ --multi Print the chechsum at all iterations.
COPYRIGHT:
@@ -628,7 +723,7 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-''' % (_r, _c, _w, _o, _s, _i)).encode('utf-8'))
+''' % (_r, _c, _w, _o, _s, _i, _j)).encode('utf-8'))
sys.stderr.buffer.flush()
exit(2)
else:
@@ -636,26 +731,22 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
linger[1] = arg
arg = None
if linger[0] in ('-r', '--bitrate'):
- r = int(linger[1])
- o = (s - r) >> 1
+ R = int(linger[1])
elif linger[0] in ('-c', '--capacity'):
- c = int(linger[1])
- r = s - c
+ C = int(linger[1])
elif linger[0] in ('-w', '--wordsize'):
- w = int(linger[1])
- s = w * 25
+ W = int(linger[1])
elif linger[0] in ('-o', '--outputsize'):
- o = int(linger[1])
- r = s - (o << 1)
+ O = int(linger[1])
elif linger[0] in ('-s', '--statesize'):
- s = int(linger[1])
- r = s - (o << 1)
+ S = int(linger[1])
elif linger[0] in ('-i', '--iterations'):
- i = int(linger[1])
+ I = int(linger[1])
+ elif linger[0] in ('-j', '--squeezes'):
+ J = int(linger[1])
else:
- sys.stderr.buffer.write((sys.argv[0] + ': unrecognised option: ' + linger[0] + '\n').encode('utf-8'))
- sys.stdout.buffer.flush()
- exit(1)
+ printerr(sys.argv[0] + ': unrecognised option: ' + linger[0])
+ sys.exit(1)
linger = None
if arg is None:
continue
@@ -673,6 +764,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
else:
if arg == '--binary':
binary = True
+ elif arg == '--multi':
+ multi += 1
+ elif arg == '--hex':
+ hex = True
else:
linger = [arg, None]
elif arg.startswith('-'):
@@ -680,6 +775,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
if arg[0] == 'b':
binary = True
arg = arg[1:]
+ elif arg[0] == 'b':
+ multi += 1
+ arg = arg[1:]
+ elif arg[0] == 'h':
+ hex = True
+ arg = arg[1:]
elif len(arg) == 1:
linger = ['-' + arg, None]
else:
@@ -687,12 +788,95 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
else:
files.append(arg)
+
+ i = _i if I is None else I
+ j = _j if J is None else J
+
+
+ if S is not None:
+ s = S
+ if ((s <= 0) or (s > 1600) or (s % 25 != 0)):
+ printerr(cmd + ': the state size must be a positive multiple of 25 and is limited to 1600.')
+ sys.exit(6)
+
+ if W is not None:
+ w = W
+ if (w <= 0) or (w > 64):
+ printerr(cmd + ': the word size must be positive and is limited to 64.')
+ sys.exit(6)
+ if (S is not None) and (s != w * 25):
+ printerr(cmd + ': the state size must be 25 times of the word size.')
+ sys.exit(6)
+ elif S is None:
+ S = w * 25
+
+ if C is not None:
+ c = C
+ if (c <= 0) or ((c & 7) != 0):
+ printerr(cmd + ': the capacity must be a positive multiple of 8.')
+ sys.exit(6);
+
+ if R is not None:
+ r = R
+ if (r <= 0) or ((r & 7) != 0):
+ printerr(cmd + ': the bitrate must be a positive multiple of 8.')
+ sys.exit(6);
+
+ if O is not None:
+ o = O
+ if o <= 0:
+ printerr(cmd + ': the output size must be positive.')
+ sys.exit(6);
+
+
+ if (R is None) and (C is None) and (O is None): ## s?
+ r = -((c = (o = ((((s = S is None ? _s : s) << 5) / 100 + 7) >> 3) << 3) << 1) - s);
+ o = 8 if o < 8 else o
+ elif (R is None) and (C is None): ## !o s?
+ r = _r
+ c = _c
+ s = (r + c) if S is None else s
+ elif R is None: ## !c o? s?
+ s = _s if S is None else s
+ r = s - c;
+ o = (8 if c == 8 else (c << 1)) if O is None else o;
+ elif C is None: ## !r o? s?
+ s = _s if S is None else s
+ c = s - r;
+ o = (8 if c == 8 else (c << 1)) if O is None else o;
+ else: ## !r !c o? s?
+ s = (r + c) if S is None else s
+ o = (8 if c == 8 else (c << 1)) if O is None else o
+
+
+ if r > s:
+ printerr(cmd + ': the bitrate must not be higher than the state size.');
+ sys.exit(6);
+ if c > s:
+ printerr(cmd + ': the capacity must not be higher than the state size.');
+ sys.exit(6);
+ if r + c != s:
+ printerr(cmd + ': the sum of the bitrate and the capacity must equal the state size.');
+ sys.exit(6);
+
+
+ printerr('Bitrate: ' % r)
+ printerr('Capacity: ' % c)
+ printerr('Word size: ' % w)
+ printerr('State size: ' % s)
+ printerr('Output size: ' % o)
+ printerr('Iterations: ' % i)
+ printerr('Squeezes: ' % j)
+
+
if len(files) == 0:
files.append(None)
if i < 1:
- sys.stdout.buffer.write((sys.argv[0] + ': sorry, I will only do at least one iteration!\n').encode('utf-8'))
- sys.stdout.buffer.flush()
- exit(3)
+ printerr(cmd + ': sorry, I will only do at least one hash iteration!\n')
+ sys.exit(3)
+ if j < 1:
+ printerr(cmd + ': sorry, I will only do at least one squeeze iteration!\n')
+ sys.exit(3)
stdin = None
for filename in files:
if (filename is None) and (stdin is not None):
@@ -700,35 +884,107 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
continue
rc = ''
fn = '/dev/stdin' if filename is None else filename
+ fail = False
with open(fn, 'rb') as file:
- SHA3.initialise(r, c, o)
- blksize = (o + 7) >> 3
try:
- blksize = os.stat(os.path.realpath(fn)).st_blksize
- except:
- pass
- while True:
- chunk = file.read(blksize)
- if len(chunk) == 0:
- break
- SHA3.update(chunk)
- bs = SHA3.digest(file.read())
- for _ in range(1, i):
- SHA3.initialise(r, c, o)
- bs = SHA3.digest(bs)
- if binary:
- if filename is None:
- stdin = bs
- sys.stdout.buffer.write(bs)
- sys.stdout.buffer.flush()
- else:
- for b in bs:
- rc += "0123456789ABCDEF"[b >> 4]
- rc += "0123456789ABCDEF"[b & 15]
- rc += ' ' + ('-' if filename is None else filename) + '\n'
- if filename is None:
- stdin = rc
- sys.stdout.buffer.write(rc.encode('UTF-8'))
+ if (filename is not None) or (stdin is None):
+ SHA3.initialise(r, c, o)
+ blksize = 4096
+ try:
+ blksize = os.stat(os.path.realpath(fn)).st_blksize
+ except:
+ pass
+ while True:
+ chunk = file.read(blksize)
+ if len(chunk) == 0:
+ break
+ if not hex:
+ SHA3.update(chunk)
+ else:
+ chunk = list(chunk)
+ n = len(chunk) >> 1
+ for _ in range(n):
+ (a, b) = (chunk[_ << 1], chunk[(_ << 1 | 1)])
+ a = ((a & 15) + (0 if a <= '9' else 9)) << 4
+ b = (b & 15) + (0 if b <= '9' else 0)
+ chunk[_] = a | b
+ SHA3.update(chunk, n)
+ bs = SHA3.digest(j == 1)
+ if j > 2:
+ SHA3.fastSqueeze(j - 2)
+ if j > 1:
+ bs = SHA3.squeeze();
+ if filename is None:
+ stdin = bs
+ else:
+ bs = stdin
+ if multi == 0:
+ for _ in range(n - 1):
+ SHA3.initialise(r, c, o)
+ bs = SHA3.digest(bs, j == 1)
+ if j > 2:
+ SHA3.fastSqueeze(j - 2)
+ if j > 1:
+ bs = SHA3.squeeze();
+ if binary:
+ sys.stdout.buffer.write(bs)
+ else:
+ for b in bs:
+ rc += "0123456789ABCDEF"[b >> 4]
+ rc += "0123456789ABCDEF"[b & 15]
+ rc += ' ' + ('-' if filename is None else filename) + '\n'
+ sys.stdout.buffer.write(rc.encode('utf-8'))
+ elif multi == 1:
+ if binary:
+ sys.stdout.buffer.write(bs)
+ else:
+ for b in bs:
+ rc += "0123456789ABCDEF"[b >> 4]
+ rc += "0123456789ABCDEF"[b & 15]
+ rc += '\n'
+ sys.stdout.buffer.write(rc.encode('UTF-8'))
+ for _ in range(i - 1):
+ SHA3.initialise(r, c, o)
+ bs = SHA3.digest(bs, j == 1)
+ if j > 2:
+ SHA3.fastSqueeze(j - 2)
+ if j > 1:
+ bs = SHA3.squeeze();
+ if binary:
+ sys.stdout.buffer.write(bs);
+ else:
+ rc = ''
+ for b in bs:
+ rc += "0123456789ABCDEF"[b >> 4]
+ rc += "0123456789ABCDEF"[b & 15]
+ rc += '\n'
+ sys.stdout.buffer.write(rc.encode('UTF-8'))
+ else:
+ got = set()
+ loop = None
+ for _ in range(i):
+ if _ > 0:
+ pass
+ rc = ''
+ for b in bs:
+ rc += "0123456789ABCDEF"[b >> 4]
+ rc += "0123456789ABCDEF"[b & 15]
+ if loop is None:
+ if rc in got:
+ loop = rc
+ else:
+ got.add(rc)
+ if loop == rc:
+ rc = '\033[31m%s\033[00m' % rc;
+ sys.stdout.buffer.write(rc.encode('utf-8'))
+ sys.stdout.buffer.flush()
+ if loop is not None:
+ printerr('\033[01;31mLoop found\033[00m')
sys.stdout.buffer.flush()
-
+ except Exception as err:
+ printerr(cmd + ': connot read file: ' + filename + ': ' + str(err))
+ fail = True
+ sys.stdout.buffer.flush()
+ if fail:
+ sys.exit(5)