forked from Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
455 lines
11 KiB
455 lines
11 KiB
// $Id: JHCore.java 255 2011-06-07 19:50:20Z tp $ |
|
|
|
package fr.cryptohash; |
|
|
|
/** |
|
* This class implements the core operations for the JH digest |
|
* algorithm. |
|
* |
|
* <pre> |
|
* ==========================(LICENSE BEGIN)============================ |
|
* |
|
* Copyright (c) 2007-2010 Projet RNRT SAPHIR |
|
* |
|
* Permission is hereby granted, free of charge, to any person obtaining |
|
* a copy of this software and associated documentation files (the |
|
* "Software"), to deal in the Software without restriction, including |
|
* without limitation the rights to use, copy, modify, merge, publish, |
|
* distribute, sublicense, and/or sell copies of the Software, and to |
|
* permit persons to whom the Software is furnished to do so, subject to |
|
* the following conditions: |
|
* |
|
* The above copyright notice and this permission notice shall be |
|
* included in all copies or substantial portions of the Software. |
|
* |
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
|
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY |
|
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
|
* |
|
* ===========================(LICENSE END)============================= |
|
* </pre> |
|
* |
|
* @version $Revision: 255 $ |
|
* @author Thomas Pornin <[email protected]> |
|
*/ |
|
|
|
abstract class JHCore extends DigestEngine { |
|
|
|
JHCore() |
|
{ |
|
} |
|
|
|
private long[] h; |
|
private byte[] tmpBuf; |
|
|
|
private static final long[] C = { |
|
0x72d5dea2df15f867L, 0x7b84150ab7231557L, |
|
0x81abd6904d5a87f6L, 0x4e9f4fc5c3d12b40L, |
|
0xea983ae05c45fa9cL, 0x03c5d29966b2999aL, |
|
0x660296b4f2bb538aL, 0xb556141a88dba231L, |
|
0x03a35a5c9a190edbL, 0x403fb20a87c14410L, |
|
0x1c051980849e951dL, 0x6f33ebad5ee7cddcL, |
|
0x10ba139202bf6b41L, 0xdc786515f7bb27d0L, |
|
0x0a2c813937aa7850L, 0x3f1abfd2410091d3L, |
|
0x422d5a0df6cc7e90L, 0xdd629f9c92c097ceL, |
|
0x185ca70bc72b44acL, 0xd1df65d663c6fc23L, |
|
0x976e6c039ee0b81aL, 0x2105457e446ceca8L, |
|
0xeef103bb5d8e61faL, 0xfd9697b294838197L, |
|
0x4a8e8537db03302fL, 0x2a678d2dfb9f6a95L, |
|
0x8afe7381f8b8696cL, 0x8ac77246c07f4214L, |
|
0xc5f4158fbdc75ec4L, 0x75446fa78f11bb80L, |
|
0x52de75b7aee488bcL, 0x82b8001e98a6a3f4L, |
|
0x8ef48f33a9a36315L, 0xaa5f5624d5b7f989L, |
|
0xb6f1ed207c5ae0fdL, 0x36cae95a06422c36L, |
|
0xce2935434efe983dL, 0x533af974739a4ba7L, |
|
0xd0f51f596f4e8186L, 0x0e9dad81afd85a9fL, |
|
0xa7050667ee34626aL, 0x8b0b28be6eb91727L, |
|
0x47740726c680103fL, 0xe0a07e6fc67e487bL, |
|
0x0d550aa54af8a4c0L, 0x91e3e79f978ef19eL, |
|
0x8676728150608dd4L, 0x7e9e5a41f3e5b062L, |
|
0xfc9f1fec4054207aL, 0xe3e41a00cef4c984L, |
|
0x4fd794f59dfa95d8L, 0x552e7e1124c354a5L, |
|
0x5bdf7228bdfe6e28L, 0x78f57fe20fa5c4b2L, |
|
0x05897cefee49d32eL, 0x447e9385eb28597fL, |
|
0x705f6937b324314aL, 0x5e8628f11dd6e465L, |
|
0xc71b770451b920e7L, 0x74fe43e823d4878aL, |
|
0x7d29e8a3927694f2L, 0xddcb7a099b30d9c1L, |
|
0x1d1b30fb5bdc1be0L, 0xda24494ff29c82bfL, |
|
0xa4e7ba31b470bfffL, 0x0d324405def8bc48L, |
|
0x3baefc3253bbd339L, 0x459fc3c1e0298ba0L, |
|
0xe5c905fdf7ae090fL, 0x947034124290f134L, |
|
0xa271b701e344ed95L, 0xe93b8e364f2f984aL, |
|
0x88401d63a06cf615L, 0x47c1444b8752afffL, |
|
0x7ebb4af1e20ac630L, 0x4670b6c5cc6e8ce6L, |
|
0xa4d5a456bd4fca00L, 0xda9d844bc83e18aeL, |
|
0x7357ce453064d1adL, 0xe8a6ce68145c2567L, |
|
0xa3da8cf2cb0ee116L, 0x33e906589a94999aL, |
|
0x1f60b220c26f847bL, 0xd1ceac7fa0d18518L, |
|
0x32595ba18ddd19d3L, 0x509a1cc0aaa5b446L, |
|
0x9f3d6367e4046bbaL, 0xf6ca19ab0b56ee7eL, |
|
0x1fb179eaa9282174L, 0xe9bdf7353b3651eeL, |
|
0x1d57ac5a7550d376L, 0x3a46c2fea37d7001L, |
|
0xf735c1af98a4d842L, 0x78edec209e6b6779L, |
|
0x41836315ea3adba8L, 0xfac33b4d32832c83L, |
|
0xa7403b1f1c2747f3L, 0x5940f034b72d769aL, |
|
0xe73e4e6cd2214ffdL, 0xb8fd8d39dc5759efL, |
|
0x8d9b0c492b49ebdaL, 0x5ba2d74968f3700dL, |
|
0x7d3baed07a8d5584L, 0xf5a5e9f0e4f88e65L, |
|
0xa0b8a2f436103b53L, 0x0ca8079e753eec5aL, |
|
0x9168949256e8884fL, 0x5bb05c55f8babc4cL, |
|
0xe3bb3b99f387947bL, 0x75daf4d6726b1c5dL, |
|
0x64aeac28dc34b36dL, 0x6c34a550b828db71L, |
|
0xf861e2f2108d512aL, 0xe3db643359dd75fcL, |
|
0x1cacbcf143ce3fa2L, 0x67bbd13c02e843b0L, |
|
0x330a5bca8829a175L, 0x7f34194db416535cL, |
|
0x923b94c30e794d1eL, 0x797475d7b6eeaf3fL, |
|
0xeaa8d4f7be1a3921L, 0x5cf47e094c232751L, |
|
0x26a32453ba323cd2L, 0x44a3174a6da6d5adL, |
|
0xb51d3ea6aff2c908L, 0x83593d98916b3c56L, |
|
0x4cf87ca17286604dL, 0x46e23ecc086ec7f6L, |
|
0x2f9833b3b1bc765eL, 0x2bd666a5efc4e62aL, |
|
0x06f4b6e8bec1d436L, 0x74ee8215bcef2163L, |
|
0xfdc14e0df453c969L, 0xa77d5ac406585826L, |
|
0x7ec1141606e0fa16L, 0x7e90af3d28639d3fL, |
|
0xd2c9f2e3009bd20cL, 0x5faace30b7d40c30L, |
|
0x742a5116f2e03298L, 0x0deb30d8e3cef89aL, |
|
0x4bc59e7bb5f17992L, 0xff51e66e048668d3L, |
|
0x9b234d57e6966731L, 0xcce6a6f3170a7505L, |
|
0xb17681d913326cceL, 0x3c175284f805a262L, |
|
0xf42bcbb378471547L, 0xff46548223936a48L, |
|
0x38df58074e5e6565L, 0xf2fc7c89fc86508eL, |
|
0x31702e44d00bca86L, 0xf04009a23078474eL, |
|
0x65a0ee39d1f73883L, 0xf75ee937e42c3abdL, |
|
0x2197b2260113f86fL, 0xa344edd1ef9fdee7L, |
|
0x8ba0df15762592d9L, 0x3c85f7f612dc42beL, |
|
0xd8a7ec7cab27b07eL, 0x538d7ddaaa3ea8deL, |
|
0xaa25ce93bd0269d8L, 0x5af643fd1a7308f9L, |
|
0xc05fefda174a19a5L, 0x974d66334cfd216aL, |
|
0x35b49831db411570L, 0xea1e0fbbedcd549bL, |
|
0x9ad063a151974072L, 0xf6759dbf91476fe2L |
|
}; |
|
|
|
/** |
|
* Encode the 64-bit word {@code val} into the array |
|
* {@code buf} at offset {@code off}, in big-endian |
|
* convention (least significant byte first). |
|
* |
|
* @param val the value to encode |
|
* @param buf the destination buffer |
|
* @param off the destination offset |
|
*/ |
|
static private final void encodeBELong(long val, byte[] buf, int off) |
|
{ |
|
buf[off + 0] = (byte)(val >>> 56); |
|
buf[off + 1] = (byte)(val >>> 48); |
|
buf[off + 2] = (byte)(val >>> 40); |
|
buf[off + 3] = (byte)(val >>> 32); |
|
buf[off + 4] = (byte)(val >>> 24); |
|
buf[off + 5] = (byte)(val >>> 16); |
|
buf[off + 6] = (byte)(val >>> 8); |
|
buf[off + 7] = (byte)val; |
|
} |
|
|
|
/** |
|
* Decode a 64-bit big-endian word from the array {@code buf} |
|
* at offset {@code off}. |
|
* |
|
* @param buf the source buffer |
|
* @param off the source offset |
|
* @return the decoded value |
|
*/ |
|
static private final long decodeBELong(byte[] buf, int off) |
|
{ |
|
return ((buf[off + 0] & 0xFFL) << 56) |
|
| ((buf[off + 1] & 0xFFL) << 48) |
|
| ((buf[off + 2] & 0xFFL) << 40) |
|
| ((buf[off + 3] & 0xFFL) << 32) |
|
| ((buf[off + 4] & 0xFFL) << 24) |
|
| ((buf[off + 5] & 0xFFL) << 16) |
|
| ((buf[off + 6] & 0xFFL) << 8) |
|
| (buf[off + 7] & 0xFFL); |
|
} |
|
|
|
/** @see DigestEngine */ |
|
protected void engineReset() |
|
{ |
|
doReset(); |
|
} |
|
|
|
private final void doS(int r) |
|
{ |
|
long x0, x1, x2, x3, cc, tmp; |
|
|
|
cc = C[(r << 2) + 0]; |
|
x0 = h[ 0]; |
|
x1 = h[ 4]; |
|
x2 = h[ 8]; |
|
x3 = h[12]; |
|
x3 = ~x3; |
|
x0 ^= cc & ~x2; |
|
tmp = cc ^ (x0 & x1); |
|
x0 ^= x2 & x3; |
|
x3 ^= ~x1 & x2; |
|
x1 ^= x0 & x2; |
|
x2 ^= x0 & ~x3; |
|
x0 ^= x1 | x3; |
|
x3 ^= x1 & x2; |
|
x1 ^= tmp & x0; |
|
x2 ^= tmp; |
|
h[ 0] = x0; |
|
h[ 4] = x1; |
|
h[ 8] = x2; |
|
h[12] = x3; |
|
|
|
cc = C[(r << 2) + 1]; |
|
x0 = h[ 1]; |
|
x1 = h[ 5]; |
|
x2 = h[ 9]; |
|
x3 = h[13]; |
|
x3 = ~x3; |
|
x0 ^= cc & ~x2; |
|
tmp = cc ^ (x0 & x1); |
|
x0 ^= x2 & x3; |
|
x3 ^= ~x1 & x2; |
|
x1 ^= x0 & x2; |
|
x2 ^= x0 & ~x3; |
|
x0 ^= x1 | x3; |
|
x3 ^= x1 & x2; |
|
x1 ^= tmp & x0; |
|
x2 ^= tmp; |
|
h[ 1] = x0; |
|
h[ 5] = x1; |
|
h[ 9] = x2; |
|
h[13] = x3; |
|
|
|
cc = C[(r << 2) + 2]; |
|
x0 = h[ 2]; |
|
x1 = h[ 6]; |
|
x2 = h[10]; |
|
x3 = h[14]; |
|
x3 = ~x3; |
|
x0 ^= cc & ~x2; |
|
tmp = cc ^ (x0 & x1); |
|
x0 ^= x2 & x3; |
|
x3 ^= ~x1 & x2; |
|
x1 ^= x0 & x2; |
|
x2 ^= x0 & ~x3; |
|
x0 ^= x1 | x3; |
|
x3 ^= x1 & x2; |
|
x1 ^= tmp & x0; |
|
x2 ^= tmp; |
|
h[ 2] = x0; |
|
h[ 6] = x1; |
|
h[10] = x2; |
|
h[14] = x3; |
|
|
|
cc = C[(r << 2) + 3]; |
|
x0 = h[ 3]; |
|
x1 = h[ 7]; |
|
x2 = h[11]; |
|
x3 = h[15]; |
|
x3 = ~x3; |
|
x0 ^= cc & ~x2; |
|
tmp = cc ^ (x0 & x1); |
|
x0 ^= x2 & x3; |
|
x3 ^= ~x1 & x2; |
|
x1 ^= x0 & x2; |
|
x2 ^= x0 & ~x3; |
|
x0 ^= x1 | x3; |
|
x3 ^= x1 & x2; |
|
x1 ^= tmp & x0; |
|
x2 ^= tmp; |
|
h[ 3] = x0; |
|
h[ 7] = x1; |
|
h[11] = x2; |
|
h[15] = x3; |
|
} |
|
|
|
private final void doL() |
|
{ |
|
long x0, x1, x2, x3, x4, x5, x6, x7; |
|
x0 = h[ 0]; |
|
x1 = h[ 4]; |
|
x2 = h[ 8]; |
|
x3 = h[12]; |
|
x4 = h[ 2]; |
|
x5 = h[ 6]; |
|
x6 = h[10]; |
|
x7 = h[14]; |
|
x4 ^= x1; |
|
x5 ^= x2; |
|
x6 ^= x3 ^ x0; |
|
x7 ^= x0; |
|
x0 ^= x5; |
|
x1 ^= x6; |
|
x2 ^= x7 ^ x4; |
|
x3 ^= x4; |
|
h[ 0] = x0; |
|
h[ 4] = x1; |
|
h[ 8] = x2; |
|
h[12] = x3; |
|
h[ 2] = x4; |
|
h[ 6] = x5; |
|
h[10] = x6; |
|
h[14] = x7; |
|
|
|
x0 = h[ 1]; |
|
x1 = h[ 5]; |
|
x2 = h[ 9]; |
|
x3 = h[13]; |
|
x4 = h[ 3]; |
|
x5 = h[ 7]; |
|
x6 = h[11]; |
|
x7 = h[15]; |
|
x4 ^= x1; |
|
x5 ^= x2; |
|
x6 ^= x3 ^ x0; |
|
x7 ^= x0; |
|
x0 ^= x5; |
|
x1 ^= x6; |
|
x2 ^= x7 ^ x4; |
|
x3 ^= x4; |
|
h[ 1] = x0; |
|
h[ 5] = x1; |
|
h[ 9] = x2; |
|
h[13] = x3; |
|
h[ 3] = x4; |
|
h[ 7] = x5; |
|
h[11] = x6; |
|
h[15] = x7; |
|
} |
|
|
|
private final void doWgen(long c, int n) |
|
{ |
|
h[ 2] = ((h[ 2] & c) << n) | ((h[ 2] >>> n) & c); |
|
h[ 3] = ((h[ 3] & c) << n) | ((h[ 3] >>> n) & c); |
|
h[ 6] = ((h[ 6] & c) << n) | ((h[ 6] >>> n) & c); |
|
h[ 7] = ((h[ 7] & c) << n) | ((h[ 7] >>> n) & c); |
|
h[10] = ((h[10] & c) << n) | ((h[10] >>> n) & c); |
|
h[11] = ((h[11] & c) << n) | ((h[11] >>> n) & c); |
|
h[14] = ((h[14] & c) << n) | ((h[14] >>> n) & c); |
|
h[15] = ((h[15] & c) << n) | ((h[15] >>> n) & c); |
|
} |
|
|
|
private final void doW6() |
|
{ |
|
long t; |
|
t = h[ 2]; h[ 2] = h[ 3]; h[ 3] = t; |
|
t = h[ 6]; h[ 6] = h[ 7]; h[ 7] = t; |
|
t = h[10]; h[10] = h[11]; h[11] = t; |
|
t = h[14]; h[14] = h[15]; h[15] = t; |
|
} |
|
|
|
/** @see DigestEngine */ |
|
protected void processBlock(byte[] data) |
|
{ |
|
long m0h = decodeBELong(data, 0); |
|
long m0l = decodeBELong(data, 8); |
|
long m1h = decodeBELong(data, 16); |
|
long m1l = decodeBELong(data, 24); |
|
long m2h = decodeBELong(data, 32); |
|
long m2l = decodeBELong(data, 40); |
|
long m3h = decodeBELong(data, 48); |
|
long m3l = decodeBELong(data, 56); |
|
h[0] ^= m0h; |
|
h[1] ^= m0l; |
|
h[2] ^= m1h; |
|
h[3] ^= m1l; |
|
h[4] ^= m2h; |
|
h[5] ^= m2l; |
|
h[6] ^= m3h; |
|
h[7] ^= m3l; |
|
for (int r = 0; r < 42; r += 7) { |
|
doS(r + 0); |
|
doL(); |
|
doWgen(0x5555555555555555L, 1); |
|
doS(r + 1); |
|
doL(); |
|
doWgen(0x3333333333333333L, 2); |
|
doS(r + 2); |
|
doL(); |
|
doWgen(0x0F0F0F0F0F0F0F0FL, 4); |
|
doS(r + 3); |
|
doL(); |
|
doWgen(0x00FF00FF00FF00FFL, 8); |
|
doS(r + 4); |
|
doL(); |
|
doWgen(0x0000FFFF0000FFFFL, 16); |
|
doS(r + 5); |
|
doL(); |
|
doWgen(0x00000000FFFFFFFFL, 32); |
|
doS(r + 6); |
|
doL(); |
|
doW6(); |
|
} |
|
h[ 8] ^= m0h; |
|
h[ 9] ^= m0l; |
|
h[10] ^= m1h; |
|
h[11] ^= m1l; |
|
h[12] ^= m2h; |
|
h[13] ^= m2l; |
|
h[14] ^= m3h; |
|
h[15] ^= m3l; |
|
} |
|
|
|
/** @see DigestEngine */ |
|
protected void doPadding(byte[] buf, int off) |
|
{ |
|
int rem = flush(); |
|
long bc = getBlockCount(); |
|
int numz = (rem == 0) ? 47 : 111 - rem; |
|
tmpBuf[0] = (byte)0x80; |
|
for (int i = 1; i <= numz; i ++) |
|
tmpBuf[i] = 0x00; |
|
encodeBELong(bc >>> 55, tmpBuf, numz + 1); |
|
encodeBELong((bc << 9) + (rem << 3), tmpBuf, numz + 9); |
|
update(tmpBuf, 0, numz + 17); |
|
for (int i = 0; i < 8; i ++) |
|
encodeBELong(h[i + 8], tmpBuf, i << 3); |
|
int dlen = getDigestLength(); |
|
System.arraycopy(tmpBuf, 64 - dlen, buf, off, dlen); |
|
} |
|
|
|
/** @see DigestEngine */ |
|
protected void doInit() |
|
{ |
|
h = new long[16]; |
|
tmpBuf = new byte[128]; |
|
doReset(); |
|
} |
|
|
|
/** |
|
* Get the initial values. |
|
* |
|
* @return the IV |
|
*/ |
|
abstract long[] getIV(); |
|
|
|
/** @see Digest */ |
|
public int getBlockLength() |
|
{ |
|
return 64; |
|
} |
|
|
|
private final void doReset() |
|
{ |
|
System.arraycopy(getIV(), 0, h, 0, 16); |
|
} |
|
|
|
/** @see DigestEngine */ |
|
protected Digest copyState(JHCore dst) |
|
{ |
|
System.arraycopy(h, 0, dst.h, 0, 16); |
|
return super.copyState(dst); |
|
} |
|
|
|
/** @see Digest */ |
|
public String toString() |
|
{ |
|
return "JH-" + (getDigestLength() << 3); |
|
} |
|
}
|
|
|