forked from Qortal/Brooklyn
960 lines
21 KiB
Java
960 lines
21 KiB
Java
|
// $Id: HamsiSmallCore.java 239 2010-06-21 14:58:08Z tp $
|
||
|
|
||
|
package fr.cryptohash;
|
||
|
|
||
|
/**
|
||
|
* This class implements Hamsi-224 and Hamsi-256.
|
||
|
*
|
||
|
* <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: 239 $
|
||
|
* @author Thomas Pornin <thomas.pornin@cryptolog.com>
|
||
|
*/
|
||
|
|
||
|
abstract class HamsiSmallCore implements Digest {
|
||
|
|
||
|
private int[] h;
|
||
|
private long bitCount;
|
||
|
private int partial;
|
||
|
private int partialLen;
|
||
|
|
||
|
/**
|
||
|
* Create the object.
|
||
|
*/
|
||
|
HamsiSmallCore()
|
||
|
{
|
||
|
h = new int[8];
|
||
|
reset();
|
||
|
}
|
||
|
|
||
|
/** @see Digest */
|
||
|
public void update(byte in)
|
||
|
{
|
||
|
bitCount += 8;
|
||
|
partial = (partial << 8) | (in & 0xFF);
|
||
|
partialLen ++;
|
||
|
if (partialLen == 4) {
|
||
|
process(partial >>> 24, (partial >>> 16) & 0xFF,
|
||
|
(partial >>> 8) & 0xFF, partial & 0xFF);
|
||
|
partialLen = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/** @see Digest */
|
||
|
public void update(byte[] inbuf)
|
||
|
{
|
||
|
update(inbuf, 0, inbuf.length);
|
||
|
}
|
||
|
|
||
|
/** @see Digest */
|
||
|
public void update(byte[] inbuf, int off, int len)
|
||
|
{
|
||
|
bitCount += (long)len << 3;
|
||
|
if (partialLen != 0) {
|
||
|
while (partialLen < 4 && len > 0) {
|
||
|
partial = (partial << 8)
|
||
|
| (inbuf[off ++] & 0xFF);
|
||
|
partialLen ++;
|
||
|
len --;
|
||
|
}
|
||
|
if (partialLen < 4)
|
||
|
return;
|
||
|
process(partial >>> 24, (partial >>> 16) & 0xFF,
|
||
|
(partial >>> 8) & 0xFF, partial & 0xFF);
|
||
|
partialLen = 0;
|
||
|
}
|
||
|
while (len >= 4) {
|
||
|
process(inbuf[off + 0] & 0xFF,
|
||
|
inbuf[off + 1] & 0xFF,
|
||
|
inbuf[off + 2] & 0xFF,
|
||
|
inbuf[off + 3] & 0xFF);
|
||
|
off += 4;
|
||
|
len -= 4;
|
||
|
}
|
||
|
partialLen = len;
|
||
|
while (len -- > 0)
|
||
|
partial = (partial << 8) | (inbuf[off ++] & 0xFF);
|
||
|
}
|
||
|
|
||
|
/** @see Digest */
|
||
|
public byte[] digest()
|
||
|
{
|
||
|
int n = getDigestLength();
|
||
|
byte[] out = new byte[n];
|
||
|
digest(out, 0, n);
|
||
|
return out;
|
||
|
}
|
||
|
|
||
|
/** @see Digest */
|
||
|
public byte[] digest(byte[] inbuf)
|
||
|
{
|
||
|
update(inbuf, 0, inbuf.length);
|
||
|
return digest();
|
||
|
}
|
||
|
|
||
|
/** @see Digest */
|
||
|
public int digest(byte[] outbuf, int off, int len)
|
||
|
{
|
||
|
long bitCount = this.bitCount;
|
||
|
update((byte)0x80);
|
||
|
while (partialLen != 0)
|
||
|
update((byte)0x00);
|
||
|
process((int)(bitCount >>> 56) & 0xFF,
|
||
|
(int)(bitCount >>> 48) & 0xFF,
|
||
|
(int)(bitCount >>> 40) & 0xFF,
|
||
|
(int)(bitCount >>> 32) & 0xFF);
|
||
|
processFinal(((int)bitCount >>> 24) & 0xFF,
|
||
|
((int)bitCount >>> 16) & 0xFF,
|
||
|
((int)bitCount >>> 8) & 0xFF,
|
||
|
(int)bitCount & 0xFF);
|
||
|
int n = getDigestLength();
|
||
|
if (len > n)
|
||
|
len = n;
|
||
|
int ch = 0;
|
||
|
for (int i = 0, j = 0; i < len; i ++) {
|
||
|
if ((i & 3) == 0)
|
||
|
ch = h[j ++];
|
||
|
outbuf[off + i] = (byte)(ch >>> 24);
|
||
|
ch <<= 8;
|
||
|
}
|
||
|
reset();
|
||
|
return len;
|
||
|
}
|
||
|
|
||
|
/** @see Digest */
|
||
|
public void reset()
|
||
|
{
|
||
|
System.arraycopy(getIV(), 0, h, 0, h.length);
|
||
|
bitCount = 0;
|
||
|
partialLen = 0;
|
||
|
}
|
||
|
|
||
|
/** @see Digest */
|
||
|
public Digest copy()
|
||
|
{
|
||
|
HamsiSmallCore d = dup();
|
||
|
System.arraycopy(h, 0, d.h, 0, h.length);
|
||
|
d.bitCount = bitCount;
|
||
|
d.partial = partial;
|
||
|
d.partialLen = partialLen;
|
||
|
return d;
|
||
|
}
|
||
|
|
||
|
/** @see Digest */
|
||
|
public int getBlockLength()
|
||
|
{
|
||
|
/*
|
||
|
* Private communication from Hamsi designer Ozgul Kucuk:
|
||
|
*
|
||
|
* << For HMAC you can calculate B = 256*ceil(k / 256)
|
||
|
* (same as CubeHash). >>
|
||
|
*/
|
||
|
return -32;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the IV.
|
||
|
*
|
||
|
* @return the IV (initial values for the state words)
|
||
|
*/
|
||
|
abstract int[] getIV();
|
||
|
|
||
|
/**
|
||
|
* Create a new instance of the same runtime class than this object.
|
||
|
*
|
||
|
* @return the duplicate
|
||
|
*/
|
||
|
abstract HamsiSmallCore dup();
|
||
|
|
||
|
private static final int[][] Tsrc = {
|
||
|
{ 0x045f0000, 0x9c4a93c9, 0x62fc79d0, 0x731ebdc2,
|
||
|
0xe0278000, 0x19dce008, 0xd7075d82, 0x5ad2e31d },
|
||
|
{ 0xe4788000, 0x859673c1, 0xb5fb2452, 0x29cc5edf,
|
||
|
0x045f0000, 0x9c4a93c9, 0x62fc79d0, 0x731ebdc2 },
|
||
|
{ 0xe6570000, 0x4bb33a25, 0x848598ba, 0x1041003e,
|
||
|
0xf44c4000, 0x10a4e3cd, 0x097f5711, 0xde77cc4c },
|
||
|
{ 0x121b4000, 0x5b17d9e8, 0x8dfacfab, 0xce36cc72,
|
||
|
0xe6570000, 0x4bb33a25, 0x848598ba, 0x1041003e },
|
||
|
{ 0x97530000, 0x204f6ed3, 0x77b9e80f, 0xa1ec5ec1,
|
||
|
0x7e792000, 0x9418e22f, 0x6643d258, 0x9c255be5 },
|
||
|
{ 0xe92a2000, 0xb4578cfc, 0x11fa3a57, 0x3dc90524,
|
||
|
0x97530000, 0x204f6ed3, 0x77b9e80f, 0xa1ec5ec1 },
|
||
|
{ 0xcba90000, 0x90273769, 0xbbdcf407, 0xd0f4af61,
|
||
|
0xbf3c1000, 0xca0c7117, 0x3321e92c, 0xce122df3 },
|
||
|
{ 0x74951000, 0x5a2b467e, 0x88fd1d2b, 0x1ee68292,
|
||
|
0xcba90000, 0x90273769, 0xbbdcf407, 0xd0f4af61 },
|
||
|
{ 0xe18b0000, 0x5459887d, 0xbf1283d3, 0x1b666a73,
|
||
|
0x3fb90800, 0x7cdad883, 0xce97a914, 0xbdd9f5e5 },
|
||
|
{ 0xde320800, 0x288350fe, 0x71852ac7, 0xa6bf9f96,
|
||
|
0xe18b0000, 0x5459887d, 0xbf1283d3, 0x1b666a73 },
|
||
|
{ 0x14bd0000, 0x2fba37ff, 0x6a72e5bb, 0x247febe6,
|
||
|
0x9b830400, 0x2227ff88, 0x05b7ad5a, 0xadf2c730 },
|
||
|
{ 0x8f3e0400, 0x0d9dc877, 0x6fc548e1, 0x898d2cd6,
|
||
|
0x14bd0000, 0x2fba37ff, 0x6a72e5bb, 0x247febe6 },
|
||
|
{ 0xee260000, 0x124b683e, 0x80c2d68f, 0x3bf3ab2c,
|
||
|
0x499e0200, 0x0d59ec0d, 0xe0272f7d, 0xa5e7de5a },
|
||
|
{ 0xa7b80200, 0x1f128433, 0x60e5f9f2, 0x9e147576,
|
||
|
0xee260000, 0x124b683e, 0x80c2d68f, 0x3bf3ab2c },
|
||
|
{ 0x734c0000, 0x956fa7d6, 0xa29d1297, 0x6ee56854,
|
||
|
0xc4e80100, 0x1f70960e, 0x2714ca3c, 0x88210c30 },
|
||
|
{ 0xb7a40100, 0x8a1f31d8, 0x8589d8ab, 0xe6c46464,
|
||
|
0x734c0000, 0x956fa7d6, 0xa29d1297, 0x6ee56854 },
|
||
|
{ 0x39a60000, 0x4ab753eb, 0xd14e094b, 0xb772b42b,
|
||
|
0x62740080, 0x0fb84b07, 0x138a651e, 0x44100618 },
|
||
|
{ 0x5bd20080, 0x450f18ec, 0xc2c46c55, 0xf362b233,
|
||
|
0x39a60000, 0x4ab753eb, 0xd14e094b, 0xb772b42b },
|
||
|
{ 0x78ab0000, 0xa0cd5a34, 0x5d5ca0f7, 0x727784cb,
|
||
|
0x35650040, 0x9b96b64a, 0x6b39cb5f, 0x5114bece },
|
||
|
{ 0x4dce0040, 0x3b5bec7e, 0x36656ba8, 0x23633a05,
|
||
|
0x78ab0000, 0xa0cd5a34, 0x5d5ca0f7, 0x727784cb },
|
||
|
{ 0x5c720000, 0xc9bacd12, 0x79a90df9, 0x63e92178,
|
||
|
0xfeca0020, 0x485d28e4, 0x806741fd, 0x814681b8 },
|
||
|
{ 0xa2b80020, 0x81e7e5f6, 0xf9ce4c04, 0xe2afa0c0,
|
||
|
0x5c720000, 0xc9bacd12, 0x79a90df9, 0x63e92178 },
|
||
|
{ 0x2e390000, 0x64dd6689, 0x3cd406fc, 0xb1f490bc,
|
||
|
0x7f650010, 0x242e1472, 0xc03320fe, 0xc0a3c0dd },
|
||
|
{ 0x515c0010, 0x40f372fb, 0xfce72602, 0x71575061,
|
||
|
0x2e390000, 0x64dd6689, 0x3cd406fc, 0xb1f490bc },
|
||
|
{ 0x171c0000, 0xb26e3344, 0x9e6a837e, 0x58f8485f,
|
||
|
0xbfb20008, 0x92170a39, 0x6019107f, 0xe051606e },
|
||
|
{ 0xa8ae0008, 0x2079397d, 0xfe739301, 0xb8a92831,
|
||
|
0x171c0000, 0xb26e3344, 0x9e6a837e, 0x58f8485f },
|
||
|
{ 0x6ba90000, 0x40ebf9aa, 0x98321c3d, 0x76acc733,
|
||
|
0xbba10004, 0xcc9d76dd, 0x05f7ac6d, 0xd9e6eee9 },
|
||
|
{ 0xd0080004, 0x8c768f77, 0x9dc5b050, 0xaf4a29da,
|
||
|
0x6ba90000, 0x40ebf9aa, 0x98321c3d, 0x76acc733 },
|
||
|
{ 0x51ac0000, 0x25e30f14, 0x79e22a4c, 0x1298bd46,
|
||
|
0xd98f0002, 0x7a04a8a7, 0xe007afe6, 0x9fed4ab7 },
|
||
|
{ 0x88230002, 0x5fe7a7b3, 0x99e585aa, 0x8d75f7f1,
|
||
|
0x51ac0000, 0x25e30f14, 0x79e22a4c, 0x1298bd46 },
|
||
|
{ 0xc8f10000, 0x0b2de782, 0x6bf648a4, 0x539cbdbf,
|
||
|
0x08bf0001, 0x38942792, 0xc5f8f3a1, 0xe6387b84 },
|
||
|
{ 0xc04e0001, 0x33b9c010, 0xae0ebb05, 0xb5a4c63b,
|
||
|
0xc8f10000, 0x0b2de782, 0x6bf648a4, 0x539cbdbf }
|
||
|
};
|
||
|
|
||
|
private static int[][] makeT(int x)
|
||
|
{
|
||
|
int[][] T = new int[256][8];
|
||
|
for (int y = 0; y < 256; y ++) {
|
||
|
for (int z = 0; z < 8; z ++) {
|
||
|
int a = 0;
|
||
|
for (int k = 0; k < 8; k ++) {
|
||
|
if ((y & (1 << (7 - k))) != 0)
|
||
|
a ^= Tsrc[x + k][z];
|
||
|
}
|
||
|
T[y][z] = a;
|
||
|
}
|
||
|
}
|
||
|
return T;
|
||
|
}
|
||
|
|
||
|
private static final int[][] T256_0 = makeT(0);
|
||
|
private static final int[][] T256_1 = makeT(8);
|
||
|
private static final int[][] T256_2 = makeT(16);
|
||
|
private static final int[][] T256_3 = makeT(24);
|
||
|
|
||
|
private static final int[] ALPHA_N = {
|
||
|
0xff00f0f0, 0xccccaaaa, 0xf0f0cccc, 0xff00aaaa,
|
||
|
0xccccaaaa, 0xf0f0ff00, 0xaaaacccc, 0xf0f0ff00,
|
||
|
0xf0f0cccc, 0xaaaaff00, 0xccccff00, 0xaaaaf0f0,
|
||
|
0xaaaaf0f0, 0xff00cccc, 0xccccf0f0, 0xff00aaaa,
|
||
|
0xccccaaaa, 0xff00f0f0, 0xff00aaaa, 0xf0f0cccc,
|
||
|
0xf0f0ff00, 0xccccaaaa, 0xf0f0ff00, 0xaaaacccc,
|
||
|
0xaaaaff00, 0xf0f0cccc, 0xaaaaf0f0, 0xccccff00,
|
||
|
0xff00cccc, 0xaaaaf0f0, 0xff00aaaa, 0xccccf0f0
|
||
|
};
|
||
|
|
||
|
private static final int[] ALPHA_F = {
|
||
|
0xcaf9639c, 0x0ff0f9c0, 0x639c0ff0, 0xcaf9f9c0,
|
||
|
0x0ff0f9c0, 0x639ccaf9, 0xf9c00ff0, 0x639ccaf9,
|
||
|
0x639c0ff0, 0xf9c0caf9, 0x0ff0caf9, 0xf9c0639c,
|
||
|
0xf9c0639c, 0xcaf90ff0, 0x0ff0639c, 0xcaf9f9c0,
|
||
|
0x0ff0f9c0, 0xcaf9639c, 0xcaf9f9c0, 0x639c0ff0,
|
||
|
0x639ccaf9, 0x0ff0f9c0, 0x639ccaf9, 0xf9c00ff0,
|
||
|
0xf9c0caf9, 0x639c0ff0, 0xf9c0639c, 0x0ff0caf9,
|
||
|
0xcaf90ff0, 0xf9c0639c, 0xcaf9f9c0, 0x0ff0639c
|
||
|
};
|
||
|
|
||
|
private void process(int b0, int b1, int b2, int b3)
|
||
|
{
|
||
|
int[] rp = T256_0[b0];
|
||
|
int m0 = rp[0];
|
||
|
int m1 = rp[1];
|
||
|
int m2 = rp[2];
|
||
|
int m3 = rp[3];
|
||
|
int m4 = rp[4];
|
||
|
int m5 = rp[5];
|
||
|
int m6 = rp[6];
|
||
|
int m7 = rp[7];
|
||
|
rp = T256_1[b1];
|
||
|
m0 ^= rp[0];
|
||
|
m1 ^= rp[1];
|
||
|
m2 ^= rp[2];
|
||
|
m3 ^= rp[3];
|
||
|
m4 ^= rp[4];
|
||
|
m5 ^= rp[5];
|
||
|
m6 ^= rp[6];
|
||
|
m7 ^= rp[7];
|
||
|
rp = T256_2[b2];
|
||
|
m0 ^= rp[0];
|
||
|
m1 ^= rp[1];
|
||
|
m2 ^= rp[2];
|
||
|
m3 ^= rp[3];
|
||
|
m4 ^= rp[4];
|
||
|
m5 ^= rp[5];
|
||
|
m6 ^= rp[6];
|
||
|
m7 ^= rp[7];
|
||
|
rp = T256_3[b3];
|
||
|
m0 ^= rp[0];
|
||
|
m1 ^= rp[1];
|
||
|
m2 ^= rp[2];
|
||
|
m3 ^= rp[3];
|
||
|
m4 ^= rp[4];
|
||
|
m5 ^= rp[5];
|
||
|
m6 ^= rp[6];
|
||
|
m7 ^= rp[7];
|
||
|
|
||
|
int c0 = h[0];
|
||
|
int c1 = h[1];
|
||
|
int c2 = h[2];
|
||
|
int c3 = h[3];
|
||
|
int c4 = h[4];
|
||
|
int c5 = h[5];
|
||
|
int c6 = h[6];
|
||
|
int c7 = h[7];
|
||
|
int t;
|
||
|
|
||
|
m0 ^= ALPHA_N[0x00];
|
||
|
m1 ^= ALPHA_N[0x01] ^ 0;
|
||
|
c0 ^= ALPHA_N[0x02];
|
||
|
c1 ^= ALPHA_N[0x03];
|
||
|
c2 ^= ALPHA_N[0x08];
|
||
|
c3 ^= ALPHA_N[0x09];
|
||
|
m2 ^= ALPHA_N[0x0A];
|
||
|
m3 ^= ALPHA_N[0x0B];
|
||
|
m4 ^= ALPHA_N[0x10];
|
||
|
m5 ^= ALPHA_N[0x11];
|
||
|
c4 ^= ALPHA_N[0x12];
|
||
|
c5 ^= ALPHA_N[0x13];
|
||
|
c6 ^= ALPHA_N[0x18];
|
||
|
c7 ^= ALPHA_N[0x19];
|
||
|
m6 ^= ALPHA_N[0x1A];
|
||
|
m7 ^= ALPHA_N[0x1B];
|
||
|
t = m0;
|
||
|
m0 &= m4;
|
||
|
m0 ^= c6;
|
||
|
m4 ^= c2;
|
||
|
m4 ^= m0;
|
||
|
c6 |= t;
|
||
|
c6 ^= c2;
|
||
|
t ^= m4;
|
||
|
c2 = c6;
|
||
|
c6 |= t;
|
||
|
c6 ^= m0;
|
||
|
m0 &= c2;
|
||
|
t ^= m0;
|
||
|
c2 ^= c6;
|
||
|
c2 ^= t;
|
||
|
m0 = m4;
|
||
|
m4 = c2;
|
||
|
c2 = c6;
|
||
|
c6 = ~t;
|
||
|
t = m1;
|
||
|
m1 &= m5;
|
||
|
m1 ^= c7;
|
||
|
m5 ^= c3;
|
||
|
m5 ^= m1;
|
||
|
c7 |= t;
|
||
|
c7 ^= c3;
|
||
|
t ^= m5;
|
||
|
c3 = c7;
|
||
|
c7 |= t;
|
||
|
c7 ^= m1;
|
||
|
m1 &= c3;
|
||
|
t ^= m1;
|
||
|
c3 ^= c7;
|
||
|
c3 ^= t;
|
||
|
m1 = m5;
|
||
|
m5 = c3;
|
||
|
c3 = c7;
|
||
|
c7 = ~t;
|
||
|
t = c0;
|
||
|
c0 &= c4;
|
||
|
c0 ^= m6;
|
||
|
c4 ^= m2;
|
||
|
c4 ^= c0;
|
||
|
m6 |= t;
|
||
|
m6 ^= m2;
|
||
|
t ^= c4;
|
||
|
m2 = m6;
|
||
|
m6 |= t;
|
||
|
m6 ^= c0;
|
||
|
c0 &= m2;
|
||
|
t ^= c0;
|
||
|
m2 ^= m6;
|
||
|
m2 ^= t;
|
||
|
c0 = c4;
|
||
|
c4 = m2;
|
||
|
m2 = m6;
|
||
|
m6 = ~t;
|
||
|
t = c1;
|
||
|
c1 &= c5;
|
||
|
c1 ^= m7;
|
||
|
c5 ^= m3;
|
||
|
c5 ^= c1;
|
||
|
m7 |= t;
|
||
|
m7 ^= m3;
|
||
|
t ^= c5;
|
||
|
m3 = m7;
|
||
|
m7 |= t;
|
||
|
m7 ^= c1;
|
||
|
c1 &= m3;
|
||
|
t ^= c1;
|
||
|
m3 ^= m7;
|
||
|
m3 ^= t;
|
||
|
c1 = c5;
|
||
|
c5 = m3;
|
||
|
m3 = m7;
|
||
|
m7 = ~t;
|
||
|
m0 = (m0 << 13) | (m0 >>> (32 - 13));
|
||
|
c4 = (c4 << 3) | (c4 >>> (32 - 3));
|
||
|
c3 ^= m0 ^ c4;
|
||
|
m7 ^= c4 ^ (m0 << 3);
|
||
|
c3 = (c3 << 1) | (c3 >>> (32 - 1));
|
||
|
m7 = (m7 << 7) | (m7 >>> (32 - 7));
|
||
|
m0 ^= c3 ^ m7;
|
||
|
c4 ^= m7 ^ (c3 << 7);
|
||
|
m0 = (m0 << 5) | (m0 >>> (32 - 5));
|
||
|
c4 = (c4 << 22) | (c4 >>> (32 - 22));
|
||
|
m1 = (m1 << 13) | (m1 >>> (32 - 13));
|
||
|
c5 = (c5 << 3) | (c5 >>> (32 - 3));
|
||
|
m2 ^= m1 ^ c5;
|
||
|
c6 ^= c5 ^ (m1 << 3);
|
||
|
m2 = (m2 << 1) | (m2 >>> (32 - 1));
|
||
|
c6 = (c6 << 7) | (c6 >>> (32 - 7));
|
||
|
m1 ^= m2 ^ c6;
|
||
|
c5 ^= c6 ^ (m2 << 7);
|
||
|
m1 = (m1 << 5) | (m1 >>> (32 - 5));
|
||
|
c5 = (c5 << 22) | (c5 >>> (32 - 22));
|
||
|
c0 = (c0 << 13) | (c0 >>> (32 - 13));
|
||
|
m4 = (m4 << 3) | (m4 >>> (32 - 3));
|
||
|
m3 ^= c0 ^ m4;
|
||
|
c7 ^= m4 ^ (c0 << 3);
|
||
|
m3 = (m3 << 1) | (m3 >>> (32 - 1));
|
||
|
c7 = (c7 << 7) | (c7 >>> (32 - 7));
|
||
|
c0 ^= m3 ^ c7;
|
||
|
m4 ^= c7 ^ (m3 << 7);
|
||
|
c0 = (c0 << 5) | (c0 >>> (32 - 5));
|
||
|
m4 = (m4 << 22) | (m4 >>> (32 - 22));
|
||
|
c1 = (c1 << 13) | (c1 >>> (32 - 13));
|
||
|
m5 = (m5 << 3) | (m5 >>> (32 - 3));
|
||
|
c2 ^= c1 ^ m5;
|
||
|
m6 ^= m5 ^ (c1 << 3);
|
||
|
c2 = (c2 << 1) | (c2 >>> (32 - 1));
|
||
|
m6 = (m6 << 7) | (m6 >>> (32 - 7));
|
||
|
c1 ^= c2 ^ m6;
|
||
|
m5 ^= m6 ^ (c2 << 7);
|
||
|
c1 = (c1 << 5) | (c1 >>> (32 - 5));
|
||
|
m5 = (m5 << 22) | (m5 >>> (32 - 22));
|
||
|
m0 ^= ALPHA_N[0x00];
|
||
|
m1 ^= ALPHA_N[0x01] ^ 1;
|
||
|
c0 ^= ALPHA_N[0x02];
|
||
|
c1 ^= ALPHA_N[0x03];
|
||
|
c2 ^= ALPHA_N[0x08];
|
||
|
c3 ^= ALPHA_N[0x09];
|
||
|
m2 ^= ALPHA_N[0x0A];
|
||
|
m3 ^= ALPHA_N[0x0B];
|
||
|
m4 ^= ALPHA_N[0x10];
|
||
|
m5 ^= ALPHA_N[0x11];
|
||
|
c4 ^= ALPHA_N[0x12];
|
||
|
c5 ^= ALPHA_N[0x13];
|
||
|
c6 ^= ALPHA_N[0x18];
|
||
|
c7 ^= ALPHA_N[0x19];
|
||
|
m6 ^= ALPHA_N[0x1A];
|
||
|
m7 ^= ALPHA_N[0x1B];
|
||
|
t = m0;
|
||
|
m0 &= m4;
|
||
|
m0 ^= c6;
|
||
|
m4 ^= c2;
|
||
|
m4 ^= m0;
|
||
|
c6 |= t;
|
||
|
c6 ^= c2;
|
||
|
t ^= m4;
|
||
|
c2 = c6;
|
||
|
c6 |= t;
|
||
|
c6 ^= m0;
|
||
|
m0 &= c2;
|
||
|
t ^= m0;
|
||
|
c2 ^= c6;
|
||
|
c2 ^= t;
|
||
|
m0 = m4;
|
||
|
m4 = c2;
|
||
|
c2 = c6;
|
||
|
c6 = ~t;
|
||
|
t = m1;
|
||
|
m1 &= m5;
|
||
|
m1 ^= c7;
|
||
|
m5 ^= c3;
|
||
|
m5 ^= m1;
|
||
|
c7 |= t;
|
||
|
c7 ^= c3;
|
||
|
t ^= m5;
|
||
|
c3 = c7;
|
||
|
c7 |= t;
|
||
|
c7 ^= m1;
|
||
|
m1 &= c3;
|
||
|
t ^= m1;
|
||
|
c3 ^= c7;
|
||
|
c3 ^= t;
|
||
|
m1 = m5;
|
||
|
m5 = c3;
|
||
|
c3 = c7;
|
||
|
c7 = ~t;
|
||
|
t = c0;
|
||
|
c0 &= c4;
|
||
|
c0 ^= m6;
|
||
|
c4 ^= m2;
|
||
|
c4 ^= c0;
|
||
|
m6 |= t;
|
||
|
m6 ^= m2;
|
||
|
t ^= c4;
|
||
|
m2 = m6;
|
||
|
m6 |= t;
|
||
|
m6 ^= c0;
|
||
|
c0 &= m2;
|
||
|
t ^= c0;
|
||
|
m2 ^= m6;
|
||
|
m2 ^= t;
|
||
|
c0 = c4;
|
||
|
c4 = m2;
|
||
|
m2 = m6;
|
||
|
m6 = ~t;
|
||
|
t = c1;
|
||
|
c1 &= c5;
|
||
|
c1 ^= m7;
|
||
|
c5 ^= m3;
|
||
|
c5 ^= c1;
|
||
|
m7 |= t;
|
||
|
m7 ^= m3;
|
||
|
t ^= c5;
|
||
|
m3 = m7;
|
||
|
m7 |= t;
|
||
|
m7 ^= c1;
|
||
|
c1 &= m3;
|
||
|
t ^= c1;
|
||
|
m3 ^= m7;
|
||
|
m3 ^= t;
|
||
|
c1 = c5;
|
||
|
c5 = m3;
|
||
|
m3 = m7;
|
||
|
m7 = ~t;
|
||
|
m0 = (m0 << 13) | (m0 >>> (32 - 13));
|
||
|
c4 = (c4 << 3) | (c4 >>> (32 - 3));
|
||
|
c3 ^= m0 ^ c4;
|
||
|
m7 ^= c4 ^ (m0 << 3);
|
||
|
c3 = (c3 << 1) | (c3 >>> (32 - 1));
|
||
|
m7 = (m7 << 7) | (m7 >>> (32 - 7));
|
||
|
m0 ^= c3 ^ m7;
|
||
|
c4 ^= m7 ^ (c3 << 7);
|
||
|
m0 = (m0 << 5) | (m0 >>> (32 - 5));
|
||
|
c4 = (c4 << 22) | (c4 >>> (32 - 22));
|
||
|
m1 = (m1 << 13) | (m1 >>> (32 - 13));
|
||
|
c5 = (c5 << 3) | (c5 >>> (32 - 3));
|
||
|
m2 ^= m1 ^ c5;
|
||
|
c6 ^= c5 ^ (m1 << 3);
|
||
|
m2 = (m2 << 1) | (m2 >>> (32 - 1));
|
||
|
c6 = (c6 << 7) | (c6 >>> (32 - 7));
|
||
|
m1 ^= m2 ^ c6;
|
||
|
c5 ^= c6 ^ (m2 << 7);
|
||
|
m1 = (m1 << 5) | (m1 >>> (32 - 5));
|
||
|
c5 = (c5 << 22) | (c5 >>> (32 - 22));
|
||
|
c0 = (c0 << 13) | (c0 >>> (32 - 13));
|
||
|
m4 = (m4 << 3) | (m4 >>> (32 - 3));
|
||
|
m3 ^= c0 ^ m4;
|
||
|
c7 ^= m4 ^ (c0 << 3);
|
||
|
m3 = (m3 << 1) | (m3 >>> (32 - 1));
|
||
|
c7 = (c7 << 7) | (c7 >>> (32 - 7));
|
||
|
c0 ^= m3 ^ c7;
|
||
|
m4 ^= c7 ^ (m3 << 7);
|
||
|
c0 = (c0 << 5) | (c0 >>> (32 - 5));
|
||
|
m4 = (m4 << 22) | (m4 >>> (32 - 22));
|
||
|
c1 = (c1 << 13) | (c1 >>> (32 - 13));
|
||
|
m5 = (m5 << 3) | (m5 >>> (32 - 3));
|
||
|
c2 ^= c1 ^ m5;
|
||
|
m6 ^= m5 ^ (c1 << 3);
|
||
|
c2 = (c2 << 1) | (c2 >>> (32 - 1));
|
||
|
m6 = (m6 << 7) | (m6 >>> (32 - 7));
|
||
|
c1 ^= c2 ^ m6;
|
||
|
m5 ^= m6 ^ (c2 << 7);
|
||
|
c1 = (c1 << 5) | (c1 >>> (32 - 5));
|
||
|
m5 = (m5 << 22) | (m5 >>> (32 - 22));
|
||
|
m0 ^= ALPHA_N[0x00];
|
||
|
m1 ^= ALPHA_N[0x01] ^ 2;
|
||
|
c0 ^= ALPHA_N[0x02];
|
||
|
c1 ^= ALPHA_N[0x03];
|
||
|
c2 ^= ALPHA_N[0x08];
|
||
|
c3 ^= ALPHA_N[0x09];
|
||
|
m2 ^= ALPHA_N[0x0A];
|
||
|
m3 ^= ALPHA_N[0x0B];
|
||
|
m4 ^= ALPHA_N[0x10];
|
||
|
m5 ^= ALPHA_N[0x11];
|
||
|
c4 ^= ALPHA_N[0x12];
|
||
|
c5 ^= ALPHA_N[0x13];
|
||
|
c6 ^= ALPHA_N[0x18];
|
||
|
c7 ^= ALPHA_N[0x19];
|
||
|
m6 ^= ALPHA_N[0x1A];
|
||
|
m7 ^= ALPHA_N[0x1B];
|
||
|
t = m0;
|
||
|
m0 &= m4;
|
||
|
m0 ^= c6;
|
||
|
m4 ^= c2;
|
||
|
m4 ^= m0;
|
||
|
c6 |= t;
|
||
|
c6 ^= c2;
|
||
|
t ^= m4;
|
||
|
c2 = c6;
|
||
|
c6 |= t;
|
||
|
c6 ^= m0;
|
||
|
m0 &= c2;
|
||
|
t ^= m0;
|
||
|
c2 ^= c6;
|
||
|
c2 ^= t;
|
||
|
m0 = m4;
|
||
|
m4 = c2;
|
||
|
c2 = c6;
|
||
|
c6 = ~t;
|
||
|
t = m1;
|
||
|
m1 &= m5;
|
||
|
m1 ^= c7;
|
||
|
m5 ^= c3;
|
||
|
m5 ^= m1;
|
||
|
c7 |= t;
|
||
|
c7 ^= c3;
|
||
|
t ^= m5;
|
||
|
c3 = c7;
|
||
|
c7 |= t;
|
||
|
c7 ^= m1;
|
||
|
m1 &= c3;
|
||
|
t ^= m1;
|
||
|
c3 ^= c7;
|
||
|
c3 ^= t;
|
||
|
m1 = m5;
|
||
|
m5 = c3;
|
||
|
c3 = c7;
|
||
|
c7 = ~t;
|
||
|
t = c0;
|
||
|
c0 &= c4;
|
||
|
c0 ^= m6;
|
||
|
c4 ^= m2;
|
||
|
c4 ^= c0;
|
||
|
m6 |= t;
|
||
|
m6 ^= m2;
|
||
|
t ^= c4;
|
||
|
m2 = m6;
|
||
|
m6 |= t;
|
||
|
m6 ^= c0;
|
||
|
c0 &= m2;
|
||
|
t ^= c0;
|
||
|
m2 ^= m6;
|
||
|
m2 ^= t;
|
||
|
c0 = c4;
|
||
|
c4 = m2;
|
||
|
m2 = m6;
|
||
|
m6 = ~t;
|
||
|
t = c1;
|
||
|
c1 &= c5;
|
||
|
c1 ^= m7;
|
||
|
c5 ^= m3;
|
||
|
c5 ^= c1;
|
||
|
m7 |= t;
|
||
|
m7 ^= m3;
|
||
|
t ^= c5;
|
||
|
m3 = m7;
|
||
|
m7 |= t;
|
||
|
m7 ^= c1;
|
||
|
c1 &= m3;
|
||
|
t ^= c1;
|
||
|
m3 ^= m7;
|
||
|
m3 ^= t;
|
||
|
c1 = c5;
|
||
|
c5 = m3;
|
||
|
m3 = m7;
|
||
|
m7 = ~t;
|
||
|
m0 = (m0 << 13) | (m0 >>> (32 - 13));
|
||
|
c4 = (c4 << 3) | (c4 >>> (32 - 3));
|
||
|
c3 ^= m0 ^ c4;
|
||
|
m7 ^= c4 ^ (m0 << 3);
|
||
|
c3 = (c3 << 1) | (c3 >>> (32 - 1));
|
||
|
m7 = (m7 << 7) | (m7 >>> (32 - 7));
|
||
|
m0 ^= c3 ^ m7;
|
||
|
c4 ^= m7 ^ (c3 << 7);
|
||
|
m0 = (m0 << 5) | (m0 >>> (32 - 5));
|
||
|
c4 = (c4 << 22) | (c4 >>> (32 - 22));
|
||
|
m1 = (m1 << 13) | (m1 >>> (32 - 13));
|
||
|
c5 = (c5 << 3) | (c5 >>> (32 - 3));
|
||
|
m2 ^= m1 ^ c5;
|
||
|
c6 ^= c5 ^ (m1 << 3);
|
||
|
m2 = (m2 << 1) | (m2 >>> (32 - 1));
|
||
|
c6 = (c6 << 7) | (c6 >>> (32 - 7));
|
||
|
m1 ^= m2 ^ c6;
|
||
|
c5 ^= c6 ^ (m2 << 7);
|
||
|
m1 = (m1 << 5) | (m1 >>> (32 - 5));
|
||
|
c5 = (c5 << 22) | (c5 >>> (32 - 22));
|
||
|
c0 = (c0 << 13) | (c0 >>> (32 - 13));
|
||
|
m4 = (m4 << 3) | (m4 >>> (32 - 3));
|
||
|
m3 ^= c0 ^ m4;
|
||
|
c7 ^= m4 ^ (c0 << 3);
|
||
|
m3 = (m3 << 1) | (m3 >>> (32 - 1));
|
||
|
c7 = (c7 << 7) | (c7 >>> (32 - 7));
|
||
|
c0 ^= m3 ^ c7;
|
||
|
m4 ^= c7 ^ (m3 << 7);
|
||
|
c0 = (c0 << 5) | (c0 >>> (32 - 5));
|
||
|
m4 = (m4 << 22) | (m4 >>> (32 - 22));
|
||
|
c1 = (c1 << 13) | (c1 >>> (32 - 13));
|
||
|
m5 = (m5 << 3) | (m5 >>> (32 - 3));
|
||
|
c2 ^= c1 ^ m5;
|
||
|
m6 ^= m5 ^ (c1 << 3);
|
||
|
c2 = (c2 << 1) | (c2 >>> (32 - 1));
|
||
|
m6 = (m6 << 7) | (m6 >>> (32 - 7));
|
||
|
c1 ^= c2 ^ m6;
|
||
|
m5 ^= m6 ^ (c2 << 7);
|
||
|
c1 = (c1 << 5) | (c1 >>> (32 - 5));
|
||
|
m5 = (m5 << 22) | (m5 >>> (32 - 22));
|
||
|
|
||
|
h[7] ^= c5;
|
||
|
h[6] ^= c4;
|
||
|
h[5] ^= m5;
|
||
|
h[4] ^= m4;
|
||
|
h[3] ^= c1;
|
||
|
h[2] ^= c0;
|
||
|
h[1] ^= m1;
|
||
|
h[0] ^= m0;
|
||
|
}
|
||
|
|
||
|
private void processFinal(int b0, int b1, int b2, int b3)
|
||
|
{
|
||
|
int[] rp = T256_0[b0];
|
||
|
int m0 = rp[0];
|
||
|
int m1 = rp[1];
|
||
|
int m2 = rp[2];
|
||
|
int m3 = rp[3];
|
||
|
int m4 = rp[4];
|
||
|
int m5 = rp[5];
|
||
|
int m6 = rp[6];
|
||
|
int m7 = rp[7];
|
||
|
rp = T256_1[b1];
|
||
|
m0 ^= rp[0];
|
||
|
m1 ^= rp[1];
|
||
|
m2 ^= rp[2];
|
||
|
m3 ^= rp[3];
|
||
|
m4 ^= rp[4];
|
||
|
m5 ^= rp[5];
|
||
|
m6 ^= rp[6];
|
||
|
m7 ^= rp[7];
|
||
|
rp = T256_2[b2];
|
||
|
m0 ^= rp[0];
|
||
|
m1 ^= rp[1];
|
||
|
m2 ^= rp[2];
|
||
|
m3 ^= rp[3];
|
||
|
m4 ^= rp[4];
|
||
|
m5 ^= rp[5];
|
||
|
m6 ^= rp[6];
|
||
|
m7 ^= rp[7];
|
||
|
rp = T256_3[b3];
|
||
|
m0 ^= rp[0];
|
||
|
m1 ^= rp[1];
|
||
|
m2 ^= rp[2];
|
||
|
m3 ^= rp[3];
|
||
|
m4 ^= rp[4];
|
||
|
m5 ^= rp[5];
|
||
|
m6 ^= rp[6];
|
||
|
m7 ^= rp[7];
|
||
|
|
||
|
int c0 = h[0];
|
||
|
int c1 = h[1];
|
||
|
int c2 = h[2];
|
||
|
int c3 = h[3];
|
||
|
int c4 = h[4];
|
||
|
int c5 = h[5];
|
||
|
int c6 = h[6];
|
||
|
int c7 = h[7];
|
||
|
int t;
|
||
|
|
||
|
for (int r = 0; r < 6; r ++) {
|
||
|
m0 ^= ALPHA_F[0x00];
|
||
|
m1 ^= ALPHA_F[0x01] ^ r;
|
||
|
c0 ^= ALPHA_F[0x02];
|
||
|
c1 ^= ALPHA_F[0x03];
|
||
|
c2 ^= ALPHA_F[0x08];
|
||
|
c3 ^= ALPHA_F[0x09];
|
||
|
m2 ^= ALPHA_F[0x0A];
|
||
|
m3 ^= ALPHA_F[0x0B];
|
||
|
m4 ^= ALPHA_F[0x10];
|
||
|
m5 ^= ALPHA_F[0x11];
|
||
|
c4 ^= ALPHA_F[0x12];
|
||
|
c5 ^= ALPHA_F[0x13];
|
||
|
c6 ^= ALPHA_F[0x18];
|
||
|
c7 ^= ALPHA_F[0x19];
|
||
|
m6 ^= ALPHA_F[0x1A];
|
||
|
m7 ^= ALPHA_F[0x1B];
|
||
|
t = m0;
|
||
|
m0 &= m4;
|
||
|
m0 ^= c6;
|
||
|
m4 ^= c2;
|
||
|
m4 ^= m0;
|
||
|
c6 |= t;
|
||
|
c6 ^= c2;
|
||
|
t ^= m4;
|
||
|
c2 = c6;
|
||
|
c6 |= t;
|
||
|
c6 ^= m0;
|
||
|
m0 &= c2;
|
||
|
t ^= m0;
|
||
|
c2 ^= c6;
|
||
|
c2 ^= t;
|
||
|
m0 = m4;
|
||
|
m4 = c2;
|
||
|
c2 = c6;
|
||
|
c6 = ~t;
|
||
|
t = m1;
|
||
|
m1 &= m5;
|
||
|
m1 ^= c7;
|
||
|
m5 ^= c3;
|
||
|
m5 ^= m1;
|
||
|
c7 |= t;
|
||
|
c7 ^= c3;
|
||
|
t ^= m5;
|
||
|
c3 = c7;
|
||
|
c7 |= t;
|
||
|
c7 ^= m1;
|
||
|
m1 &= c3;
|
||
|
t ^= m1;
|
||
|
c3 ^= c7;
|
||
|
c3 ^= t;
|
||
|
m1 = m5;
|
||
|
m5 = c3;
|
||
|
c3 = c7;
|
||
|
c7 = ~t;
|
||
|
t = c0;
|
||
|
c0 &= c4;
|
||
|
c0 ^= m6;
|
||
|
c4 ^= m2;
|
||
|
c4 ^= c0;
|
||
|
m6 |= t;
|
||
|
m6 ^= m2;
|
||
|
t ^= c4;
|
||
|
m2 = m6;
|
||
|
m6 |= t;
|
||
|
m6 ^= c0;
|
||
|
c0 &= m2;
|
||
|
t ^= c0;
|
||
|
m2 ^= m6;
|
||
|
m2 ^= t;
|
||
|
c0 = c4;
|
||
|
c4 = m2;
|
||
|
m2 = m6;
|
||
|
m6 = ~t;
|
||
|
t = c1;
|
||
|
c1 &= c5;
|
||
|
c1 ^= m7;
|
||
|
c5 ^= m3;
|
||
|
c5 ^= c1;
|
||
|
m7 |= t;
|
||
|
m7 ^= m3;
|
||
|
t ^= c5;
|
||
|
m3 = m7;
|
||
|
m7 |= t;
|
||
|
m7 ^= c1;
|
||
|
c1 &= m3;
|
||
|
t ^= c1;
|
||
|
m3 ^= m7;
|
||
|
m3 ^= t;
|
||
|
c1 = c5;
|
||
|
c5 = m3;
|
||
|
m3 = m7;
|
||
|
m7 = ~t;
|
||
|
m0 = (m0 << 13) | (m0 >>> (32 - 13));
|
||
|
c4 = (c4 << 3) | (c4 >>> (32 - 3));
|
||
|
c3 ^= m0 ^ c4;
|
||
|
m7 ^= c4 ^ (m0 << 3);
|
||
|
c3 = (c3 << 1) | (c3 >>> (32 - 1));
|
||
|
m7 = (m7 << 7) | (m7 >>> (32 - 7));
|
||
|
m0 ^= c3 ^ m7;
|
||
|
c4 ^= m7 ^ (c3 << 7);
|
||
|
m0 = (m0 << 5) | (m0 >>> (32 - 5));
|
||
|
c4 = (c4 << 22) | (c4 >>> (32 - 22));
|
||
|
m1 = (m1 << 13) | (m1 >>> (32 - 13));
|
||
|
c5 = (c5 << 3) | (c5 >>> (32 - 3));
|
||
|
m2 ^= m1 ^ c5;
|
||
|
c6 ^= c5 ^ (m1 << 3);
|
||
|
m2 = (m2 << 1) | (m2 >>> (32 - 1));
|
||
|
c6 = (c6 << 7) | (c6 >>> (32 - 7));
|
||
|
m1 ^= m2 ^ c6;
|
||
|
c5 ^= c6 ^ (m2 << 7);
|
||
|
m1 = (m1 << 5) | (m1 >>> (32 - 5));
|
||
|
c5 = (c5 << 22) | (c5 >>> (32 - 22));
|
||
|
c0 = (c0 << 13) | (c0 >>> (32 - 13));
|
||
|
m4 = (m4 << 3) | (m4 >>> (32 - 3));
|
||
|
m3 ^= c0 ^ m4;
|
||
|
c7 ^= m4 ^ (c0 << 3);
|
||
|
m3 = (m3 << 1) | (m3 >>> (32 - 1));
|
||
|
c7 = (c7 << 7) | (c7 >>> (32 - 7));
|
||
|
c0 ^= m3 ^ c7;
|
||
|
m4 ^= c7 ^ (m3 << 7);
|
||
|
c0 = (c0 << 5) | (c0 >>> (32 - 5));
|
||
|
m4 = (m4 << 22) | (m4 >>> (32 - 22));
|
||
|
c1 = (c1 << 13) | (c1 >>> (32 - 13));
|
||
|
m5 = (m5 << 3) | (m5 >>> (32 - 3));
|
||
|
c2 ^= c1 ^ m5;
|
||
|
m6 ^= m5 ^ (c1 << 3);
|
||
|
c2 = (c2 << 1) | (c2 >>> (32 - 1));
|
||
|
m6 = (m6 << 7) | (m6 >>> (32 - 7));
|
||
|
c1 ^= c2 ^ m6;
|
||
|
m5 ^= m6 ^ (c2 << 7);
|
||
|
c1 = (c1 << 5) | (c1 >>> (32 - 5));
|
||
|
m5 = (m5 << 22) | (m5 >>> (32 - 22));
|
||
|
}
|
||
|
|
||
|
h[7] ^= c5;
|
||
|
h[6] ^= c4;
|
||
|
h[5] ^= m5;
|
||
|
h[4] ^= m4;
|
||
|
h[3] ^= c1;
|
||
|
h[2] ^= c0;
|
||
|
h[1] ^= m1;
|
||
|
h[0] ^= m0;
|
||
|
}
|
||
|
|
||
|
/** @see Digest */
|
||
|
public String toString()
|
||
|
{
|
||
|
return "Hamsi-" + (getDigestLength() << 3);
|
||
|
}
|
||
|
}
|