QortalOS Brooklyn for Raspberry Pi 4
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.
 
 
 
 
 
 

352 lines
9.7 KiB

// $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 &lt;[email protected]&gt;
*/
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";
}
}