236 lines
8.0 KiB
Java
236 lines
8.0 KiB
Java
![]() |
package com.cypherx.xauth;
|
||
|
|
||
|
import java.util.Arrays;
|
||
|
|
||
|
class Whirlpool {
|
||
|
public static final int DIGESTBITS = 512;
|
||
|
public static final int DIGESTBYTES = DIGESTBITS >>> 3;
|
||
|
protected static final int R = 10;
|
||
|
private static final String sbox =
|
||
|
"\u1823\uc6E8\u87B8\u014F\u36A6\ud2F5\u796F\u9152" +
|
||
|
"\u60Bc\u9B8E\uA30c\u7B35\u1dE0\ud7c2\u2E4B\uFE57" +
|
||
|
"\u1577\u37E5\u9FF0\u4AdA\u58c9\u290A\uB1A0\u6B85" +
|
||
|
"\uBd5d\u10F4\ucB3E\u0567\uE427\u418B\uA77d\u95d8" +
|
||
|
"\uFBEE\u7c66\udd17\u479E\ucA2d\uBF07\uAd5A\u8333" +
|
||
|
"\u6302\uAA71\uc819\u49d9\uF2E3\u5B88\u9A26\u32B0" +
|
||
|
"\uE90F\ud580\uBEcd\u3448\uFF7A\u905F\u2068\u1AAE" +
|
||
|
"\uB454\u9322\u64F1\u7312\u4008\uc3Ec\udBA1\u8d3d" +
|
||
|
"\u9700\ucF2B\u7682\ud61B\uB5AF\u6A50\u45F3\u30EF" +
|
||
|
"\u3F55\uA2EA\u65BA\u2Fc0\udE1c\uFd4d\u9275\u068A" +
|
||
|
"\uB2E6\u0E1F\u62d4\uA896\uF9c5\u2559\u8472\u394c" +
|
||
|
"\u5E78\u388c\ud1A5\uE261\uB321\u9c1E\u43c7\uFc04" +
|
||
|
"\u5199\u6d0d\uFAdF\u7E24\u3BAB\ucE11\u8F4E\uB7EB" +
|
||
|
"\u3c81\u94F7\uB913\u2cd3\uE76E\uc403\u5644\u7FA9" +
|
||
|
"\u2ABB\uc153\udc0B\u9d6c\u3174\uF646\uAc89\u14E1" +
|
||
|
"\u163A\u6909\u70B6\ud0Ed\ucc42\u98A4\u285c\uF886";
|
||
|
|
||
|
private static long[][] C = new long[8][256];
|
||
|
private static long[] rc = new long[R + 1];
|
||
|
|
||
|
static {
|
||
|
for (int x = 0; x < 256; x++) {
|
||
|
char c = sbox.charAt(x/2);
|
||
|
long v1 = ((x & 1) == 0) ? c >>> 8 : c & 0xff;
|
||
|
long v2 = v1 << 1;
|
||
|
if (v2 >= 0x100L) {
|
||
|
v2 ^= 0x11dL;
|
||
|
}
|
||
|
long v4 = v2 << 1;
|
||
|
if (v4 >= 0x100L) {
|
||
|
v4 ^= 0x11dL;
|
||
|
}
|
||
|
long v5 = v4 ^ v1;
|
||
|
long v8 = v4 << 1;
|
||
|
if (v8 >= 0x100L) {
|
||
|
v8 ^= 0x11dL;
|
||
|
}
|
||
|
long v9 = v8 ^ v1;
|
||
|
|
||
|
C[0][x] =
|
||
|
(v1 << 56) | (v1 << 48) | (v4 << 40) | (v1 << 32) |
|
||
|
(v8 << 24) | (v5 << 16) | (v2 << 8) | (v9 );
|
||
|
|
||
|
for (int t = 1; t < 8; t++) {
|
||
|
C[t][x] = (C[t - 1][x] >>> 8) | ((C[t - 1][x] << 56));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
rc[0] = 0L;
|
||
|
for (int r = 1; r <= R; r++) {
|
||
|
int i = 8*(r - 1);
|
||
|
rc[r] =
|
||
|
(C[0][i ] & 0xff00000000000000L) ^
|
||
|
(C[1][i + 1] & 0x00ff000000000000L) ^
|
||
|
(C[2][i + 2] & 0x0000ff0000000000L) ^
|
||
|
(C[3][i + 3] & 0x000000ff00000000L) ^
|
||
|
(C[4][i + 4] & 0x00000000ff000000L) ^
|
||
|
(C[5][i + 5] & 0x0000000000ff0000L) ^
|
||
|
(C[6][i + 6] & 0x000000000000ff00L) ^
|
||
|
(C[7][i + 7] & 0x00000000000000ffL);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected byte[] bitLength = new byte[32];
|
||
|
protected byte[] buffer = new byte[64];
|
||
|
protected int bufferBits = 0;
|
||
|
protected int bufferPos = 0;
|
||
|
protected long[] hash = new long[8];
|
||
|
protected long[] K = new long[8];
|
||
|
protected long[] L = new long[8];
|
||
|
protected long[] block = new long[8];
|
||
|
protected long[] state = new long[8];
|
||
|
|
||
|
public Whirlpool() {}
|
||
|
|
||
|
protected void processBuffer() {
|
||
|
for (int i = 0, j = 0; i < 8; i++, j += 8) {
|
||
|
block[i] =
|
||
|
(((long)buffer[j ] ) << 56) ^
|
||
|
(((long)buffer[j + 1] & 0xffL) << 48) ^
|
||
|
(((long)buffer[j + 2] & 0xffL) << 40) ^
|
||
|
(((long)buffer[j + 3] & 0xffL) << 32) ^
|
||
|
(((long)buffer[j + 4] & 0xffL) << 24) ^
|
||
|
(((long)buffer[j + 5] & 0xffL) << 16) ^
|
||
|
(((long)buffer[j + 6] & 0xffL) << 8) ^
|
||
|
(((long)buffer[j + 7] & 0xffL) );
|
||
|
}
|
||
|
|
||
|
for (int i = 0; i < 8; i++) {
|
||
|
state[i] = block[i] ^ (K[i] = hash[i]);
|
||
|
}
|
||
|
|
||
|
for (int r = 1; r <= R; r++) {
|
||
|
for (int i = 0; i < 8; i++) {
|
||
|
L[i] = 0L;
|
||
|
for (int t = 0, s = 56; t < 8; t++, s -= 8) {
|
||
|
L[i] ^= C[t][(int)(K[(i - t) & 7] >>> s) & 0xff];
|
||
|
}
|
||
|
}
|
||
|
for (int i = 0; i < 8; i++) {
|
||
|
K[i] = L[i];
|
||
|
}
|
||
|
K[0] ^= rc[r];
|
||
|
|
||
|
for (int i = 0; i < 8; i++) {
|
||
|
L[i] = K[i];
|
||
|
for (int t = 0, s = 56; t < 8; t++, s -= 8) {
|
||
|
L[i] ^= C[t][(int)(state[(i - t) & 7] >>> s) & 0xff];
|
||
|
}
|
||
|
}
|
||
|
for (int i = 0; i < 8; i++) {
|
||
|
state[i] = L[i];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for (int i = 0; i < 8; i++) {
|
||
|
hash[i] ^= state[i] ^ block[i];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void NESSIEinit() {
|
||
|
Arrays.fill(bitLength, (byte)0);
|
||
|
bufferBits = bufferPos = 0;
|
||
|
buffer[0] = 0;
|
||
|
Arrays.fill(hash, 0L);
|
||
|
}
|
||
|
|
||
|
public void NESSIEadd(byte[] source, long sourceBits) {
|
||
|
int sourcePos = 0;
|
||
|
int sourceGap = (8 - ((int)sourceBits & 7)) & 7;
|
||
|
int bufferRem = bufferBits & 7;
|
||
|
int b;
|
||
|
long value = sourceBits;
|
||
|
for (int i = 31, carry = 0; i >= 0; i--) {
|
||
|
carry += (bitLength[i] & 0xff) + ((int)value & 0xff);
|
||
|
bitLength[i] = (byte)carry;
|
||
|
carry >>>= 8;
|
||
|
value >>>= 8;
|
||
|
}
|
||
|
|
||
|
while (sourceBits > 8) {
|
||
|
b = ((source[sourcePos] << sourceGap) & 0xff) |
|
||
|
((source[sourcePos + 1] & 0xff) >>> (8 - sourceGap));
|
||
|
if (b < 0 || b >= 256) {
|
||
|
throw new RuntimeException("LOGIC ERROR");
|
||
|
}
|
||
|
buffer[bufferPos++] |= b >>> bufferRem;
|
||
|
bufferBits += 8 - bufferRem;
|
||
|
if (bufferBits == 512) {
|
||
|
processBuffer();
|
||
|
bufferBits = bufferPos = 0;
|
||
|
}
|
||
|
buffer[bufferPos] = (byte)((b << (8 - bufferRem)) & 0xff);
|
||
|
bufferBits += bufferRem;
|
||
|
sourceBits -= 8;
|
||
|
sourcePos++;
|
||
|
}
|
||
|
if (sourceBits > 0) {
|
||
|
b = (source[sourcePos] << sourceGap) & 0xff;
|
||
|
buffer[bufferPos] |= b >>> bufferRem;
|
||
|
} else {
|
||
|
b = 0;
|
||
|
}
|
||
|
if (bufferRem + sourceBits < 8) {
|
||
|
bufferBits += sourceBits;
|
||
|
} else {
|
||
|
bufferPos++;
|
||
|
bufferBits += 8 - bufferRem;
|
||
|
sourceBits -= 8 - bufferRem;
|
||
|
if (bufferBits == 512) {
|
||
|
processBuffer();
|
||
|
bufferBits = bufferPos = 0;
|
||
|
}
|
||
|
buffer[bufferPos] = (byte)((b << (8 - bufferRem)) & 0xff);
|
||
|
bufferBits += (int)sourceBits;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void NESSIEfinalize(byte[] digest) {
|
||
|
buffer[bufferPos] |= 0x80 >>> (bufferBits & 7);
|
||
|
bufferPos++;
|
||
|
if (bufferPos > 32) {
|
||
|
while (bufferPos < 64) {
|
||
|
buffer[bufferPos++] = 0;
|
||
|
}
|
||
|
processBuffer();
|
||
|
bufferPos = 0;
|
||
|
}
|
||
|
while (bufferPos < 32) {
|
||
|
buffer[bufferPos++] = 0;
|
||
|
}
|
||
|
System.arraycopy(bitLength, 0, buffer, 32, 32);
|
||
|
processBuffer();
|
||
|
for (int i = 0, j = 0; i < 8; i++, j += 8) {
|
||
|
long h = hash[i];
|
||
|
digest[j ] = (byte)(h >>> 56);
|
||
|
digest[j + 1] = (byte)(h >>> 48);
|
||
|
digest[j + 2] = (byte)(h >>> 40);
|
||
|
digest[j + 3] = (byte)(h >>> 32);
|
||
|
digest[j + 4] = (byte)(h >>> 24);
|
||
|
digest[j + 5] = (byte)(h >>> 16);
|
||
|
digest[j + 6] = (byte)(h >>> 8);
|
||
|
digest[j + 7] = (byte)(h );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void NESSIEadd(String source) {
|
||
|
if (source.length() > 0) {
|
||
|
byte[] data = new byte[source.length()];
|
||
|
for (int i = 0; i < source.length(); i++) {
|
||
|
data[i] = (byte)source.charAt(i);
|
||
|
}
|
||
|
NESSIEadd(data, 8*data.length);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static String display(byte[] array) {
|
||
|
char[] val = new char[2*array.length];
|
||
|
String hex = "0123456789ABCDEF";
|
||
|
for (int i = 0; i < array.length; i++) {
|
||
|
int b = array[i] & 0xff;
|
||
|
val[2*i] = hex.charAt(b >>> 4);
|
||
|
val[2*i + 1] = hex.charAt(b & 15);
|
||
|
}
|
||
|
return String.valueOf(val);
|
||
|
}
|
||
|
}
|