/******************************************************************************
* Copyright © 2013-2016 The Nxt Core Developers. *
* *
* See the AUTHORS.txt, DEVELOPER-AGREEMENT.txt and LICENSE.txt files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* Nxt software, including this file, may be copied, modified, propagated, *
* or distributed except according to the terms contained in the LICENSE.txt *
* file. *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
package nxt.crypto;
public final class KNV25 {
private static final long[] constants = {
1L, 32898L, -9223372036854742902L, -9223372034707259392L, 32907L,
2147483649L, -9223372034707259263L, -9223372036854743031L, 138L, 136L,
2147516425L, 2147483658L, 2147516555L, -9223372036854775669L, -9223372036854742903L,
-9223372036854743037L, -9223372036854743038L, -9223372036854775680L, 32778L, -9223372034707292150L,
-9223372034707259263L, -9223372036854742912L, 2147483649L, -9223372034707259384L, 1L
};
@SuppressWarnings("ShiftOutOfRange")
public static byte[] hash(final byte input[]) {
int inputOffset = 0;
int inputLength = input.length;
if (inputLength % 8 != 0) {
throw new IllegalArgumentException(String.format("input length %d must be a multiple of 8", inputLength));
}
byte[] output = new byte[32];
long[] state = new long[25];
while (inputOffset <= inputLength) {
int i = 0;
while (inputOffset < inputLength && i < 17) {
state[i++] ^= ((long)(input[inputOffset++] & 0xFF)) | (((long)(input[inputOffset++] & 0xFF)) << 8) | (((long)(input[inputOffset++] & 0xFF)) << 16) | (((long)(input[inputOffset++] & 0xFF)) << 24) | (((long)(input[inputOffset++] & 0xFF)) << 32) | (((long)(input[inputOffset++] & 0xFF)) << 40) | (((long)(input[inputOffset++] & 0xFF)) << 48) | (((long)(input[inputOffset++] & 0xFF)) << 56);
}
if (inputOffset == inputLength && i < 17) {
state[i] ^= 1;
state[16] ^= -9223372036854775808L;
inputOffset++;
}
long state0 = state[0], state1 = state[1], state2 = state[2], state3 = state[3], state4 = state[4], state5 = state[5], state6 = state[6], state7 = state[7], state8 = state[8], state9 = state[9], state10 = state[10], state11 = state[11], state12 = state[12], state13 = state[13], state14 = state[14], state15 = state[15], state16 = state[16], state17 = state[17], state18 = state[18], state19 = state[19], state20 = state[20], state21 = state[21], state22 = state[22], state23 = state[23], state24 = state[24];
for (i = 0; i < 25; ) {
long t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18, t19;
t12 = state1 ^ (t3 = (t1 = state0 ^ state5 ^ state10 ^ state15 ^ state20) ^ (((t2 = state2 ^ state7 ^ state12 ^ state17 ^ state22) << 1) | (t2 >>> -1)));
t13 = state2 ^ (t6 = (t4 = state1 ^ state6 ^ state11 ^ state16 ^ state21) ^ (((t5 = state3 ^ state8 ^ state13 ^ state18 ^ state23) << 1) | (t5 >>> -1)));
state0 = (t9 = state0 ^ (t8 = ((t4 << 1) | (t4 >>> -1)) ^ (t7 = state4 ^ state9 ^ state14 ^ state19 ^ state24))) ^ ((~(t16 = ((t16 = state6 ^ t3) << 44) | (t16 >>> -44))) & (state2 = ((state2 = state12 ^ t6) << 43) | (state2 >>> -43))) ^ constants[i++];
t14 = state3 ^ (t10 = ((t7 << 1) | (t7 >>> -1)) ^ t2);
state1 = t16 ^ ((~state2) & (state3 = ((state3 = state18 ^ t10) << 21) | (state3 >>> -21)));
t15 = state4 ^ (t11 = ((t1 << 1) | (t1 >>> -1)) ^ t5);
state2 ^= (~state3) & (state4 = ((state4 = state24 ^ t11) << 14) | (state4 >>> -14));
state3 ^= (~state4) & t9;
state4 ^= (~t9) & t16;
t16 = state5 ^ t8;
t17 = state7 ^ t6;
state5 = (t14 = (t14 << 28) | (t14 >>> -28)) ^ ((~(t19 = ((t19 = state9 ^ t11) << 20) | (t19 >>> -20))) & (state7 = ((state7 = state10 ^ t8) << 3) | (state7 >>> -3)));
t18 = state8 ^ t10;
state6 = t19 ^ ((~state7) & (state8 = ((state8 = state16 ^ t3) << 45) | (state8 >>> -45)));
state7 ^= (~state8) & (state9 = ((state9 = state22 ^ t6) << 61) | (state9 >>> -61));
state8 ^= (~state9) & t14;
state9 ^= (~t14) & t19;
t19 = state11 ^ t3;
state10 = (t12 = (t12 << 1) | (t12 >>> -1)) ^ ((~(t17 = (t17 << 6) | (t17 >>> -6))) & (state12 = ((state12 = state13 ^ t10) << 25) | (state12 >>> -25)));
state11 = t17 ^ ((~state12) & (state13 = ((state13 = state19 ^ t11) << 8) | (state13 >>> -8)));
t14 = state14 ^ t11;
state12 ^= (~state13) & (state14 = ((state14 = state20 ^ t8) << 18) | (state14 >>> -18));
state13 ^= (~state14) & t12;
state14 ^= (~t12) & t17;
t12 = state15 ^ t8;
t17 = state17 ^ t6;
state15 = (t15 = (t15 << 27) | (t15 >>> -27)) ^ ((~(t16 = (t16 << 36) | (t16 >>> -36))) & (state17 = (t19 << 10) | (t19 >>> -10)));
state16 = t16 ^ ((~state17) & (state18 = (t17 << 15) | (t17 >>> -15)));
state17 ^= (~state18) & (state19 = ((state19 = state23 ^ t10) << 56) | (state19 >>> -56));
state18 ^= (~state19) & t15;
state19 ^= (~t15) & t16;
t19 = state21 ^ t3;
state20 = (t13 = (t13 << 62) | (t13 >>> -62)) ^ ((~(t18 = (t18 << 55) | (t18 >>> -55))) & (state22 = (t14 << 39) | (t14 >>> -39)));
state21 = t18 ^ ((~state22) & (state23 = (t12 << 41) | (t12 >>> -41)));
state22 ^= (~state23) & (state24 = (t19 << 2) | (t19 >>> -2));
state23 ^= (~state24) & t13;
state24 ^= (~t13) & t18;
}
state[0] = state0;
state[1] = state1;
state[2] = state2;
state[3] = state3;
state[4] = state4;
state[5] = state5;
state[6] = state6;
state[7] = state7;
state[8] = state8;
state[9] = state9;
state[10] = state10;
state[11] = state11;
state[12] = state12;
state[13] = state13;
state[14] = state14;
state[15] = state15;
state[16] = state16;
state[17] = state17;
state[18] = state18;
state[19] = state19;
state[20] = state20;
state[21] = state21;
state[22] = state22;
state[23] = state23;
state[24] = state24;
}
for (int i = 0; i < 32; i++) {
output[i] = (byte)(state[i >> 3] >> ((i & 7) << 3));
}
return output;
}
}