diff options
author | Mattias Andrée <maandree@operamail.com> | 2013-06-16 23:48:26 +0200 |
---|---|---|
committer | Mattias Andrée <maandree@operamail.com> | 2013-06-16 23:48:26 +0200 |
commit | 42c0197d1858200b09d4e0523b44dc1e150cb2df (patch) | |
tree | d5f4215ca3716abde3b9f949dbb6053d6ed6bb80 /c | |
parent | m (diff) | |
download | sha3sum-42c0197d1858200b09d4e0523b44dc1e150cb2df.tar.gz sha3sum-42c0197d1858200b09d4e0523b44dc1e150cb2df.tar.bz2 sha3sum-42c0197d1858200b09d4e0523b44dc1e150cb2df.tar.xz |
misc
Signed-off-by: Mattias Andrée <maandree@operamail.com>
Diffstat (limited to '')
-rw-r--r-- | c/sha3.c | 99 | ||||
-rw-r--r-- | c/sha3.h | 32 | ||||
-rw-r--r-- | c/sha3sum.c | 517 |
3 files changed, 561 insertions, 87 deletions
@@ -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; } @@ -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); |