mirror of
https://github.com/Qortal/Brooklyn.git
synced 2025-01-30 23:02:18 +00:00
353 lines
9.7 KiB
Java
353 lines
9.7 KiB
Java
// $Id: PANAMA.java 214 2010-06-03 17:25:08Z tp $
|
|
|
|
package fr.cryptohash;
|
|
|
|
/**
|
|
* This class implements the PANAMA digest algorithm under the
|
|
* {@link Digest} API.
|
|
*
|
|
* <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: 214 $
|
|
* @author Thomas Pornin <thomas.pornin@cryptolog.com>
|
|
*/
|
|
|
|
public class PANAMA extends DigestEngine {
|
|
|
|
/**
|
|
* Create the object.
|
|
*/
|
|
public PANAMA()
|
|
{
|
|
}
|
|
|
|
private int[] buffer;
|
|
private int bufferPtr;
|
|
private int state0, state1, state2, state3, state4, state5;
|
|
private int state6, state7, state8, state9, state10, state11;
|
|
private int state12, state13, state14, state15, state16;
|
|
private int inData0, inData1, inData2, inData3;
|
|
private int inData4, inData5, inData6, inData7;
|
|
|
|
/** @see Digest */
|
|
public Digest copy()
|
|
{
|
|
PANAMA d = new PANAMA();
|
|
System.arraycopy(buffer, 0, d.buffer, 0, buffer.length);
|
|
d.bufferPtr = bufferPtr;
|
|
d.state0 = state0 ;
|
|
d.state1 = state1 ;
|
|
d.state2 = state2 ;
|
|
d.state3 = state3 ;
|
|
d.state4 = state4 ;
|
|
d.state5 = state5 ;
|
|
d.state6 = state6 ;
|
|
d.state7 = state7 ;
|
|
d.state8 = state8 ;
|
|
d.state9 = state9 ;
|
|
d.state10 = state10;
|
|
d.state11 = state11;
|
|
d.state12 = state12;
|
|
d.state13 = state13;
|
|
d.state14 = state14;
|
|
d.state15 = state15;
|
|
d.state16 = state16;
|
|
return copyState(d);
|
|
}
|
|
|
|
/** @see Digest */
|
|
public int getDigestLength()
|
|
{
|
|
return 32;
|
|
}
|
|
|
|
/** @see Digest */
|
|
public int getBlockLength()
|
|
{
|
|
return 32;
|
|
}
|
|
|
|
/** @see DigestEngine */
|
|
protected void engineReset()
|
|
{
|
|
for (int i = 0; i < buffer.length; i ++)
|
|
buffer[i] = 0;
|
|
bufferPtr = 0;
|
|
state0 = 0;
|
|
state1 = 0;
|
|
state2 = 0;
|
|
state3 = 0;
|
|
state4 = 0;
|
|
state5 = 0;
|
|
state6 = 0;
|
|
state7 = 0;
|
|
state8 = 0;
|
|
state9 = 0;
|
|
state10 = 0;
|
|
state11 = 0;
|
|
state12 = 0;
|
|
state13 = 0;
|
|
state14 = 0;
|
|
state15 = 0;
|
|
state16 = 0;
|
|
}
|
|
|
|
/** @see DigestEngine */
|
|
protected void doPadding(byte[] output, int outputOffset)
|
|
{
|
|
int pending = flush();
|
|
update((byte)0x01);
|
|
for (int i = pending + 1; i < 32; i ++)
|
|
update((byte)0x00);
|
|
flush();
|
|
for (int i = 0; i < 32; i ++)
|
|
oneStep(false);
|
|
encodeLEInt(state9, output, outputOffset + 0);
|
|
encodeLEInt(state10, output, outputOffset + 4);
|
|
encodeLEInt(state11, output, outputOffset + 8);
|
|
encodeLEInt(state12, output, outputOffset + 12);
|
|
encodeLEInt(state13, output, outputOffset + 16);
|
|
encodeLEInt(state14, output, outputOffset + 20);
|
|
encodeLEInt(state15, output, outputOffset + 24);
|
|
encodeLEInt(state16, output, outputOffset + 28);
|
|
}
|
|
|
|
/** @see DigestEngine */
|
|
protected void doInit()
|
|
{
|
|
buffer = new int[256];
|
|
/*
|
|
* engineReset() is not needed because in Java, "int"
|
|
* variables and arrays of "int" are initialized upon
|
|
* creation to the correct value (full of zeroes).
|
|
*/
|
|
}
|
|
|
|
/**
|
|
* Encode the 32-bit word {@code val} into the array
|
|
* {@code buf} at offset {@code off}, in little-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 encodeLEInt(int val, byte[] buf, int off)
|
|
{
|
|
buf[off + 3] = (byte)((val >> 24) & 0xff);
|
|
buf[off + 2] = (byte)((val >> 16) & 0xff);
|
|
buf[off + 1] = (byte)((val >> 8) & 0xff);
|
|
buf[off + 0] = (byte)(val & 0xff);
|
|
}
|
|
|
|
/**
|
|
* Decode a 32-bit little-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 int decodeLEInt(byte[] buf, int off)
|
|
{
|
|
return (buf[off] & 0xFF)
|
|
| ((buf[off + 1] & 0xFF) << 8)
|
|
| ((buf[off + 2] & 0xFF) << 16)
|
|
| ((buf[off + 3] & 0xFF) << 24);
|
|
}
|
|
|
|
/** @see DigestEngine */
|
|
protected void processBlock(byte[] data)
|
|
{
|
|
inData0 = decodeLEInt(data, 0);
|
|
inData1 = decodeLEInt(data, 4);
|
|
inData2 = decodeLEInt(data, 8);
|
|
inData3 = decodeLEInt(data, 12);
|
|
inData4 = decodeLEInt(data, 16);
|
|
inData5 = decodeLEInt(data, 20);
|
|
inData6 = decodeLEInt(data, 24);
|
|
inData7 = decodeLEInt(data, 28);
|
|
oneStep(true);
|
|
}
|
|
|
|
private final void oneStep(boolean push)
|
|
{
|
|
/*
|
|
* Buffer update.
|
|
*/
|
|
int ptr0 = bufferPtr;
|
|
int ptr24 = (ptr0 - 64) & 248;
|
|
int ptr31 = (ptr0 - 8) & 248;
|
|
if (push) {
|
|
buffer[ptr24 + 0] ^= buffer[ptr31 + 2];
|
|
buffer[ptr31 + 2] ^= inData2;
|
|
buffer[ptr24 + 1] ^= buffer[ptr31 + 3];
|
|
buffer[ptr31 + 3] ^= inData3;
|
|
buffer[ptr24 + 2] ^= buffer[ptr31 + 4];
|
|
buffer[ptr31 + 4] ^= inData4;
|
|
buffer[ptr24 + 3] ^= buffer[ptr31 + 5];
|
|
buffer[ptr31 + 5] ^= inData5;
|
|
buffer[ptr24 + 4] ^= buffer[ptr31 + 6];
|
|
buffer[ptr31 + 6] ^= inData6;
|
|
buffer[ptr24 + 5] ^= buffer[ptr31 + 7];
|
|
buffer[ptr31 + 7] ^= inData7;
|
|
buffer[ptr24 + 6] ^= buffer[ptr31 + 0];
|
|
buffer[ptr31 + 0] ^= inData0;
|
|
buffer[ptr24 + 7] ^= buffer[ptr31 + 1];
|
|
buffer[ptr31 + 1] ^= inData1;
|
|
} else {
|
|
buffer[ptr24 + 0] ^= buffer[ptr31 + 2];
|
|
buffer[ptr31 + 2] ^= state3;
|
|
buffer[ptr24 + 1] ^= buffer[ptr31 + 3];
|
|
buffer[ptr31 + 3] ^= state4;
|
|
buffer[ptr24 + 2] ^= buffer[ptr31 + 4];
|
|
buffer[ptr31 + 4] ^= state5;
|
|
buffer[ptr24 + 3] ^= buffer[ptr31 + 5];
|
|
buffer[ptr31 + 5] ^= state6;
|
|
buffer[ptr24 + 4] ^= buffer[ptr31 + 6];
|
|
buffer[ptr31 + 6] ^= state7;
|
|
buffer[ptr24 + 5] ^= buffer[ptr31 + 7];
|
|
buffer[ptr31 + 7] ^= state8;
|
|
buffer[ptr24 + 6] ^= buffer[ptr31 + 0];
|
|
buffer[ptr31 + 0] ^= state1;
|
|
buffer[ptr24 + 7] ^= buffer[ptr31 + 1];
|
|
buffer[ptr31 + 1] ^= state2;
|
|
}
|
|
bufferPtr = ptr31;
|
|
|
|
/*
|
|
* Gamma transform.
|
|
*/
|
|
int g0, g1, g2, g3, g4, g5, g6, g7, g8, g9;
|
|
int g10, g11, g12, g13, g14, g15, g16;
|
|
g0 = state0 ^ (state1 | ~state2 );
|
|
g1 = state1 ^ (state2 | ~state3 );
|
|
g2 = state2 ^ (state3 | ~state4 );
|
|
g3 = state3 ^ (state4 | ~state5 );
|
|
g4 = state4 ^ (state5 | ~state6 );
|
|
g5 = state5 ^ (state6 | ~state7 );
|
|
g6 = state6 ^ (state7 | ~state8 );
|
|
g7 = state7 ^ (state8 | ~state9 );
|
|
g8 = state8 ^ (state9 | ~state10);
|
|
g9 = state9 ^ (state10 | ~state11);
|
|
g10 = state10 ^ (state11 | ~state12);
|
|
g11 = state11 ^ (state12 | ~state13);
|
|
g12 = state12 ^ (state13 | ~state14);
|
|
g13 = state13 ^ (state14 | ~state15);
|
|
g14 = state14 ^ (state15 | ~state16);
|
|
g15 = state15 ^ (state16 | ~state0 );
|
|
g16 = state16 ^ (state0 | ~state1 );
|
|
|
|
/*
|
|
* Pi transform.
|
|
*/
|
|
int p0, p1, p2, p3, p4, p5, p6, p7, p8, p9;
|
|
int p10, p11, p12, p13, p14, p15, p16;
|
|
p0 = g0;
|
|
p1 = ( g7 << 1) | ( g7 >>> (32 - 1));
|
|
p2 = (g14 << 3) | (g14 >>> (32 - 3));
|
|
p3 = ( g4 << 6) | ( g4 >>> (32 - 6));
|
|
p4 = (g11 << 10) | (g11 >>> (32 - 10));
|
|
p5 = ( g1 << 15) | ( g1 >>> (32 - 15));
|
|
p6 = ( g8 << 21) | ( g8 >>> (32 - 21));
|
|
p7 = (g15 << 28) | (g15 >>> (32 - 28));
|
|
p8 = ( g5 << 4) | ( g5 >>> (32 - 4));
|
|
p9 = (g12 << 13) | (g12 >>> (32 - 13));
|
|
p10 = ( g2 << 23) | ( g2 >>> (32 - 23));
|
|
p11 = ( g9 << 2) | ( g9 >>> (32 - 2));
|
|
p12 = (g16 << 14) | (g16 >>> (32 - 14));
|
|
p13 = ( g6 << 27) | ( g6 >>> (32 - 27));
|
|
p14 = (g13 << 9) | (g13 >>> (32 - 9));
|
|
p15 = ( g3 << 24) | ( g3 >>> (32 - 24));
|
|
p16 = (g10 << 8) | (g10 >>> (32 - 8));
|
|
|
|
/*
|
|
* Theta transform.
|
|
*/
|
|
int t0, t1, t2, t3, t4, t5, t6, t7, t8, t9;
|
|
int t10, t11, t12, t13, t14, t15, t16;
|
|
t0 = p0 ^ p1 ^ p4 ;
|
|
t1 = p1 ^ p2 ^ p5 ;
|
|
t2 = p2 ^ p3 ^ p6 ;
|
|
t3 = p3 ^ p4 ^ p7 ;
|
|
t4 = p4 ^ p5 ^ p8 ;
|
|
t5 = p5 ^ p6 ^ p9 ;
|
|
t6 = p6 ^ p7 ^ p10;
|
|
t7 = p7 ^ p8 ^ p11;
|
|
t8 = p8 ^ p9 ^ p12;
|
|
t9 = p9 ^ p10 ^ p13;
|
|
t10 = p10 ^ p11 ^ p14;
|
|
t11 = p11 ^ p12 ^ p15;
|
|
t12 = p12 ^ p13 ^ p16;
|
|
t13 = p13 ^ p14 ^ p0 ;
|
|
t14 = p14 ^ p15 ^ p1 ;
|
|
t15 = p15 ^ p16 ^ p2 ;
|
|
t16 = p16 ^ p0 ^ p3 ;
|
|
|
|
/*
|
|
* Sigma transform.
|
|
*/
|
|
int ptr16 = ptr0 ^ 128;
|
|
state0 = t0 ^ 1;
|
|
if (push) {
|
|
state1 = t1 ^ inData0;
|
|
state2 = t2 ^ inData1;
|
|
state3 = t3 ^ inData2;
|
|
state4 = t4 ^ inData3;
|
|
state5 = t5 ^ inData4;
|
|
state6 = t6 ^ inData5;
|
|
state7 = t7 ^ inData6;
|
|
state8 = t8 ^ inData7;
|
|
} else {
|
|
int ptr4 = (ptr0 + 32) & 248;
|
|
state1 = t1 ^ buffer[ptr4 + 0];
|
|
state2 = t2 ^ buffer[ptr4 + 1];
|
|
state3 = t3 ^ buffer[ptr4 + 2];
|
|
state4 = t4 ^ buffer[ptr4 + 3];
|
|
state5 = t5 ^ buffer[ptr4 + 4];
|
|
state6 = t6 ^ buffer[ptr4 + 5];
|
|
state7 = t7 ^ buffer[ptr4 + 6];
|
|
state8 = t8 ^ buffer[ptr4 + 7];
|
|
}
|
|
state9 = t9 ^ buffer[ptr16 + 0];
|
|
state10 = t10 ^ buffer[ptr16 + 1];
|
|
state11 = t11 ^ buffer[ptr16 + 2];
|
|
state12 = t12 ^ buffer[ptr16 + 3];
|
|
state13 = t13 ^ buffer[ptr16 + 4];
|
|
state14 = t14 ^ buffer[ptr16 + 5];
|
|
state15 = t15 ^ buffer[ptr16 + 6];
|
|
state16 = t16 ^ buffer[ptr16 + 7];
|
|
}
|
|
|
|
/** @see Digest */
|
|
public String toString()
|
|
{
|
|
return "PANAMA";
|
|
}
|
|
}
|