aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias Andrée <maandree@operamail.com>2014-08-21 18:22:25 +0200
committerMattias Andrée <maandree@operamail.com>2014-08-21 18:22:25 +0200
commit0a9fd0ca7575e96c7eac5a80dacedd074e568226 (patch)
tree3a55ed6d93a94d458eeb022381476d84b4df0680
parentfix memory leak (diff)
downloadsha3sum-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>
-rw-r--r--c/sha3.c88
-rw-r--r--c/sha3.h24
-rw-r--r--c/sha3sum.c18
-rw-r--r--java-c-jni/SHA3.c69
-rw-r--r--java-c-jni/SHA3.java201
-rw-r--r--java-c-jni/sha3sum.java14
-rw-r--r--java/ConcurrentSHA3.java238
-rw-r--r--java/SHA3.java238
-rw-r--r--java/sha3sum.java14
-rw-r--r--python2/sha3.py68
-rwxr-xr-xpython2/sha3sum.py6
-rw-r--r--python3/sha3.py68
-rwxr-xr-xpython3/sha3sum.py6
13 files changed, 888 insertions, 164 deletions
diff --git a/c/sha3.c b/c/sha3.c
index c460b5f..ca7c964 100644
--- a/c/sha3.c
+++ b/c/sha3.c
@@ -18,6 +18,8 @@
*/
#include "sha3.h"
+#include <string.h>
+
#ifdef WITH_C99
#define static_inline static inline
@@ -421,19 +423,22 @@ static_inline llong sha3_toLane64(byte* restrict_ message, long msglen, long rr,
* @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
* @param outlen The length of the padded message (out parameter)
* @return The message padded
*/
-static_inline byte* sha3_pad10star1(byte* restrict_ msg, long len, long r, long* restrict_ outlen)
+static_inline byte* sha3_pad10star1(byte* restrict_ msg, long len, long r, long bits, long* restrict_ outlen)
{
byte* message;
+ byte b;
+ long i, ll, nbrf, nrf;
- long nrf = (len <<= 3) >> 3;
- long nbrf = len & 7;
- long ll = len % r;
- long i;
+ len = ((len - (bits + 7) / 8) << 3) + bits;
+ nrf = len >> 3;
+ nbrf = len & 7;
+ ll = len % r;
- byte b = (byte)(nbrf == 0 ? 1 : ((msg[nrf] >> (8 - nbrf)) | (1 << nbrf)));
+ b = (byte)(nbrf == 0 ? 1 : (msg[nrf] | (1 << nbrf)));
if ((r - 8 <= ll) && (ll <= r - 2))
{
@@ -591,7 +596,7 @@ extern void sha3_update(byte* restrict_ msg, long msglen)
long nnn;
if (mptr + msglen > mlen)
- #ifdef WITH_WIPE
+ #ifndef WITH_WIPE
M = (byte*)realloc(M, mlen = (mlen + msglen) << 1);
#else
{
@@ -656,10 +661,12 @@ extern void sha3_update(byte* restrict_ msg, long msglen)
*
* @param msg The rest of the message, may be {@code null}
* @param msglen The length of the partial message
+ * @param bits The number of bits at the end of the message not covered by `msglen`
+ * @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}
*/
-extern byte* sha3_digest(byte* restrict_ msg, long msglen, boolean withReturn)
+extern byte* sha3_digest(byte* restrict_ msg, long msglen, long bits, char* restrict_ suffix, boolean withReturn)
{
byte* message;
byte* _msg;
@@ -669,28 +676,57 @@ extern byte* sha3_digest(byte* restrict_ msg, long msglen, boolean withReturn)
long ww = w >> 3, ni;
long i, j = 0, ptr = 0, _;
long nnn;
+ long suffix_len = strlen(suffix);
- if ((msg == null) || (msglen == 0))
- message = sha3_pad10star1(M, mptr, r, &len);
- else
+ if (msg == null)
+ msglen = bits = 0;
+
+ msglen += bits >> 3;
+ if ((bits &= 7))
{
- if (mptr + msglen > mlen)
- #ifdef WITH_WIPE
- M = (byte*)realloc(M, mlen += msglen);
- #else
+ msg[msglen] &= (1 << bits) - 1;
+ #ifndef WITH_WIPE
+ msg = (byte*)realloc(msg, msglen + ((suffix_len + bits + 7) >> 3));
+ #else
+ {
+ char* old_msg = msg;
+ msg = (byte*)malloc(msglen + ((suffix_len + bits + 7) >> 3));
+ memcpy(msg, old_msg, msglen + 1);
+ for (i = 0; i <= msglen; i++)
+ *(old_msg + i) = 0;
+ free(old_msg);
+ }
+ #endif
+ for (i = 0; i < suffix_len; i++)
{
- long mlen_ = mlen;
- char* M_ = (byte*)malloc(mlen += msglen);
- sha3_arraycopy(M, 0, M_, 0, mlen_);
- for (i = 0; i < mlen_; i++)
- *(M + i) = 0;
- free(M);
- M = M_;
- }
- #endif
- sha3_arraycopy(msg, 0, M, mptr, msglen);
- message = sha3_pad10star1(M, mptr + msglen, r, &len);
+ msg[msglen] |= (suffix[i] == '1') << bits;
+ if (bits == 8)
+ {
+ bits = 0;
+ msglen++;
+ }
+ }
+ if (bits)
+ msglen++;
+ }
+
+ if (mptr + msglen > mlen)
+ #ifndef WITH_WIPE
+ M = (byte*)realloc(M, mlen += msglen);
+ #else
+ {
+ long mlen_ = mlen;
+ char* M_ = (byte*)malloc(mlen += msglen);
+ sha3_arraycopy(M, 0, M_, 0, mlen_);
+ for (i = 0; i < mlen_; i++)
+ *(M + i) = 0;
+ free(M);
+ M = M_;
}
+ #endif
+ sha3_arraycopy(msg, 0, M, mptr, msglen);
+ message = sha3_pad10star1(M, mptr + msglen, r, bits, &len);
+
#ifdef WITH_WIPE
for (i = 0; i < mlen; i++)
*(M + i) = 0;
diff --git a/c/sha3.h b/c/sha3.h
index f984df5..b8c4b06 100644
--- a/c/sha3.h
+++ b/c/sha3.h
@@ -42,6 +42,26 @@
#endif
+/**
+ * Suffix the message when calculating the Keccak hash sum
+ */
+#define KECCAK_SUFFIX ""
+
+/**
+ * Suffix the message when calculating the SHA-3 hash sum
+ */
+#define SHA3_SUFFIX "01"
+
+/**
+ * Suffix the message when calculating the RawSHAKE hash sum
+ */
+#define RawSHAKE_SUFFIX "11"
+
+/**
+ * Suffix the message when calculating the SHAKE hash sum
+ */
+#define SHAKE_SUFFIX "1111"
+
/**
* Initialise Keccak sponge
@@ -73,10 +93,12 @@ extern void sha3_update(byte* restrict_ msg, long msglen);
*
* @param msg The rest of the message, may be {@code null}
* @param msglen The length of the partial message
+ * @param bits The number of bits at the end of the message not covered by `msglen`
+ * @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}
*/
-extern byte* sha3_digest(byte* restrict_ msg, long msglen, boolean withReturn);
+extern byte* sha3_digest(byte* restrict_ msg, long msglen, long bits, char* restrict_ suffix, boolean withReturn);
/**
diff --git a/c/sha3sum.c b/c/sha3sum.c
index a0b5351..662933b 100644
--- a/c/sha3sum.c
+++ b/c/sha3sum.c
@@ -61,7 +61,7 @@ SET set_new()
*
* @param set The set
*/
-void set_free(SET restrict set)
+void set_free(SET restrict_ set)
{
if (*(set + 0)) set_free((void**)*(set + 0));
if (*(set + 1)) set_free((void**)*(set + 1));
@@ -90,7 +90,7 @@ void set_free(SET restrict set)
* @param item The item
* @param n The length of the item
*/
-void set_add(SET restrict set, char* restrict item, long n)
+void set_add(SET restrict_ set, char* restrict_ item, long n)
{
long i, j;
void** at = set;
@@ -125,7 +125,7 @@ void set_add(SET restrict set, char* restrict item, long n)
* @param n The length of the item
* @return Whether the set contains the item
*/
-long set_contains(SET restrict set, byte* restrict item, long n)
+long set_contains(SET restrict_ set, byte* restrict_ item, long n)
{
long i;
void** at = set;
@@ -152,7 +152,7 @@ long set_contains(SET restrict set, byte* restrict item, long n)
* @param b Second comparand
* @return Whether the comparands are equal
*/
-long eq(char* restrict a, char* restrict b)
+long eq(char* restrict_ a, char* restrict_ b)
{
while (*a)
if (*a++ != *b++)
@@ -167,7 +167,7 @@ long eq(char* restrict a, char* restrict b)
* @param str String representation
* @return Native representation
*/
-long parseInt(char* restrict str)
+long parseInt(char* restrict_ str)
{
long rc = 0;
while (*str)
@@ -604,7 +604,7 @@ int main(int argc, char** argv)
sha3_update(chunk, n);
}
}
- bs = sha3_digest(null, 0, j == 1);
+ bs = sha3_digest(null, 0, 0, SHA3_SUFFIX, j == 1);
if (j > 2)
sha3_fastSqueeze(j - 2);
if (j > 1)
@@ -627,7 +627,7 @@ int main(int argc, char** argv)
{
byte* _bs = bs;
sha3_initialise(r, c, o);
- bs = sha3_digest(bs, bn, j == 1);
+ bs = sha3_digest(bs, bn, 0, SHA3_SUFFIX, j == 1);
if (j > 2)
sha3_fastSqueeze(j - 2);
if (j > 1)
@@ -670,7 +670,7 @@ int main(int argc, char** argv)
{
byte* _bs = bs;
sha3_initialise(r, c, o);
- bs = sha3_digest(bs, bn, j == 1);
+ bs = sha3_digest(bs, bn, 0, SHA3_SUFFIX, j == 1);
if (j > 2)
sha3_fastSqueeze(j - 2);
if (j > 1)
@@ -704,7 +704,7 @@ int main(int argc, char** argv)
{
byte* _bs = bs;
sha3_initialise(r, c, o);
- bs = sha3_digest(bs, bn, j == 1);
+ bs = sha3_digest(bs, bn, 0, SHA3_SUFFIX, j == 1);
if (j > 2)
sha3_fastSqueeze(j - 2);
if (j > 1)
diff --git a/java-c-jni/SHA3.c b/java-c-jni/SHA3.c
index eea5dbe..1735099 100644
--- a/java-c-jni/SHA3.c
+++ b/java-c-jni/SHA3.c
@@ -407,19 +407,22 @@ inline llong toLane64(byte* message, long msglen, long rr, long off)
* @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
* @param outlen The length of the padded message (out parameter)
* @return The message padded
*/
-inline byte* pad10star1(byte* msg, long len, long r, long* outlen)
+inline byte* pad10star1(byte* msg, long len, long r, long bits, long* outlen)
{
byte* message;
+ byte b;
+ long i, ll, nbrf, nrf;
- long nrf = (len <<= 3) >> 3;
- long nbrf = len & 7;
- long ll = len % r;
- long i;
+ len = ((len - (bits + 7) / 8) << 3) + bits;
+ nrf = len >> 3;
+ nbrf = len & 7;
+ ll = len % r;
- byte b = (byte)(nbrf == 0 ? 1 : ((msg[nrf] >> (8 - nbrf)) | (1 << nbrf)));
+ b = (byte)(nbrf == 0 ? 1 : (msg[nrf] | (1 << nbrf)));
if ((r - 8 <= ll) && (ll <= r - 2))
{
@@ -620,10 +623,13 @@ void update(byte* msg, long msglen)
*
* @param msg The rest of the message, may be {@code null}
* @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 suffix_len The length of the suffix
* @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}
*/
-byte* digest(byte* msg, long msglen, boolean withReturn)
+byte* digest(byte* msg, long msglen, long bits, int* suffix, long suffix_len, boolean withReturn)
{
byte* message;
byte* _msg;
@@ -634,20 +640,37 @@ byte* digest(byte* msg, long msglen, boolean withReturn)
long i, j = 0, ptr = 0, _;
long nnn;
- if ((msg == null) || (msglen == 0))
- message = pad10star1(M, mptr, r, &len);
- else
+ if (msg == null)
+ msglen = bits = 0;
+
+ msglen += bits >> 3;
+ if ((bits &= 7))
{
- if (mptr + msglen > mlen)
+ msg[msglen] &= (1 << bits) - 1;
+ msg = (byte*)realloc(msg, msglen + ((suffix_len + bits + 7) >> 3));
+ for (i = 0; i < suffix_len; i++)
{
- byte* buf = (byte*)malloc(mlen += msglen);
- arraycopy(M, 0, buf, 0, mptr);
- free(M);
- M = buf;
- }
- arraycopy(msg, 0, M, mptr, msglen);
- message = pad10star1(M, mptr + msglen, r, &len);
+ msg[msglen] |= suffix[i] << bits;
+ if (bits == 8)
+ {
+ bits = 0;
+ msglen++;
+ }
+ }
+ if (bits)
+ msglen++;
+ }
+
+ if (mptr + msglen > mlen)
+ {
+ byte* buf = (byte*)malloc(mlen += msglen);
+ arraycopy(M, 0, buf, 0, mptr);
+ free(M);
+ M = buf;
}
+ arraycopy(msg, 0, M, mptr, msglen);
+ message = pad10star1(M, mptr + msglen, r, bits, &len);
+
free(M);
M = null;
rc = (byte*)malloc((n + 7) >> 3);
@@ -814,16 +837,20 @@ JNIEXPORT void JNICALL Java_SHA3_update(JNIEnv* env, jclass class, jbyteArray ms
}
-JNIEXPORT jbyteArray JNICALL Java_SHA3_digest(JNIEnv* env, jclass class, jbyteArray msg, jint msglen, jboolean withReturn)
+JNIEXPORT jbyteArray JNICALL Java_SHA3_digest(JNIEnv* env, jclass class, jbyteArray msg, jint msglen, jint bits, jintArray suffix, jboolean withReturn)
{
jbyte* rcn;
jbyteArray rcj = null;
+ int* suffix_elems = (int*)((*env)->GetIntArrayElements(env, suffix, 0));
+ long suffix_len = (long)((*env)->GetArrayLength(env, suffix));
+
(void) class;
if ((msg != null) && (msglen != 0))
- rcn = (jbyte*)digest((byte*)((*env)->GetByteArrayElements(env, msg, 0)), msglen, withReturn);
+ rcn = (jbyte*)digest((byte*)((*env)->GetByteArrayElements(env, msg, 0)), msglen,
+ bits, suffix_elems, suffix_len, withReturn);
else
- rcn = (jbyte*)digest(null, 0, withReturn);
+ rcn = (jbyte*)digest(null, 0, 0, suffix_elems, suffix_len, withReturn);
if (withReturn)
{
rcj = (*env)->NewByteArray(env, (n + 7) >> 3);
diff --git a/java-c-jni/SHA3.java b/java-c-jni/SHA3.java
index 1a4067b..4be013e 100644
--- a/java-c-jni/SHA3.java
+++ b/java-c-jni/SHA3.java
@@ -28,6 +28,28 @@ import java.util.*;
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";
+
+
+
+ /**
* Hidden constructor
*/
private SHA3()
@@ -91,19 +113,44 @@ 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
*
- * @paran withReturn Whether to return the hash instead of just do a quick squeeze phrase and return {@code null}
+ * @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);
+ }
+
+
+ /**
+ * Squeeze the Keccak sponge
+ *
+ * @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)
{
- 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);
}
@@ -115,7 +162,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);
}
@@ -123,12 +183,26 @@ 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)
{
- 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);
}
@@ -136,12 +210,119 @@ 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);
+ }
+
+
+ /**
+ * 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 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
+ * @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[] suffix_ = new int[suffix.length()];
+ for (int i = 0, n = suffix_.length; i < n; i++)
+ suffix_[i] = suffix.charAt(i) == '1' ? 1 : 0;
+
+ return digest(msg, msglen, bits, suffix_, withReturn);
}
@@ -150,10 +331,12 @@ public class SHA3
*
* @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 static native byte[] digest(byte[] msg, int msglen, boolean withReturn);
+ public static native byte[] digest(byte[] msg, int msglen, int bits, int[] suffix, boolean withReturn);
/**
diff --git a/java-c-jni/sha3sum.java b/java-c-jni/sha3sum.java
index a7abd07..c3c63a5 100644
--- a/java-c-jni/sha3sum.java
+++ b/java-c-jni/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)
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)
diff --git a/python2/sha3.py b/python2/sha3.py
index 316930d..a71f750 100644
--- a/python2/sha3.py
+++ b/python2/sha3.py
@@ -27,6 +27,27 @@ class SHA3:
'''
+ KECCAK_SUFFIX = ''
+ '''
+ :str Suffix the message when calculating the Keccak hash sum
+ '''
+
+ SHA3_SUFFIX = '01'
+ '''
+ :str Suffix the message when calculating the SHA-3 hash sum
+ '''
+
+ RawSHAKE_SUFFIX = '11'
+ '''
+ :str Suffix the message when calculating the RawSHAKE hash sum
+ '''
+
+ SHAKE_SUFFIX = '1111'
+ '''
+ :str Suffix the message when calculating the SHAKE hash sum
+ '''
+
+
def __init__(self):
'''
Constructor
@@ -319,21 +340,22 @@ class SHA3:
((message[off]) if (off < n) else 0)
- def pad10star1(self, msg, r):
+ def pad10star1(self, msg, r, bits):
'''
pad 10*1
- @param msg:bytes The message to pad
- @param r:int The bitrate
- @return :bytes The message padded
+ @param msg:bytes The message to pad
+ @param r:int The bitrate
+ @param bits:int The number of bits in the end of the message that does not make a whole byte
+ @return :bytes The message padded
'''
- nnn = len(msg) << 3
+ nnn = ((len(msg) - (bits + 7) // 8) << 3) + bits
nrf = nnn >> 3
nbrf = nnn & 7
ll = nnn % r
- bbbb = 1 if nbrf == 0 else ((msg[nrf] >> (8 - nbrf)) | (1 << nbrf))
+ bbbb = 1 if nbrf == 0 else (msg[nrf] | (1 << nbrf))
message = None
if ((r - 8 <= ll) and (ll <= r - 2)):
@@ -374,7 +396,7 @@ class SHA3:
Absorb the more of the message message to the Keccak sponge
@param msg:bytes The partial message
- @param msglen:int The length of the partial message
+ @param msglen:int The length of the partial message in whole bytes
'''
if msglen is not None:
msg = msg[:msglen]
@@ -451,24 +473,36 @@ class SHA3:
message = message[rr:]
- def digest(self, msg = None, msglen = None, withReturn = None):
+ def digest(self, msg = None, msglen = None, bits = 0, suffix = SHA3_SUFFIX, withReturn = None):
'''
Absorb the last part of the message and squeeze the Keccak sponge
@param msg:bytes? The rest of the message
- @param msglen:int The length of the partial message
+ @param msglen:int The length of the partial message in whole bytes
+ @param bits:int The number of bits at the end of the message not covered by `msglen`
+ @param suffix:str The suffix concatenate to the 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 (msg is not None) and isinstance(msg, bool):
- (msg, withReturn) = (withReturn, msg)
- elif (msglen is not None) and isinstance(msglen, bool):
- (msglen, withReturn) = (withReturn, msglen)
if msg is None:
- msg = []
- elif msglen is not None:
- msg = msg[:msglen]
- message = self.pad10star1(self.M + msg, self.r)
+ msg, last_byte = [], 0
+ bits = 0
+ else:
+ msg, last_byte = msg[:msglen + bits // 8], (0 if bits % 8 == 0 else msg[msglen])
+ bits %= 8
+ last_byte &= (1 << bits) - 1
+ msg_end = []
+ for bit in suffix:
+ last_byte |= int(bit) << bits
+ bits += 1
+ if bits == 8:
+ msg_end.append(last_byte)
+ last_byte = 0
+ bits = 0
+ if not bits == 0:
+ msg_end.append(last_byte)
+ msg += msg_end
+ message = self.pad10star1(self.M + msg, self.r, bits)
self.M = None
nnn = len(message)
diff --git a/python2/sha3sum.py b/python2/sha3sum.py
index f3131d8..17b083c 100755
--- a/python2/sha3sum.py
+++ b/python2/sha3sum.py
@@ -317,7 +317,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
b = (b & 15) + (0 if b <= '9' else 0)
chunk[_] = a | b
sha.update(chunk, n)
- bs = sha.digest(j == 1)
+ bs = sha.digest(withReturn = j == 1)
if j > 2:
sha.fastSqueeze(j - 2)
if j > 1:
@@ -329,7 +329,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
if multi == 0:
for _ in range(i - 1):
sha.initialise(r, c, o)
- bs = sha.digest(bs, j == 1)
+ bs = sha.digest(bs, withReturn = j == 1)
if j > 2:
sha.fastSqueeze(j - 2)
if j > 1:
@@ -390,7 +390,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
printerr('\033[01;31mLoop found\033[00m')
flush()
except Exception as err:
- printerr(cmd + ': connot read file: ' + fn + ': ' + str(err))
+ printerr(cmd + ': cannot read file: ' + fn + ': ' + str(err))
fail = True
flush()
if fail:
diff --git a/python3/sha3.py b/python3/sha3.py
index dc62630..e1c10fa 100644
--- a/python3/sha3.py
+++ b/python3/sha3.py
@@ -27,6 +27,27 @@ class SHA3:
'''
+ KECCAK_SUFFIX = ''
+ '''
+ :str Suffix the message when calculating the Keccak hash sum
+ '''
+
+ SHA3_SUFFIX = '01'
+ '''
+ :str Suffix the message when calculating the SHA-3 hash sum
+ '''
+
+ RawSHAKE_SUFFIX = '11'
+ '''
+ :str Suffix the message when calculating the RawSHAKE hash sum
+ '''
+
+ SHAKE_SUFFIX = '1111'
+ '''
+ :str Suffix the message when calculating the SHAKE hash sum
+ '''
+
+
def __init__(self):
'''
Constructor
@@ -312,21 +333,22 @@ class SHA3:
return ((message[off + 7] << 56) if (off + 7 < n) else 0) | ((message[off + 6] << 48) if (off + 6 < n) else 0) | ((message[off + 5] << 40) if (off + 5 < n) else 0) | ((message[off + 4] << 32) if (off + 4 < n) else 0) | ((message[off + 3] << 24) if (off + 3 < n) else 0) | ((message[off + 2] << 16) if (off + 2 < n) else 0) | ((message[off + 1] << 8) if (off + 1 < n) else 0) | ((message[off]) if (off < n) else 0)
- def pad10star1(self, msg, r):
+ def pad10star1(self, msg, r, bits):
'''
pad 10*1
- @param msg:bytes The message to pad
- @param r:int The bitrate
- @return :bytes The message padded
+ @param msg:bytes The message to pad
+ @param r:int The bitrate
+ @param bits:int The number of bits in the end of the message that does not make a whole byte
+ @return :bytes The message padded
'''
- nnn = len(msg) << 3
+ nnn = ((len(msg) - (bits + 7) // 8) << 3) + bits
nrf = nnn >> 3
nbrf = nnn & 7
ll = nnn % r
- bbbb = 1 if nbrf == 0 else ((msg[nrf] >> (8 - nbrf)) | (1 << nbrf))
+ bbbb = 1 if nbrf == 0 else (msg[nrf] | (1 << nbrf))
message = None
if ((r - 8 <= ll) and (ll <= r - 2)):
@@ -367,7 +389,7 @@ class SHA3:
Absorb the more of the message message to the Keccak sponge
@param msg:bytes The partial message
- @param msglen:int The length of the partial message
+ @param msglen:int The length of the partial message in whole bytes
'''
if msglen is not None:
msg = msg[:msglen]
@@ -444,24 +466,36 @@ class SHA3:
message = message[rr:]
- def digest(self, msg = None, msglen = None, withReturn = None):
+ def digest(self, msg = None, msglen = None, bits = 0, suffix = SHA3_SUFFIX, withReturn = False):
'''
Absorb the last part of the message and squeeze the Keccak sponge
@param msg:bytes? The rest of the message
- @param msglen:int The length of the partial message
+ @param msglen:int The length of the partial message in whole bytes
+ @param bits:int The number of bits at the end of the message not covered by `msglen`
+ @param suffix:str The suffix concatenate to the 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 (msg is not None) and isinstance(msg, bool):
- (msg, withReturn) = (withReturn, msg)
- elif (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 = self.pad10star1(self.M + msg, self.r)
+ msg, last_byte = bytes([]), 0
+ bits = 0
+ else:
+ msg, last_byte = msg[:msglen + bits // 8], (0 if bits % 8 == 0 else msg[msglen])
+ bits %= 8
+ last_byte &= (1 << bits) - 1
+ msg_end = []
+ for bit in suffix:
+ last_byte |= int(bit) << bits
+ bits += 1
+ if bits == 8:
+ msg_end.append(last_byte)
+ last_byte = 0
+ bits = 0
+ if not bits == 0:
+ msg_end.append(last_byte)
+ msg += bytes(msg_end)
+ message = self.pad10star1(self.M + msg, self.r, bits)
self.M = None
nnn = len(message)
diff --git a/python3/sha3sum.py b/python3/sha3sum.py
index 77d66e5..f0957b2 100755
--- a/python3/sha3sum.py
+++ b/python3/sha3sum.py
@@ -305,7 +305,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
b = (b & 15) + (0 if b <= '9' else 0)
chunk[_] = a | b
sha.update(bytes(chunk), n)
- bs = sha.digest(j == 1)
+ bs = sha.digest(withReturn = j == 1)
if j > 2:
sha.fastSqueeze(j - 2)
if j > 1:
@@ -317,7 +317,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
if multi == 0:
for _ in range(i - 1):
sha.initialise(r, c, o)
- bs = sha.digest(bs, j == 1)
+ bs = sha.digest(bs, withReturn = j == 1)
if j > 2:
sha.fastSqueeze(j - 2)
if j > 1:
@@ -378,7 +378,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
printerr('\033[01;31mLoop found\033[00m')
sys.stdout.buffer.flush()
except Exception as err:
- printerr(cmd + ': connot read file: ' + fn + ': ' + str(err))
+ printerr(cmd + ': cannot read file: ' + fn + ': ' + str(err))
fail = True
sys.stdout.buffer.flush()
if fail: