diff options
author | Mattias Andrée <maandree@operamail.com> | 2014-08-21 18:22:25 +0200 |
---|---|---|
committer | Mattias Andrée <maandree@operamail.com> | 2014-08-21 18:22:25 +0200 |
commit | 0a9fd0ca7575e96c7eac5a80dacedd074e568226 (patch) | |
tree | 3a55ed6d93a94d458eeb022381476d84b4df0680 /java | |
parent | fix memory leak (diff) | |
download | sha3sum-0a9fd0ca7575e96c7eac5a80dacedd074e568226.tar.gz sha3sum-0a9fd0ca7575e96c7eac5a80dacedd074e568226.tar.bz2 sha3sum-0a9fd0ca7575e96c7eac5a80dacedd074e568226.tar.xz |
beginning on support for partial bytes, c implemention is not working correctly
Signed-off-by: Mattias Andrée <maandree@operamail.com>
Diffstat (limited to 'java')
-rw-r--r-- | java/ConcurrentSHA3.java | 238 | ||||
-rw-r--r-- | java/SHA3.java | 238 | ||||
-rw-r--r-- | java/sha3sum.java | 14 |
3 files changed, 439 insertions, 51 deletions
diff --git a/java/ConcurrentSHA3.java b/java/ConcurrentSHA3.java index 88934f3..622feb5 100644 --- a/java/ConcurrentSHA3.java +++ b/java/ConcurrentSHA3.java @@ -26,6 +26,27 @@ public class ConcurrentSHA3 { /** + * Suffix the message when calculating the Keccak hash sum + */ + public static final String KECCAK_SUFFIX = ""; + + /** + * Suffix the message when calculating the SHA-3 hash sum + */ + public static final String SHA3_SUFFIX = "01"; + + /** + * Suffix the message when calculating the RawSHAKE hash sum + */ + public static final String RawSHAKE_SUFFIX = "11"; + + /** + * Suffix the message when calculating the SHAKE hash sum + */ + public static final String SHAKE_SUFFIX = "1111"; + + + /** * Round contants */ private static final long[] RC = { @@ -323,18 +344,21 @@ public class ConcurrentSHA3 /** * pad 10*1 * - * @param msg The message to pad - * @param len The length of the message - * @param r The bitrate - * @return The actual length of {@link #message} + * @param msg The message to pad + * @param len The length of the message + * @param r The bitrate + * @param bits The number of bits in the end of the message that does not make a whole byte + * @return The actual length of {@link #message} */ - private int pad10star1(byte[] msg, int len, int r) + private int pad10star1(byte[] msg, int len, int r, int bits) { - int nrf = (len <<= 3) >> 3; + len = ((len - (bits + 7) / 8) << 3) + bits; + + int nrf = len >> 3; int nbrf = len & 7; int ll = len % r; - byte b = (byte)(nbrf == 0 ? 1 : ((msg[nrf] >> (8 - nbrf)) | (1 << nbrf))); + byte b = (byte)(nbrf == 0 ? 1 : (msg[nrf] | (1 << nbrf))); if ((r - 8 <= ll) && (ll <= r - 2)) { @@ -485,7 +509,19 @@ public class ConcurrentSHA3 */ public byte[] digest() { - return this.digest(null, 0, true); + return digest(null, 0, 0, SHA3.SHA3_SUFFIX, true); + } + + + /** + * Squeeze the Keccak sponge + * + * @param suffix The suffix concatenate to the message + * @return The hash sum + */ + public byte[] digest(String suffix) + { + return digest(null, 0, 0, suffix, true); } @@ -497,7 +533,20 @@ public class ConcurrentSHA3 */ public byte[] digest(boolean withReturn) { - return this.digest(null, 0, withReturn); + return digest(null, 0, 0, SHA3.SHA3_SUFFIX, withReturn); + } + + + /** + * Squeeze the Keccak sponge + * + * @param suffix The suffix concatenate to the 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 byte[] digest(String suffix, boolean withReturn) + { + return digest(null, 0, 0, suffix, withReturn); } @@ -509,7 +558,20 @@ public class ConcurrentSHA3 */ public byte[] digest(byte[] msg) { - return this.digest(msg, msg == null ? 0 : msg.length, true); + return digest(msg, msg == null ? 0 : msg.length, 0, SHA3.SHA3_SUFFIX, true); + } + + + /** + * Absorb the last part of the message and squeeze the Keccak sponge + * + * @param msg The rest of the message + * @param suffix The suffix concatenate to the message + * @return The hash sum + */ + public byte[] digest(byte[] msg, String suffix) + { + return digest(msg, msg == null ? 0 : msg.length, 0, suffix, true); } @@ -522,7 +584,21 @@ public class ConcurrentSHA3 */ public byte[] digest(byte[] msg, boolean withReturn) { - return this.digest(msg, msg == null ? 0 : msg.length, withReturn); + return digest(msg, msg == null ? 0 : msg.length, 0, SHA3.SHA3_SUFFIX, withReturn); + } + + + /** + * Absorb the last part of the message and squeeze the Keccak sponge + * + * @param msg The rest of the message + * @param suffix The suffix concatenate to the 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 byte[] digest(byte[] msg, String suffix, boolean withReturn) + { + return digest(msg, msg == null ? 0 : msg.length, 0, suffix, withReturn); } @@ -530,12 +606,55 @@ public class ConcurrentSHA3 * 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 msglen The length of the partial message in while bytes * @return The hash sum */ public byte[] digest(byte[] msg, int msglen) { - return this.digest(msg, msg == null ? 0 : msg.length, true); + return digest(msg, msg == null ? 0 : msg.length, 0, SHA3.SHA3_SUFFIX, 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 in while bytes + * @param suffix The suffix concatenate to the message + * @return The hash sum + */ + public byte[] digest(byte[] msg, int msglen, String suffix) + { + return digest(msg, msg == null ? 0 : msg.length, 0, suffix, 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 in while bytes + * @param bits The number of bits at the end of the message not covered by <tt>msglen</tt> + * @return The hash sum + */ + public byte[] digest(byte[] msg, int msglen, int bits) + { + return digest(msg, msg == null ? 0 : msg.length, bits, SHA3.SHA3_SUFFIX, 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 in while bytes + * @param bits The number of bits at the end of the message not covered by <tt>msglen</tt> + * @param suffix The suffix concatenate to the message + * @return The hash sum + */ + public byte[] digest(byte[] msg, int msglen, int bits, String suffix) + { + return digest(msg, msg == null ? 0 : msg.length, bits, suffix, true); } @@ -543,22 +662,97 @@ public class ConcurrentSHA3 * 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 msglen The length of the partial message in while bytes * @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 byte[] digest(byte[] msg, int msglen, boolean withReturn) { + return digest(msg, msg == null ? 0 : msg.length, 0, SHA3.SHA3_SUFFIX, 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 in while bytes + * @param suffix The suffix concatenate to the 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 byte[] digest(byte[] msg, int msglen, String suffix, boolean withReturn) + { + return digest(msg, msg == null ? 0 : msg.length, 0, suffix, 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 in while bytes + * @param bits The number of bits at the end of the message not covered by <tt>msglen</tt> + * @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 byte[] digest(byte[] msg, int msglen, int bits, boolean withReturn) + { + return digest(msg, msg == null ? 0 : msg.length, 0, SHA3.SHA3_SUFFIX, 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 + * @param bits The number of bits at the end of the message not covered by <tt>msglen</tt> + * @param suffix The suffix concatenate to the 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 byte[] digest(byte[] msg, int msglen, int bits, String suffix, boolean withReturn) + { int len; + byte last_byte = 0; if ((msg == null) || (msglen == 0)) - len = this.pad10star1(this.M, this.mptr, this.r); - else { - if (this.mptr + msglen > this.M.length) - System.arraycopy(this.M, 0, this.M = new byte[this.M.length + msglen], 0, this.mptr); - System.arraycopy(msg, 0, this.M, this.mptr, msglen); - len = this.pad10star1(this.M, this.mptr + msglen, this.r); + msg = new byte[0]; + bits = 0; + } + + msglen += bits / 8; + if ((bits %= 8) != 0) + last_byte = msg[msglen]; + + byte[] msg_end = new byte[(suffix.length() + bits + 7) / 8]; + int msg_end_ptr = 0; + for (int i = 0, n = suffix.length(); i < n; i++) + { + byte bit = (byte)(suffix.charAt(i) - '0'); + last_byte |= bit << bits++; + if (bits == 8) + { + msg_end[msg_end_ptr++] = last_byte; + last_byte = 0; + bits = 0; + } + } + if (bits != 0) + msg_end[msg_end_ptr++] = last_byte; + if (msg_end_ptr > 0) + { + if (msglen + msg_end_ptr > msg.length) + System.arraycopy(msg, 0, msg = new byte[msglen + msg_end_ptr], 0, msglen); + System.arraycopy(msg_end, 0, msg, msglen, msg_end_ptr); + msglen += msg_end_ptr; } + + if (this.mptr + msglen > this.M.length) + System.arraycopy(this.M, 0, this.M = new byte[this.M.length + msglen], 0, this.mptr); + System.arraycopy(msg, 0, this.M, this.mptr, msglen); + len = this.pad10star1(this.M, this.mptr + msglen, this.r, bits); int rr = this.r >> 3; int nn = (this.n + 7) >> 3; @@ -645,7 +839,7 @@ public class ConcurrentSHA3 while ((i < ni) && (j < nn)) { long v = this.S[(i % 5) * 5 + i / 5]; - for (int _ = 0; _ < ww; _++) + for (int k = 0; k < ww; k++) { if (j < nn) { @@ -744,7 +938,7 @@ public class ConcurrentSHA3 while ((i < ni) && (j < nn)) { long v = this.S[(i % 5) * 5 + i / 5]; - for (int _ = 0; _ < ww; _++) + for (int k = 0; k < ww; k++) { if (j < nn) { diff --git a/java/SHA3.java b/java/SHA3.java index 616e05f..8ab9a51 100644 --- a/java/SHA3.java +++ b/java/SHA3.java @@ -26,6 +26,27 @@ public class SHA3 { /** + * Suffix the message when calculating the Keccak hash sum + */ + public static final String KECCAK_SUFFIX = ""; + + /** + * Suffix the message when calculating the SHA-3 hash sum + */ + public static final String SHA3_SUFFIX = "01"; + + /** + * Suffix the message when calculating the RawSHAKE hash sum + */ + public static final String RawSHAKE_SUFFIX = "11"; + + /** + * Suffix the message when calculating the SHAKE hash sum + */ + public static final String SHAKE_SUFFIX = "1111"; + + + /** * Round contants */ private static final long[] RC = { @@ -318,18 +339,21 @@ public class SHA3 /** * pad 10*1 * - * @param msg The message to pad - * @param len The length of the message - * @param r The bitrate - * @return The actual length of {@link #message} + * @param msg The message to pad + * @param len The length of the message + * @param r The bitrate + * @param bits The number of bits in the end of the message that does not make a whole byte + * @return The actual length of {@link #message} */ - private static int pad10star1(byte[] msg, int len, int r) + private static int pad10star1(byte[] msg, int len, int r, int bits) { - int nrf = (len <<= 3) >> 3; + len = ((len - (bits + 7) / 8) << 3) + bits; + + int nrf = len >> 3; int nbrf = len & 7; int ll = len % r; - byte b = (byte)(nbrf == 0 ? 1 : ((msg[nrf] >> (8 - nbrf)) | (1 << nbrf))); + byte b = (byte)(nbrf == 0 ? 1 : (msg[nrf] | (1 << nbrf))); if ((r - 8 <= ll) && (ll <= r - 2)) { @@ -491,7 +515,19 @@ public class SHA3 */ public static byte[] digest() { - return digest(null, 0, true); + return digest(null, 0, 0, SHA3.SHA3_SUFFIX, true); + } + + + /** + * Squeeze the Keccak sponge + * + * @param suffix The suffix concatenate to the message + * @return The hash sum + */ + public static byte[] digest(String suffix) + { + return digest(null, 0, 0, suffix, true); } @@ -503,7 +539,20 @@ public class SHA3 */ public static byte[] digest(boolean withReturn) { - return digest(null, 0, withReturn); + return digest(null, 0, 0, SHA3.SHA3_SUFFIX, withReturn); + } + + + /** + * Squeeze the Keccak sponge + * + * @param suffix The suffix concatenate to the 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 byte[] digest(String suffix, boolean withReturn) + { + return digest(null, 0, 0, suffix, withReturn); } @@ -515,7 +564,20 @@ public class SHA3 */ public static byte[] digest(byte[] msg) { - return digest(msg, msg == null ? 0 : msg.length, true); + return digest(msg, msg == null ? 0 : msg.length, 0, SHA3.SHA3_SUFFIX, true); + } + + + /** + * Absorb the last part of the message and squeeze the Keccak sponge + * + * @param msg The rest of the message + * @param suffix The suffix concatenate to the message + * @return The hash sum + */ + public static byte[] digest(byte[] msg, String suffix) + { + return digest(msg, msg == null ? 0 : msg.length, 0, suffix, true); } @@ -528,7 +590,21 @@ public class SHA3 */ public static byte[] digest(byte[] msg, boolean withReturn) { - return digest(msg, msg == null ? 0 : msg.length, withReturn); + return digest(msg, msg == null ? 0 : msg.length, 0, SHA3.SHA3_SUFFIX, withReturn); + } + + + /** + * Absorb the last part of the message and squeeze the Keccak sponge + * + * @param msg The rest of the message + * @param suffix The suffix concatenate to the 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 byte[] digest(byte[] msg, String suffix, boolean withReturn) + { + return digest(msg, msg == null ? 0 : msg.length, 0, suffix, withReturn); } @@ -536,12 +612,55 @@ public class SHA3 * 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 msglen The length of the partial message in while bytes * @return The hash sum */ public static byte[] digest(byte[] msg, int msglen) { - return digest(msg, msg == null ? 0 : msg.length, true); + return digest(msg, msg == null ? 0 : msg.length, 0, SHA3.SHA3_SUFFIX, 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 in while bytes + * @param suffix The suffix concatenate to the message + * @return The hash sum + */ + public static byte[] digest(byte[] msg, int msglen, String suffix) + { + return digest(msg, msg == null ? 0 : msg.length, 0, suffix, 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 in while bytes + * @param bits The number of bits at the end of the message not covered by <tt>msglen</tt> + * @return The hash sum + */ + public static byte[] digest(byte[] msg, int msglen, int bits) + { + return digest(msg, msg == null ? 0 : msg.length, bits, SHA3.SHA3_SUFFIX, 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 in while bytes + * @param bits The number of bits at the end of the message not covered by <tt>msglen</tt> + * @param suffix The suffix concatenate to the message + * @return The hash sum + */ + public static byte[] digest(byte[] msg, int msglen, int bits, String suffix) + { + return digest(msg, msg == null ? 0 : msg.length, bits, suffix, true); } @@ -549,22 +668,97 @@ public class SHA3 * 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 msglen The length of the partial message in while bytes * @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, int msglen, boolean withReturn) { + return digest(msg, msg == null ? 0 : msg.length, 0, SHA3.SHA3_SUFFIX, 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 in while bytes + * @param suffix The suffix concatenate to the 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 byte[] digest(byte[] msg, int msglen, String suffix, boolean withReturn) + { + return digest(msg, msg == null ? 0 : msg.length, 0, suffix, 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 in while bytes + * @param bits The number of bits at the end of the message not covered by <tt>msglen</tt> + * @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, int msglen, int bits, boolean withReturn) + { + return digest(msg, msg == null ? 0 : msg.length, 0, SHA3.SHA3_SUFFIX, 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 in while bytes + * @param bits The number of bits at the end of the message not covered by <tt>msglen</tt> + * @param suffix The suffix concatenate to the 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 byte[] digest(byte[] msg, int msglen, int bits, String suffix, boolean withReturn) + { int len; + byte last_byte = 0; if ((msg == null) || (msglen == 0)) - len = SHA3.pad10star1(SHA3.M, SHA3.mptr, SHA3.r); - else { - if (SHA3.mptr + msglen > SHA3.M.length) - System.arraycopy(SHA3.M, 0, SHA3.M = new byte[SHA3.M.length + msglen], 0, SHA3.mptr); - System.arraycopy(msg, 0, SHA3.M, SHA3.mptr, msglen); - len = SHA3.pad10star1(SHA3.M, SHA3.mptr + msglen, SHA3.r); + msg = new byte[0]; + bits = 0; + } + + msglen += bits / 8; + if ((bits %= 8) != 0) + last_byte = msg[msglen]; + + byte[] msg_end = new byte[(suffix.length() + bits + 7) / 8]; + int msg_end_ptr = 0; + for (int i = 0, n = suffix.length(); i < n; i++) + { + byte bit = (byte)(suffix.charAt(i) - '0'); + last_byte |= bit << bits++; + if (bits == 8) + { + msg_end[msg_end_ptr++] = last_byte; + last_byte = 0; + bits = 0; + } + } + if (bits != 0) + msg_end[msg_end_ptr++] = last_byte; + if (msg_end_ptr > 0) + { + if (msglen + msg_end_ptr > msg.length) + System.arraycopy(msg, 0, msg = new byte[msglen + msg_end_ptr], 0, msglen); + System.arraycopy(msg_end, 0, msg, msglen, msg_end_ptr); + msglen += msg_end_ptr; } + + if (SHA3.mptr + msglen > SHA3.M.length) + System.arraycopy(SHA3.M, 0, SHA3.M = new byte[SHA3.M.length + msglen], 0, SHA3.mptr); + System.arraycopy(msg, 0, SHA3.M, SHA3.mptr, msglen); + len = SHA3.pad10star1(SHA3.M, SHA3.mptr + msglen, SHA3.r, bits); int rr = SHA3.r >> 3; int nn = (SHA3.n + 7) >> 3; @@ -651,7 +845,7 @@ public class SHA3 while ((i < ni) && (j < nn)) { long v = SHA3.S[(i % 5) * 5 + i / 5]; - for (int _ = 0; _ < ww; _++) + for (int k = 0; k < ww; k++) { if (j < nn) { @@ -750,7 +944,7 @@ public class SHA3 while ((i < ni) && (j < nn)) { long v = SHA3.S[(i % 5) * 5 + i / 5]; - for (int _ = 0; _ < ww; _++) + for (int k = 0; k < ww; k++) { if (j < nn) { diff --git a/java/sha3sum.java b/java/sha3sum.java index a7abd07..c3c63a5 100644 --- a/java/sha3sum.java +++ b/java/sha3sum.java @@ -355,9 +355,9 @@ public class sha3sum else { 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))); + for (int k = 0; k < n; k++) + { byte a = chunk[k << 1], b = chunk[(k << 1) | 1]; + chunk[k] = (byte)((((a & 15) + (a <= '9' ? 0 : 9)) << 4) | ((b & 15) + (b <= '9' ? 0 : 9))); } SHA3.update(chunk, n); } @@ -374,7 +374,7 @@ public class sha3sum bs = stdin; if (multi == 0) { - for (int _ = 1; _ < i; _++) + for (int k = 1; k < i; k++) { SHA3.initialise(r, c, o); bs = SHA3.digest(bs, j == 1); @@ -409,7 +409,7 @@ public class sha3sum out[out.length - 1] = '\n'; System.out.write(out); } - for (int _ = 1; _ < i; _++) + for (int k = 1; k < i; k++) { SHA3.initialise(r, c, o); bs = SHA3.digest(bs, j == 1); @@ -434,9 +434,9 @@ public class sha3sum HashSet<String> got = new HashSet<String>(); String loop = null; byte[] out = new byte[(bs.length << 1)]; - for (int _ = 0; _ < i; _++) + for (int k = 0; k < i; k++) { - if (_ > 0) + if (k > 0) { SHA3.initialise(r, c, o); bs = SHA3.digest(bs, j == 1); if (j > 2) |