diff options
-rw-r--r-- | c/sha3.c | 88 | ||||
-rw-r--r-- | c/sha3.h | 24 | ||||
-rw-r--r-- | c/sha3sum.c | 18 | ||||
-rw-r--r-- | java-c-jni/SHA3.c | 69 | ||||
-rw-r--r-- | java-c-jni/SHA3.java | 201 | ||||
-rw-r--r-- | java-c-jni/sha3sum.java | 14 | ||||
-rw-r--r-- | java/ConcurrentSHA3.java | 238 | ||||
-rw-r--r-- | java/SHA3.java | 238 | ||||
-rw-r--r-- | java/sha3sum.java | 14 | ||||
-rw-r--r-- | python2/sha3.py | 68 | ||||
-rwxr-xr-x | python2/sha3sum.py | 6 | ||||
-rw-r--r-- | python3/sha3.py | 68 | ||||
-rwxr-xr-x | python3/sha3sum.py | 6 |
13 files changed, 888 insertions, 164 deletions
@@ -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; @@ -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: |