2098 lines
65 KiB
Java
2098 lines
65 KiB
Java
/* !!! Doost !!! */
|
|
|
|
/*
|
|
A Java implementation of BLAKE2B cryptographic digest algorithm.
|
|
|
|
Joubin Mohammad Houshyar <alphazero@sensesay.net>
|
|
bushwick, nyc
|
|
02-14-2014
|
|
|
|
--
|
|
|
|
To the extent possible under law, the author(s) have dedicated all copyright
|
|
and related and neighboring rights to this software to the public domain
|
|
worldwide. This software is distributed without any warranty.
|
|
|
|
You should have received a copy of the CC0 Public Domain Dedication along with
|
|
this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
|
|
*/
|
|
|
|
package com.tangem.wallet.cardano;
|
|
|
|
import java.io.PrintStream;
|
|
import java.io.Serializable;
|
|
import java.security.Key;
|
|
import java.security.spec.AlgorithmParameterSpec; // JCE not supported / anticipated ..
|
|
import java.util.Arrays;
|
|
|
|
import static com.tangem.wallet.cardano.Blake2b.Engine.Assert.assertFail;
|
|
import static com.tangem.wallet.cardano.Blake2b.Engine.Assert.exclusiveLowerBound;
|
|
import static com.tangem.wallet.cardano.Blake2b.Engine.Assert.inclusiveLowerBound;
|
|
import static com.tangem.wallet.cardano.Blake2b.Engine.Assert.inclusiveUpperBound;
|
|
import static com.tangem.wallet.cardano.Blake2b.Engine.LittleEndian.readInt;
|
|
import static com.tangem.wallet.cardano.Blake2b.Engine.LittleEndian.readLong;
|
|
import static com.tangem.wallet.cardano.Blake2b.Engine.LittleEndian.writeInt;
|
|
import static com.tangem.wallet.cardano.Blake2b.Engine.LittleEndian.writeLong;
|
|
|
|
|
|
|
|
/** */
|
|
public interface Blake2b {
|
|
// ---------------------------------------------------------------------
|
|
// Specification
|
|
// ---------------------------------------------------------------------
|
|
public interface Spec {
|
|
/** pblock size of blake2b */
|
|
int param_bytes = 64;
|
|
|
|
/** pblock size of blake2b */
|
|
int block_bytes = 128;
|
|
|
|
/** maximum digest size */
|
|
int max_digest_bytes = 64;
|
|
|
|
/** maximum key sie */
|
|
int max_key_bytes = 64;
|
|
|
|
/** maximum salt size */
|
|
int max_salt_bytes = 16;
|
|
|
|
/** maximum personalization string size */
|
|
int max_personalization_bytes = 16;
|
|
|
|
/** length of h space vector array */
|
|
int state_space_len = 8;
|
|
|
|
/** max tree fanout value */
|
|
int max_tree_fantout = 0xFF;
|
|
|
|
/** max tree depth value */
|
|
int max_tree_depth = 0xFF;
|
|
|
|
/** max tree leaf length value.Note that this has uint32 semantics
|
|
and thus 0xFFFFFFFF is used as max value limit. */
|
|
int max_tree_leaf_length = 0xFFFFFFFF;
|
|
|
|
/** max node offset value. Note that this has uint64 semantics
|
|
and thus 0xFFFFFFFFFFFFFFFFL is used as max value limit. */
|
|
long max_node_offset = 0xFFFFFFFFFFFFFFFFL;
|
|
|
|
/** max tree inner length value */
|
|
int max_tree_inner_length = 0xFF;
|
|
|
|
/** initialization values map ref-Spec IV[i] -> slice iv[i*8:i*8+7] */
|
|
long[] IV = {
|
|
0x6a09e667f3bcc908L,
|
|
0xbb67ae8584caa73bL,
|
|
0x3c6ef372fe94f82bL,
|
|
0xa54ff53a5f1d36f1L,
|
|
0x510e527fade682d1L,
|
|
0x9b05688c2b3e6c1fL,
|
|
0x1f83d9abfb41bd6bL,
|
|
0x5be0cd19137e2179L
|
|
};
|
|
}
|
|
|
|
// ---------------------------------------------------------------------
|
|
// API
|
|
// ---------------------------------------------------------------------
|
|
// TODO add ByteBuffer variants
|
|
|
|
/**
|
|
* A serializable / JSON-izable object usable for pausing a hash-in-process
|
|
* which can then be resumed with the same Parameter the original digest
|
|
* was constructed with, and fed additional bytes to conclude the hash.
|
|
*/
|
|
public static final class ResumeHandle implements Serializable {
|
|
/** per spec */
|
|
public long[] h = new long [ 8 ];
|
|
/** per spec */
|
|
public long[] t = new long [ 2 ];
|
|
/** per spec */
|
|
public long[] f = new long [ 2 ];
|
|
/** per spec (tree) */
|
|
public boolean last_node = false;
|
|
/** pulled up 2b optimal */
|
|
public long[] m = new long [16];
|
|
/** pulled up 2b optimal */
|
|
public long[] v = new long [16];
|
|
|
|
/** compressor cache buffer */
|
|
public byte[] buffer;
|
|
/** compressor cache buffer offset/cached data length */
|
|
public int buflen;
|
|
|
|
/** digest length from init param - copied here on init */
|
|
public int outlen;
|
|
|
|
public int type;
|
|
|
|
/**
|
|
* Create a reconstituted Black2b digest from
|
|
*
|
|
* @param param
|
|
* @return
|
|
*/
|
|
public Blake2b resume(Param param) {
|
|
assert this.buffer != null && this.buffer.length == Spec.block_bytes;
|
|
assert this.h != null && this.h.length == 8
|
|
&& this.t != null && this.t.length == 2
|
|
&& this.f != null && this.f.length == 2
|
|
&& this.m != null && this.m.length == 16
|
|
&& this.v != null && this.v.length == 16 : "Data is corrupted";
|
|
assert this.outlen == param.getDigestLength() : "Not originally initialized from this param";
|
|
assert this.type == 1 || this.type == 2 : "Unknown type " + this.type;
|
|
Engine.State state = new Engine.State(outlen, this.type == 1);
|
|
System.arraycopy(this.h, 0, state.h, 0, state.h.length);
|
|
System.arraycopy(this.t, 0, state.t, 0, state.t.length);
|
|
System.arraycopy(this.f, 0, state.f, 0, state.f.length);
|
|
System.arraycopy(this.m, 0, m, 0, m.length);
|
|
System.arraycopy(this.v, 0, v, 0, v.length);
|
|
System.arraycopy(this.buffer, 0, state.buffer, 0, state.buffer.length);
|
|
state.buflen = buflen;
|
|
return type == 1 ? new Mac(param, state) : new Digest(param, state);
|
|
}
|
|
}
|
|
|
|
/** */
|
|
void update(byte[] input) ;
|
|
|
|
/** */
|
|
void update(byte input) ;
|
|
|
|
/** */
|
|
void update(byte[] input, int offset, int len) ;
|
|
|
|
/** */
|
|
byte[] digest() ;
|
|
|
|
/** */
|
|
byte[] digest(byte[] input) ;
|
|
|
|
/** */
|
|
void digest(byte[] output, int offset, int len) ;
|
|
|
|
/** */
|
|
void reset() ;
|
|
|
|
ResumeHandle state();
|
|
// ---------------------------------------------------------------------
|
|
// Blake2b Message Digest
|
|
// ---------------------------------------------------------------------
|
|
|
|
/** Generalized Blake2b digest. */
|
|
public static class Digest extends Engine implements Blake2b {
|
|
private Digest (final Param p) { super (p); }
|
|
private Digest () { super (); }
|
|
private Digest(Param p, State state) {
|
|
super(state, p);
|
|
}
|
|
|
|
public static Digest newInstance () {
|
|
return new Digest ();
|
|
}
|
|
public static Digest newInstance (final int digestLength) {
|
|
return new Digest (new Param().setDigestLength(digestLength));
|
|
}
|
|
public static Digest newInstance (Param p) {
|
|
return new Digest (p);
|
|
}
|
|
public static Digest newInstance (Param p, State state) {
|
|
return new Digest(p, state);
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------
|
|
// Blake2b Message Authentication Code
|
|
// ---------------------------------------------------------------------
|
|
|
|
/** Message Authentication Code (MAC) digest. */
|
|
public static class Mac extends Engine implements Blake2b {
|
|
private Mac (final Param p, State state) { super (state, p); }
|
|
private Mac (final Param p) { super (p); }
|
|
private Mac () { super (); }
|
|
|
|
/** Blake2b.MAC 512 - using default Blake2b.Spec settings with given key */
|
|
public static Mac newInstance (final byte[] key) {
|
|
return new Mac (new Param().setKey(key));
|
|
}
|
|
/** Blake2b.MAC - using default Blake2b.Spec settings with given key, with given digest length */
|
|
public static Mac newInstance (final byte[] key, final int digestLength) {
|
|
return new Mac (new Param().setKey(key).setDigestLength(digestLength));
|
|
}
|
|
/** Blake2b.MAC - using default Blake2b.Spec settings with given java.security.Key, with given digest length */
|
|
public static Mac newInstance (final Key key, final int digestLength) {
|
|
return new Mac (new Param().setKey(key).setDigestLength(digestLength));
|
|
}
|
|
/** Blake2b.MAC - using the specified Parameters.
|
|
* @param p asserted valid configured Param with key */
|
|
public static Mac newInstance (Param p) {
|
|
assert p != null : "Param (p) is null";
|
|
assert p.hasKey() : "Param (p) not configured with a key";
|
|
return new Mac (p);
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------
|
|
// Blake2b Incremental Message Digest (Tree)
|
|
// ---------------------------------------------------------------------
|
|
|
|
/**
|
|
* Note that Tree is just a convenience class; incremental hash (tree)
|
|
* can be done directly with the Digest class.
|
|
* <br>
|
|
* Further node, that tree does NOT accumulate the leaf hashes --
|
|
* you need to do that
|
|
*/
|
|
public static class Tree {
|
|
|
|
final int depth;
|
|
final int fanout;
|
|
final int leaf_length;
|
|
final int inner_length;
|
|
final int digest_length;
|
|
|
|
/**
|
|
*
|
|
* @param fanout
|
|
* @param depth
|
|
* @param leaf_length size of data input for leaf nodes.
|
|
* @param inner_length note this is used also as digest-length for non-root nodes.
|
|
* @param digest_length final hash out digest-length for the tree
|
|
*/
|
|
public Tree (
|
|
final int depth,
|
|
final int fanout,
|
|
final int leaf_length,
|
|
final int inner_length,
|
|
final int digest_length
|
|
) {
|
|
this.fanout = fanout;
|
|
this.depth = depth;
|
|
this.leaf_length = leaf_length;
|
|
this.inner_length = inner_length;
|
|
this.digest_length = digest_length;
|
|
}
|
|
private Param treeParam() {
|
|
return new Param().
|
|
setDepth(depth).setFanout(fanout).setLeafLength(leaf_length).setInnerLength(inner_length);
|
|
}
|
|
/** returns the Digest for tree node @ (depth, offset) */
|
|
public final Digest getNode (final int depth, final int offset) {
|
|
final Param nodeParam = treeParam().setNodeDepth(depth).setNodeOffset(offset).setDigestLength(inner_length);
|
|
return Digest.newInstance(nodeParam);
|
|
}
|
|
/** returns the Digest for root node */
|
|
public final Digest getRoot () {
|
|
final int depth = this.depth - 1;
|
|
final Param rootParam = treeParam().setNodeDepth(depth).setNodeOffset(0L).setDigestLength(digest_length);
|
|
return Digest.newInstance(rootParam);
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------
|
|
// Engine
|
|
// ---------------------------------------------------------------------
|
|
static class Engine implements Blake2b {
|
|
|
|
// ---------------------------------------------------------------------
|
|
// Blake2b State(+) per reference implementation
|
|
// ---------------------------------------------------------------------
|
|
// REVU: address last_node TODO part of the Tree/incremental
|
|
static final class State {
|
|
/** per spec */
|
|
private final long[] h = new long [ 8 ];
|
|
/** per spec */
|
|
private final long[] t = new long [ 2 ];
|
|
/** per spec */
|
|
private final long[] f = new long [ 2 ];
|
|
/** per spec (tree) */
|
|
private boolean last_node = false;
|
|
/** pulled up 2b optimal */
|
|
private final long[] m = new long [16];
|
|
/** pulled up 2b optimal */
|
|
private final long[] v = new long [16];
|
|
|
|
/** compressor cache buffer */
|
|
private final byte[] buffer;
|
|
/** compressor cache buffer offset/cached data length */
|
|
private int buflen;
|
|
|
|
/** digest length from init param - copied here on init */
|
|
private final int outlen;
|
|
|
|
private final int digestType;
|
|
|
|
State(int digestLength, boolean isMac) {
|
|
this.buffer = new byte [ Spec.block_bytes ];
|
|
this.outlen = digestLength;
|
|
// do not use zero, so we can detect serialization errors
|
|
this.digestType = isMac ? 1 : 2;
|
|
}
|
|
|
|
public ResumeHandle toResumableForm() {
|
|
ResumeHandle state = new ResumeHandle();
|
|
state.h = h;
|
|
state.t = t;
|
|
state.f = f;
|
|
state.last_node = last_node;
|
|
state.m = m;
|
|
state.v = v;
|
|
state.buffer = buffer;
|
|
state.buflen = buflen;
|
|
state.outlen = outlen;
|
|
state.type = digestType;
|
|
return state;
|
|
}
|
|
}
|
|
|
|
private State state;
|
|
/** configuration params */
|
|
private final Param param;
|
|
|
|
/** read only */
|
|
private static byte[] zeropad = new byte [ Spec.block_bytes ];
|
|
|
|
/** a little bit of semantics */
|
|
interface flag {
|
|
int last_block = 0;
|
|
int last_node = 1;
|
|
}
|
|
/** to support update(byte) */
|
|
private final byte[] oneByte = new byte[1];
|
|
|
|
// ---------------------------------------------------------------------
|
|
// Ctor & Initialization
|
|
// ---------------------------------------------------------------------
|
|
|
|
/** Basic use constructor pending (TODO) JCA/JCE compliance */
|
|
Engine () {
|
|
this( new Param() );
|
|
}
|
|
|
|
Engine(State state, Param param) {
|
|
assert state != null : "state is null";
|
|
assert param != null : "param is null";
|
|
this.state = state;
|
|
this.param = param;
|
|
}
|
|
|
|
/** User provided Param for custom configurations */
|
|
Engine (final Param param) {
|
|
assert param != null : "param is null";
|
|
this.param = param;
|
|
state = new State(param.getDigestLength(), this instanceof Mac);
|
|
if ( param.getDepth() > Param.Default.depth ) {
|
|
final int ndepth = param.getNodeDepth();
|
|
final long nxoff = param.getNodeOffset();
|
|
if (ndepth == param.getDepth() - 1) {
|
|
state.last_node = true;
|
|
assert nxoff == 0 : "root must have offset of zero";
|
|
} else if ( nxoff == param.getFanout() - 1) {
|
|
this.state.last_node = true;
|
|
}
|
|
}
|
|
|
|
initialize();
|
|
}
|
|
|
|
public ResumeHandle state() {
|
|
return state.toResumableForm();
|
|
}
|
|
|
|
private void initialize () {
|
|
// state vector h - copy values to address reset() requests
|
|
System.arraycopy( param.initialized_H(), 0, this.state.h, 0, Spec.state_space_len);
|
|
|
|
// if we have a key update initial block
|
|
// Note param has zero padded key_bytes to Spec.max_key_bytes
|
|
if(param.hasKey){
|
|
this.update (param.key_bytes, 0, Spec.block_bytes);
|
|
}
|
|
}
|
|
|
|
public static void main(String... args) {
|
|
Blake2b mac = Mac.newInstance("LOVE".getBytes());
|
|
final byte[] hash = mac.digest("Salaam!".getBytes());
|
|
// Debug.dumpBuffer(System.out, "-- mac hash --", hash);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------
|
|
// interface: Blake2b API
|
|
// ---------------------------------------------------------------------
|
|
|
|
/** {@inheritDoc} */
|
|
@Override final public void reset () {
|
|
// reset cache
|
|
this.state.buflen = 0;
|
|
for(int i=0; i < state.buffer.length; i++){
|
|
state.buffer[ i ] = (byte) 0;
|
|
}
|
|
|
|
// reset flags
|
|
this.state.f[ 0 ] = 0L;
|
|
this.state.f[ 1 ] = 0L;
|
|
|
|
// reset counters
|
|
this.state.t[ 0 ] = 0L;
|
|
this.state.t[ 1 ] = 0L;
|
|
|
|
// reset state vector
|
|
// NOTE: keep as last stmt as init calls update0 for MACs.
|
|
initialize();
|
|
}
|
|
|
|
/** {@inheritDoc} */
|
|
@Override final public void update (final byte[] b, int off, int len) {
|
|
if (b == null) {
|
|
throw new IllegalArgumentException("input buffer (b) is null");
|
|
}
|
|
/* zero or more calls to compress */
|
|
final long[] t = state.t;
|
|
final byte[] buffer = state.buffer;
|
|
while (len > 0) {
|
|
if ( state.buflen == 0) {
|
|
/* try compressing direct from input ? */
|
|
while ( len > Spec.block_bytes ) {
|
|
t[0] += Spec.block_bytes;
|
|
t[1] += (t[0] < 0 && state.buflen > -t[0]) ? 1 : 0;
|
|
compress( b, off);
|
|
len -= Spec.block_bytes;
|
|
off += Spec.block_bytes;
|
|
}
|
|
} else if ( state.buflen == Spec.block_bytes ) {
|
|
/* flush */
|
|
t[0] += Spec.block_bytes;
|
|
t[1] += t[0] == 0 ? 1 : 0;
|
|
compress( buffer, 0 );
|
|
state.buflen = 0;
|
|
continue;
|
|
}
|
|
|
|
// "are we there yet?"
|
|
if( len == 0 ) return;
|
|
|
|
final int cap = Spec.block_bytes - state.buflen;
|
|
final int fill = len > cap ? cap : len;
|
|
System.arraycopy( b, off, buffer, state.buflen, fill );
|
|
state.buflen += fill;
|
|
len -= fill;
|
|
off += fill;
|
|
}
|
|
}
|
|
|
|
/** {@inheritDoc} */
|
|
@Override final public void update (byte b) {
|
|
oneByte[0] = b;
|
|
update (oneByte, 0, 1);
|
|
}
|
|
|
|
/** {@inheritDoc} */
|
|
@Override final public void update(byte[] input) {
|
|
update (input, 0, input.length);
|
|
}
|
|
|
|
/** {@inheritDoc} */
|
|
@Override final public void digest(byte[] output, int off, int len) {
|
|
// zero pad last block; set last block flags; and compress
|
|
System.arraycopy( zeropad, 0, state.buffer, state.buflen, Spec.block_bytes - state.buflen);
|
|
if(state.buflen > 0) {
|
|
this.state.t[0] += state.buflen;
|
|
this.state.t[1] += this.state.t[0] == 0 ? 1 : 0;
|
|
}
|
|
|
|
this.state.f[ flag.last_block ] = 0xFFFFFFFFFFFFFFFFL;
|
|
this.state.f[ flag.last_node ] = this.state.last_node ? 0xFFFFFFFFFFFFFFFFL : 0x0L;
|
|
|
|
// compres and write final out (truncated to len) to output
|
|
compress( state.buffer, 0 );
|
|
hashout( output, off, len );
|
|
|
|
reset();
|
|
}
|
|
|
|
/** {@inheritDoc} */
|
|
@Override final public byte[] digest () throws IllegalArgumentException {
|
|
final byte[] out = new byte [state.outlen];
|
|
digest ( out, 0, state.outlen );
|
|
return out;
|
|
}
|
|
|
|
/** {@inheritDoc} */
|
|
@Override final public byte[] digest (byte[] input) {
|
|
update(input, 0, input.length);
|
|
return digest();
|
|
}
|
|
|
|
// ---------------------------------------------------------------------
|
|
// Internal Ops
|
|
// ---------------------------------------------------------------------
|
|
|
|
/**
|
|
* write out the digest output from the 'h' registers.
|
|
* truncate full output if necessary.
|
|
*/
|
|
private void hashout (final byte[] out, final int offset, final int hashlen) {
|
|
// write max number of whole longs
|
|
final int lcnt = hashlen >>> 3;
|
|
long v = 0;
|
|
int i = offset;
|
|
final long[] h = state.h;
|
|
for (int w = 0; w < lcnt; w++) {
|
|
v = h [ w ];
|
|
out [ i ] = (byte) v; v >>>= 8;
|
|
out [ i+1 ] = (byte) v; v >>>= 8;
|
|
out [ i+2 ] = (byte) v; v >>>= 8;
|
|
out [ i+3 ] = (byte) v; v >>>= 8;
|
|
out [ i+4 ] = (byte) v; v >>>= 8;
|
|
out [ i+5 ] = (byte) v; v >>>= 8;
|
|
out [ i+6 ] = (byte) v; v >>>= 8;
|
|
out [ i+7 ] = (byte) v;
|
|
i+=8;
|
|
}
|
|
|
|
// basta?
|
|
if( hashlen == Spec.max_digest_bytes) return;
|
|
|
|
// write the remaining bytes of a partial long value
|
|
v = h [ lcnt ];
|
|
i = lcnt << 3;
|
|
while( i < hashlen ) {
|
|
out [ offset + i ] = (byte) v; v >>>= 8; ++i;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// Compression Kernel /////////////////////////////////////////// BEGIN
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
/** compress Spec.block_bytes data from b, from offset */
|
|
private void compress (final byte[] b, final int offset) {
|
|
|
|
// set m registers
|
|
final long[] m = state.m;
|
|
m[ 0] = LittleEndian.readLong(b, offset);
|
|
m[ 1] = LittleEndian.readLong(b, offset + 8);
|
|
m[ 2] = LittleEndian.readLong(b, offset + 16);
|
|
m[ 3] = LittleEndian.readLong(b, offset + 24);
|
|
m[ 4] = LittleEndian.readLong(b, offset + 32);
|
|
m[ 5] = LittleEndian.readLong(b, offset + 40);
|
|
m[ 6] = LittleEndian.readLong(b, offset + 48);
|
|
m[ 7] = LittleEndian.readLong(b, offset + 56);
|
|
m[ 8] = LittleEndian.readLong(b, offset + 64);
|
|
m[ 9] = LittleEndian.readLong(b, offset + 72);
|
|
m[10] = LittleEndian.readLong(b, offset + 80);
|
|
m[11] = LittleEndian.readLong(b, offset + 88);
|
|
m[12] = LittleEndian.readLong(b, offset + 96);
|
|
m[13] = LittleEndian.readLong(b, offset + 104);
|
|
m[14] = LittleEndian.readLong(b, offset + 112);
|
|
m[15] = LittleEndian.readLong(b, offset + 120);
|
|
|
|
// set v registers
|
|
final long[] v = state.v;
|
|
final long[] h = state.h;
|
|
final long[] t = state.t;
|
|
final long[] f = state.f;
|
|
v[ 0] = h[0];
|
|
v[ 1] = h[1];
|
|
v[ 2] = h[2];
|
|
v[ 3] = h[3];
|
|
v[ 4] = h[4];
|
|
v[ 5] = h[5];
|
|
v[ 6] = h[6];
|
|
v[ 7] = h[7];
|
|
v[ 8] = 0x6a09e667f3bcc908L;
|
|
v[ 9] = 0xbb67ae8584caa73bL;
|
|
v[10] = 0x3c6ef372fe94f82bL;
|
|
v[11] = 0xa54ff53a5f1d36f1L;
|
|
v[12] = t [0] ^ 0x510e527fade682d1L;
|
|
v[13] = t [1] ^ 0x9b05688c2b3e6c1fL;
|
|
v[14] = f [0] ^ 0x1f83d9abfb41bd6bL;
|
|
v[15] = f [1] ^ 0x5be0cd19137e2179L;
|
|
|
|
// do the rounds
|
|
round_0(v, m);
|
|
round_1(v, m);
|
|
round_2(v, m);
|
|
round_3(v, m);
|
|
round_4(v, m);
|
|
round_5(v, m);
|
|
round_6(v, m);
|
|
round_7(v, m);
|
|
round_8(v, m);
|
|
round_9(v, m);
|
|
round_0(v, m); // round 10 is identical to round 0
|
|
round_1(v, m); // round 11 is identical to round 1
|
|
|
|
// Update state vector h
|
|
h[0] ^= v[0] ^ v[8];
|
|
h[1] ^= v[1] ^ v[9];
|
|
h[2] ^= v[2] ^ v[10];
|
|
h[3] ^= v[3] ^ v[11];
|
|
h[4] ^= v[4] ^ v[12];
|
|
h[5] ^= v[5] ^ v[13];
|
|
h[6] ^= v[6] ^ v[14];
|
|
h[7] ^= v[7] ^ v[15];
|
|
|
|
/* kaamil */
|
|
}
|
|
private void round_0(final long[] v, final long[] m) {
|
|
v[ 0] = v[ 0] + v[ 4] + m[0];
|
|
v[12] ^= v[ 0];
|
|
v[12] = ( v[12] << 32 ) | ( v[12] >>> 32 );
|
|
v[ 8] = v[ 8] + v[12];
|
|
v[ 4] ^= v[ 8];
|
|
v[ 4] = ( v[ 4] >>> 24 ) | ( v[ 4] << 40 );
|
|
v[ 0] = v[ 0] + v[ 4] + m [1];
|
|
v[12] ^= v[ 0];
|
|
v[12] = ( v[12] >>> 16 ) | ( v[12] << 48 );
|
|
v[ 8] = v[ 8] + v[12];
|
|
v[ 4] ^= v[ 8];
|
|
v[ 4] = ( v[ 4] << 1 ) | ( v[ 4] >>> 63 );
|
|
|
|
v[ 1] = v[ 1] + v[ 5] + m[2];
|
|
v[13] ^= v[ 1];
|
|
v[13] = ( v[13] << 32 ) | ( v[13] >>> 32 );
|
|
v[ 9] = v[ 9] + v[13];
|
|
v[ 5] ^= v[ 9];
|
|
v[ 5] = ( v[ 5] >>> 24 ) | ( v[ 5] << 40 );
|
|
v[ 1] = v[ 1] + v[ 5] + m[3];
|
|
v[13] ^= v[ 1];
|
|
v[13] = ( v[13] >>> 16 ) | ( v[13] << 48 );
|
|
v[ 9] = v[ 9] + v[13];
|
|
v[ 5] ^= v[ 9];
|
|
v[ 5] = ( v[ 5] << 1 ) | ( v[ 5] >>> 63 );
|
|
|
|
v[ 2] = v[ 2] + v[ 6] + m[4];
|
|
v[14] ^= v[ 2];
|
|
v[14] = ( v[14] << 32 ) | ( v[14] >>> 32 );
|
|
v[10] = v[10] + v[14];
|
|
v[ 6] ^= v[10];
|
|
v[ 6] = ( v[ 6] >>> 24 ) | ( v[ 6] << 40 );
|
|
v[ 2] = v[ 2] + v[ 6] + m[5];
|
|
v[14] ^= v[ 2];
|
|
v[14] = ( v[14] >>> 16 ) | ( v[14] << 48 );
|
|
v[10] = v[10] + v[14];
|
|
v[ 6] ^= v[10];
|
|
v[ 6] = ( v[ 6] << 1 ) | ( v[ 6] >>> 63 );
|
|
|
|
v[ 3] = v[ 3] + v[ 7] + m[6];
|
|
v[15] ^= v[ 3];
|
|
v[15] = ( v[15] << 32 ) | ( v[15] >>> 32 );
|
|
v[11] = v[11] + v[15];
|
|
v[ 7] ^= v[11];
|
|
v[ 7] = ( v[ 7] >>> 24 ) | ( v[ 7] << 40 );
|
|
v[ 3] = v[ 3] + v[ 7] + m[7];
|
|
v[15] ^= v[ 3];
|
|
v[15] = ( v[15] >>> 16 ) | ( v[15] << 48 );
|
|
v[11] = v[11] + v[15];
|
|
v[ 7] ^= v[11];
|
|
v[ 7] = ( v[ 7] << 1 ) | ( v[ 7] >>> 63 );
|
|
|
|
v[ 0] = v[ 0] + v[ 5] + m[8];
|
|
v[15] ^= v[ 0];
|
|
v[15] = ( v[15] << 32 ) | ( v[15] >>> 32 );
|
|
v[10] = v[10] + v[15];
|
|
v[ 5] ^= v[10];
|
|
v[ 5] = ( v[ 5] >>> 24 ) | ( v[ 5] << 40 );
|
|
v[ 0] = v[ 0] + v[ 5] + m[9];
|
|
v[15] ^= v[ 0];
|
|
v[15] = ( v[15] >>> 16 ) | ( v[15] << 48 );
|
|
v[10] = v[10] + v[15];
|
|
v[ 5] ^= v[10];
|
|
v[ 5] = ( v[ 5] << 1 ) | ( v[ 5] >>> 63 );
|
|
|
|
v[ 1] = v[ 1] + v[ 6] + m[10];
|
|
v[12] ^= v[ 1];
|
|
v[12] = ( v[12] << 32 ) | ( v[12] >>> 32 );
|
|
v[11] = v[11] + v[12];
|
|
v[ 6] ^= v[11];
|
|
v[ 6] = ( v[ 6] >>> 24 ) | ( v[ 6] << 40 );
|
|
v[ 1] = v[ 1] + v[ 6] + + m[11];
|
|
v[12] ^= v[ 1];
|
|
v[12] = ( v[12] >>> 16 ) | ( v[12] << 48 );
|
|
v[11] = v[11] + v[12];
|
|
v[ 6] ^= v[11];
|
|
v[ 6] = ( v[ 6] << 1 ) | ( v[ 6] >>> 63 );
|
|
|
|
v[ 2] = v[ 2] + v[ 7] + m[12];
|
|
v[13] ^= v[ 2];
|
|
v[13] = ( v[13] << 32 ) | ( v[13] >>> 32 );
|
|
v[ 8] = v[ 8] + v[13];
|
|
v[ 7] ^= v[ 8];
|
|
v[ 7] = ( v[ 7] >>> 24 ) | ( v[ 7] << 40 );
|
|
v[ 2] = v[ 2] + v[ 7] + m[13];
|
|
v[13] ^= v[ 2];
|
|
v[13] = ( v[13] >>> 16 ) | ( v[13] << 48 );
|
|
v[ 8] = v[ 8] + v[13];
|
|
v[ 7] ^= v[ 8];
|
|
v[ 7] = ( v[ 7] << 1 ) | ( v[ 7] >>> 63 );
|
|
|
|
v[ 3] = v[ 3] + v[ 4] + m[14];
|
|
v[14] ^= v[ 3];
|
|
v[14] = ( v[14] << 32 ) | ( v[14] >>> 32 );
|
|
v[ 9] = v[ 9] + v[14];
|
|
v[ 4] ^= v[ 9];
|
|
v[ 4] = ( v[ 4] >>> 24 ) | ( v[ 4] << 40 );
|
|
v[ 3] = v[ 3] + v[ 4] + m[15];
|
|
v[14] ^= v[ 3];
|
|
v[14] = ( v[14] >>> 16 ) | ( v[14] << 48 );
|
|
v[ 9] = v[ 9] + v[14];
|
|
v[ 4] ^= v[ 9];
|
|
v[ 4] = ( v[ 4] << 1 ) | ( v[ 4] >>> 63 );
|
|
}
|
|
private void round_1(final long[] v, final long[] m) {
|
|
v[ 0] = v[ 0] + v[ 4] + m[14];
|
|
v[12] ^= v[ 0];
|
|
v[12] = ( v[12] << 32 ) | ( v[12] >>> 32 );
|
|
v[ 8] = v[ 8] + v[12];
|
|
v[ 4] ^= v[ 8];
|
|
v[ 4] = ( v[ 4] >>> 24 ) | ( v[ 4] << 40 );
|
|
v[ 0] = v[ 0] + v[ 4] + m [10];
|
|
v[12] ^= v[ 0];
|
|
v[12] = ( v[12] >>> 16 ) | ( v[12] << 48 );
|
|
v[ 8] = v[ 8] + v[12];
|
|
v[ 4] ^= v[ 8];
|
|
v[ 4] = ( v[ 4] << 1 ) | ( v[ 4] >>> 63 );
|
|
|
|
v[ 1] = v[ 1] + v[ 5] + m[4];
|
|
v[13] ^= v[ 1];
|
|
v[13] = ( v[13] << 32 ) | ( v[13] >>> 32 );
|
|
v[ 9] = v[ 9] + v[13];
|
|
v[ 5] ^= v[ 9];
|
|
v[ 5] = ( v[ 5] >>> 24 ) | ( v[ 5] << 40 );
|
|
v[ 1] = v[ 1] + v[ 5] + m[8];
|
|
v[13] ^= v[ 1];
|
|
v[13] = ( v[13] >>> 16 ) | ( v[13] << 48 );
|
|
v[ 9] = v[ 9] + v[13];
|
|
v[ 5] ^= v[ 9];
|
|
v[ 5] = ( v[ 5] << 1 ) | ( v[ 5] >>> 63 );
|
|
|
|
v[ 2] = v[ 2] + v[ 6] + m[9];
|
|
v[14] ^= v[ 2];
|
|
v[14] = ( v[14] << 32 ) | ( v[14] >>> 32 );
|
|
v[10] = v[10] + v[14];
|
|
v[ 6] ^= v[10];
|
|
v[ 6] = ( v[ 6] >>> 24 ) | ( v[ 6] << 40 );
|
|
v[ 2] = v[ 2] + v[ 6] + m[15];
|
|
v[14] ^= v[ 2];
|
|
v[14] = ( v[14] >>> 16 ) | ( v[14] << 48 );
|
|
v[10] = v[10] + v[14];
|
|
v[ 6] ^= v[10];
|
|
v[ 6] = ( v[ 6] << 1 ) | ( v[ 6] >>> 63 );
|
|
|
|
v[ 3] = v[ 3] + v[ 7] + m[13];
|
|
v[15] ^= v[ 3];
|
|
v[15] = ( v[15] << 32 ) | ( v[15] >>> 32 );
|
|
v[11] = v[11] + v[15];
|
|
v[ 7] ^= v[11];
|
|
v[ 7] = ( v[ 7] >>> 24 ) | ( v[ 7] << 40 );
|
|
v[ 3] = v[ 3] + v[ 7] + m[6];
|
|
v[15] ^= v[ 3];
|
|
v[15] = ( v[15] >>> 16 ) | ( v[15] << 48 );
|
|
v[11] = v[11] + v[15];
|
|
v[ 7] ^= v[11];
|
|
v[ 7] = ( v[ 7] << 1 ) | ( v[ 7] >>> 63 );
|
|
|
|
v[ 0] = v[ 0] + v[ 5] + m[1];
|
|
v[15] ^= v[ 0];
|
|
v[15] = ( v[15] << 32 ) | ( v[15] >>> 32 );
|
|
v[10] = v[10] + v[15];
|
|
v[ 5] ^= v[10];
|
|
v[ 5] = ( v[ 5] >>> 24 ) | ( v[ 5] << 40 );
|
|
v[ 0] = v[ 0] + v[ 5] + m[12];
|
|
v[15] ^= v[ 0];
|
|
v[15] = ( v[15] >>> 16 ) | ( v[15] << 48 );
|
|
v[10] = v[10] + v[15];
|
|
v[ 5] ^= v[10];
|
|
v[ 5] = ( v[ 5] << 1 ) | ( v[ 5] >>> 63 );
|
|
|
|
v[ 1] = v[ 1] + v[ 6] + m[0];
|
|
v[12] ^= v[ 1];
|
|
v[12] = ( v[12] << 32 ) | ( v[12] >>> 32 );
|
|
v[11] = v[11] + v[12];
|
|
v[ 6] ^= v[11];
|
|
v[ 6] = ( v[ 6] >>> 24 ) | ( v[ 6] << 40 );
|
|
v[ 1] = v[ 1] + v[ 6] + + m[2];
|
|
v[12] ^= v[ 1];
|
|
v[12] = ( v[12] >>> 16 ) | ( v[12] << 48 );
|
|
v[11] = v[11] + v[12];
|
|
v[ 6] ^= v[11];
|
|
v[ 6] = ( v[ 6] << 1 ) | ( v[ 6] >>> 63 );
|
|
|
|
v[ 2] = v[ 2] + v[ 7] + m[11];
|
|
v[13] ^= v[ 2];
|
|
v[13] = ( v[13] << 32 ) | ( v[13] >>> 32 );
|
|
v[ 8] = v[ 8] + v[13];
|
|
v[ 7] ^= v[ 8];
|
|
v[ 7] = ( v[ 7] >>> 24 ) | ( v[ 7] << 40 );
|
|
v[ 2] = v[ 2] + v[ 7] + m[7];
|
|
v[13] ^= v[ 2];
|
|
v[13] = ( v[13] >>> 16 ) | ( v[13] << 48 );
|
|
v[ 8] = v[ 8] + v[13];
|
|
v[ 7] ^= v[ 8];
|
|
v[ 7] = ( v[ 7] << 1 ) | ( v[ 7] >>> 63 );
|
|
|
|
v[ 3] = v[ 3] + v[ 4] + m[5];
|
|
v[14] ^= v[ 3];
|
|
v[14] = ( v[14] << 32 ) | ( v[14] >>> 32 );
|
|
v[ 9] = v[ 9] + v[14];
|
|
v[ 4] ^= v[ 9];
|
|
v[ 4] = ( v[ 4] >>> 24 ) | ( v[ 4] << 40 );
|
|
v[ 3] = v[ 3] + v[ 4] + m[3];
|
|
v[14] ^= v[ 3];
|
|
v[14] = ( v[14] >>> 16 ) | ( v[14] << 48 );
|
|
v[ 9] = v[ 9] + v[14];
|
|
v[ 4] ^= v[ 9];
|
|
v[ 4] = ( v[ 4] << 1 ) | ( v[ 4] >>> 63 );
|
|
}
|
|
private void round_2(final long[] v, final long[] m) {
|
|
v[ 0] = v[ 0] + v[ 4] + m[11];
|
|
v[12] ^= v[ 0];
|
|
v[12] = ( v[12] << 32 ) | ( v[12] >>> 32 );
|
|
v[ 8] = v[ 8] + v[12];
|
|
v[ 4] ^= v[ 8];
|
|
v[ 4] = ( v[ 4] >>> 24 ) | ( v[ 4] << 40 );
|
|
v[ 0] = v[ 0] + v[ 4] + m [8];
|
|
v[12] ^= v[ 0];
|
|
v[12] = ( v[12] >>> 16 ) | ( v[12] << 48 );
|
|
v[ 8] = v[ 8] + v[12];
|
|
v[ 4] ^= v[ 8];
|
|
v[ 4] = ( v[ 4] << 1 ) | ( v[ 4] >>> 63 );
|
|
|
|
v[ 1] = v[ 1] + v[ 5] + m[12];
|
|
v[13] ^= v[ 1];
|
|
v[13] = ( v[13] << 32 ) | ( v[13] >>> 32 );
|
|
v[ 9] = v[ 9] + v[13];
|
|
v[ 5] ^= v[ 9];
|
|
v[ 5] = ( v[ 5] >>> 24 ) | ( v[ 5] << 40 );
|
|
v[ 1] = v[ 1] + v[ 5] + m[0];
|
|
v[13] ^= v[ 1];
|
|
v[13] = ( v[13] >>> 16 ) | ( v[13] << 48 );
|
|
v[ 9] = v[ 9] + v[13];
|
|
v[ 5] ^= v[ 9];
|
|
v[ 5] = ( v[ 5] << 1 ) | ( v[ 5] >>> 63 );
|
|
|
|
v[ 2] = v[ 2] + v[ 6] + m[5];
|
|
v[14] ^= v[ 2];
|
|
v[14] = ( v[14] << 32 ) | ( v[14] >>> 32 );
|
|
v[10] = v[10] + v[14];
|
|
v[ 6] ^= v[10];
|
|
v[ 6] = ( v[ 6] >>> 24 ) | ( v[ 6] << 40 );
|
|
v[ 2] = v[ 2] + v[ 6] + m[2];
|
|
v[14] ^= v[ 2];
|
|
v[14] = ( v[14] >>> 16 ) | ( v[14] << 48 );
|
|
v[10] = v[10] + v[14];
|
|
v[ 6] ^= v[10];
|
|
v[ 6] = ( v[ 6] << 1 ) | ( v[ 6] >>> 63 );
|
|
|
|
v[ 3] = v[ 3] + v[ 7] + m[15];
|
|
v[15] ^= v[ 3];
|
|
v[15] = ( v[15] << 32 ) | ( v[15] >>> 32 );
|
|
v[11] = v[11] + v[15];
|
|
v[ 7] ^= v[11];
|
|
v[ 7] = ( v[ 7] >>> 24 ) | ( v[ 7] << 40 );
|
|
v[ 3] = v[ 3] + v[ 7] + m[13];
|
|
v[15] ^= v[ 3];
|
|
v[15] = ( v[15] >>> 16 ) | ( v[15] << 48 );
|
|
v[11] = v[11] + v[15];
|
|
v[ 7] ^= v[11];
|
|
v[ 7] = ( v[ 7] << 1 ) | ( v[ 7] >>> 63 );
|
|
|
|
v[ 0] = v[ 0] + v[ 5] + m[10];
|
|
v[15] ^= v[ 0];
|
|
v[15] = ( v[15] << 32 ) | ( v[15] >>> 32 );
|
|
v[10] = v[10] + v[15];
|
|
v[ 5] ^= v[10];
|
|
v[ 5] = ( v[ 5] >>> 24 ) | ( v[ 5] << 40 );
|
|
v[ 0] = v[ 0] + v[ 5] + m[14];
|
|
v[15] ^= v[ 0];
|
|
v[15] = ( v[15] >>> 16 ) | ( v[15] << 48 );
|
|
v[10] = v[10] + v[15];
|
|
v[ 5] ^= v[10];
|
|
v[ 5] = ( v[ 5] << 1 ) | ( v[ 5] >>> 63 );
|
|
|
|
v[ 1] = v[ 1] + v[ 6] + m[3];
|
|
v[12] ^= v[ 1];
|
|
v[12] = ( v[12] << 32 ) | ( v[12] >>> 32 );
|
|
v[11] = v[11] + v[12];
|
|
v[ 6] ^= v[11];
|
|
v[ 6] = ( v[ 6] >>> 24 ) | ( v[ 6] << 40 );
|
|
v[ 1] = v[ 1] + v[ 6] + + m[6];
|
|
v[12] ^= v[ 1];
|
|
v[12] = ( v[12] >>> 16 ) | ( v[12] << 48 );
|
|
v[11] = v[11] + v[12];
|
|
v[ 6] ^= v[11];
|
|
v[ 6] = ( v[ 6] << 1 ) | ( v[ 6] >>> 63 );
|
|
|
|
v[ 2] = v[ 2] + v[ 7] + m[7];
|
|
v[13] ^= v[ 2];
|
|
v[13] = ( v[13] << 32 ) | ( v[13] >>> 32 );
|
|
v[ 8] = v[ 8] + v[13];
|
|
v[ 7] ^= v[ 8];
|
|
v[ 7] = ( v[ 7] >>> 24 ) | ( v[ 7] << 40 );
|
|
v[ 2] = v[ 2] + v[ 7] + m[1];
|
|
v[13] ^= v[ 2];
|
|
v[13] = ( v[13] >>> 16 ) | ( v[13] << 48 );
|
|
v[ 8] = v[ 8] + v[13];
|
|
v[ 7] ^= v[ 8];
|
|
v[ 7] = ( v[ 7] << 1 ) | ( v[ 7] >>> 63 );
|
|
|
|
v[ 3] = v[ 3] + v[ 4] + m[9];
|
|
v[14] ^= v[ 3];
|
|
v[14] = ( v[14] << 32 ) | ( v[14] >>> 32 );
|
|
v[ 9] = v[ 9] + v[14];
|
|
v[ 4] ^= v[ 9];
|
|
v[ 4] = ( v[ 4] >>> 24 ) | ( v[ 4] << 40 );
|
|
v[ 3] = v[ 3] + v[ 4] + m[4];
|
|
v[14] ^= v[ 3];
|
|
v[14] = ( v[14] >>> 16 ) | ( v[14] << 48 );
|
|
v[ 9] = v[ 9] + v[14];
|
|
v[ 4] ^= v[ 9];
|
|
v[ 4] = ( v[ 4] << 1 ) | ( v[ 4] >>> 63 );
|
|
}
|
|
private void round_3(final long[] v, final long[] m) {
|
|
v[ 0] = v[ 0] + v[ 4] + m[7];
|
|
v[12] ^= v[ 0];
|
|
v[12] = ( v[12] << 32 ) | ( v[12] >>> 32 );
|
|
v[ 8] = v[ 8] + v[12];
|
|
v[ 4] ^= v[ 8];
|
|
v[ 4] = ( v[ 4] >>> 24 ) | ( v[ 4] << 40 );
|
|
v[ 0] = v[ 0] + v[ 4] + m [9];
|
|
v[12] ^= v[ 0];
|
|
v[12] = ( v[12] >>> 16 ) | ( v[12] << 48 );
|
|
v[ 8] = v[ 8] + v[12];
|
|
v[ 4] ^= v[ 8];
|
|
v[ 4] = ( v[ 4] << 1 ) | ( v[ 4] >>> 63 );
|
|
|
|
v[ 1] = v[ 1] + v[ 5] + m[3];
|
|
v[13] ^= v[ 1];
|
|
v[13] = ( v[13] << 32 ) | ( v[13] >>> 32 );
|
|
v[ 9] = v[ 9] + v[13];
|
|
v[ 5] ^= v[ 9];
|
|
v[ 5] = ( v[ 5] >>> 24 ) | ( v[ 5] << 40 );
|
|
v[ 1] = v[ 1] + v[ 5] + m[1];
|
|
v[13] ^= v[ 1];
|
|
v[13] = ( v[13] >>> 16 ) | ( v[13] << 48 );
|
|
v[ 9] = v[ 9] + v[13];
|
|
v[ 5] ^= v[ 9];
|
|
v[ 5] = ( v[ 5] << 1 ) | ( v[ 5] >>> 63 );
|
|
|
|
v[ 2] = v[ 2] + v[ 6] + m[13];
|
|
v[14] ^= v[ 2];
|
|
v[14] = ( v[14] << 32 ) | ( v[14] >>> 32 );
|
|
v[10] = v[10] + v[14];
|
|
v[ 6] ^= v[10];
|
|
v[ 6] = ( v[ 6] >>> 24 ) | ( v[ 6] << 40 );
|
|
v[ 2] = v[ 2] + v[ 6] + m[12];
|
|
v[14] ^= v[ 2];
|
|
v[14] = ( v[14] >>> 16 ) | ( v[14] << 48 );
|
|
v[10] = v[10] + v[14];
|
|
v[ 6] ^= v[10];
|
|
v[ 6] = ( v[ 6] << 1 ) | ( v[ 6] >>> 63 );
|
|
|
|
v[ 3] = v[ 3] + v[ 7] + m[11];
|
|
v[15] ^= v[ 3];
|
|
v[15] = ( v[15] << 32 ) | ( v[15] >>> 32 );
|
|
v[11] = v[11] + v[15];
|
|
v[ 7] ^= v[11];
|
|
v[ 7] = ( v[ 7] >>> 24 ) | ( v[ 7] << 40 );
|
|
v[ 3] = v[ 3] + v[ 7] + m[14];
|
|
v[15] ^= v[ 3];
|
|
v[15] = ( v[15] >>> 16 ) | ( v[15] << 48 );
|
|
v[11] = v[11] + v[15];
|
|
v[ 7] ^= v[11];
|
|
v[ 7] = ( v[ 7] << 1 ) | ( v[ 7] >>> 63 );
|
|
|
|
v[ 0] = v[ 0] + v[ 5] + m[2];
|
|
v[15] ^= v[ 0];
|
|
v[15] = ( v[15] << 32 ) | ( v[15] >>> 32 );
|
|
v[10] = v[10] + v[15];
|
|
v[ 5] ^= v[10];
|
|
v[ 5] = ( v[ 5] >>> 24 ) | ( v[ 5] << 40 );
|
|
v[ 0] = v[ 0] + v[ 5] + m[6];
|
|
v[15] ^= v[ 0];
|
|
v[15] = ( v[15] >>> 16 ) | ( v[15] << 48 );
|
|
v[10] = v[10] + v[15];
|
|
v[ 5] ^= v[10];
|
|
v[ 5] = ( v[ 5] << 1 ) | ( v[ 5] >>> 63 );
|
|
|
|
v[ 1] = v[ 1] + v[ 6] + m[5];
|
|
v[12] ^= v[ 1];
|
|
v[12] = ( v[12] << 32 ) | ( v[12] >>> 32 );
|
|
v[11] = v[11] + v[12];
|
|
v[ 6] ^= v[11];
|
|
v[ 6] = ( v[ 6] >>> 24 ) | ( v[ 6] << 40 );
|
|
v[ 1] = v[ 1] + v[ 6] + + m[10];
|
|
v[12] ^= v[ 1];
|
|
v[12] = ( v[12] >>> 16 ) | ( v[12] << 48 );
|
|
v[11] = v[11] + v[12];
|
|
v[ 6] ^= v[11];
|
|
v[ 6] = ( v[ 6] << 1 ) | ( v[ 6] >>> 63 );
|
|
|
|
v[ 2] = v[ 2] + v[ 7] + m[4];
|
|
v[13] ^= v[ 2];
|
|
v[13] = ( v[13] << 32 ) | ( v[13] >>> 32 );
|
|
v[ 8] = v[ 8] + v[13];
|
|
v[ 7] ^= v[ 8];
|
|
v[ 7] = ( v[ 7] >>> 24 ) | ( v[ 7] << 40 );
|
|
v[ 2] = v[ 2] + v[ 7] + m[0];
|
|
v[13] ^= v[ 2];
|
|
v[13] = ( v[13] >>> 16 ) | ( v[13] << 48 );
|
|
v[ 8] = v[ 8] + v[13];
|
|
v[ 7] ^= v[ 8];
|
|
v[ 7] = ( v[ 7] << 1 ) | ( v[ 7] >>> 63 );
|
|
|
|
v[ 3] = v[ 3] + v[ 4] + m[15];
|
|
v[14] ^= v[ 3];
|
|
v[14] = ( v[14] << 32 ) | ( v[14] >>> 32 );
|
|
v[ 9] = v[ 9] + v[14];
|
|
v[ 4] ^= v[ 9];
|
|
v[ 4] = ( v[ 4] >>> 24 ) | ( v[ 4] << 40 );
|
|
v[ 3] = v[ 3] + v[ 4] + m[8];
|
|
v[14] ^= v[ 3];
|
|
v[14] = ( v[14] >>> 16 ) | ( v[14] << 48 );
|
|
v[ 9] = v[ 9] + v[14];
|
|
v[ 4] ^= v[ 9];
|
|
v[ 4] = ( v[ 4] << 1 ) | ( v[ 4] >>> 63 );
|
|
}
|
|
private void round_4(final long[] v, final long[] m) {
|
|
v[ 0] = v[ 0] + v[ 4] + m[9];
|
|
v[12] ^= v[ 0];
|
|
v[12] = ( v[12] << 32 ) | ( v[12] >>> 32 );
|
|
v[ 8] = v[ 8] + v[12];
|
|
v[ 4] ^= v[ 8];
|
|
v[ 4] = ( v[ 4] >>> 24 ) | ( v[ 4] << 40 );
|
|
v[ 0] = v[ 0] + v[ 4] + m [0];
|
|
v[12] ^= v[ 0];
|
|
v[12] = ( v[12] >>> 16 ) | ( v[12] << 48 );
|
|
v[ 8] = v[ 8] + v[12];
|
|
v[ 4] ^= v[ 8];
|
|
v[ 4] = ( v[ 4] << 1 ) | ( v[ 4] >>> 63 );
|
|
|
|
v[ 1] = v[ 1] + v[ 5] + m[5];
|
|
v[13] ^= v[ 1];
|
|
v[13] = ( v[13] << 32 ) | ( v[13] >>> 32 );
|
|
v[ 9] = v[ 9] + v[13];
|
|
v[ 5] ^= v[ 9];
|
|
v[ 5] = ( v[ 5] >>> 24 ) | ( v[ 5] << 40 );
|
|
v[ 1] = v[ 1] + v[ 5] + m[7];
|
|
v[13] ^= v[ 1];
|
|
v[13] = ( v[13] >>> 16 ) | ( v[13] << 48 );
|
|
v[ 9] = v[ 9] + v[13];
|
|
v[ 5] ^= v[ 9];
|
|
v[ 5] = ( v[ 5] << 1 ) | ( v[ 5] >>> 63 );
|
|
|
|
v[ 2] = v[ 2] + v[ 6] + m[2];
|
|
v[14] ^= v[ 2];
|
|
v[14] = ( v[14] << 32 ) | ( v[14] >>> 32 );
|
|
v[10] = v[10] + v[14];
|
|
v[ 6] ^= v[10];
|
|
v[ 6] = ( v[ 6] >>> 24 ) | ( v[ 6] << 40 );
|
|
v[ 2] = v[ 2] + v[ 6] + m[4];
|
|
v[14] ^= v[ 2];
|
|
v[14] = ( v[14] >>> 16 ) | ( v[14] << 48 );
|
|
v[10] = v[10] + v[14];
|
|
v[ 6] ^= v[10];
|
|
v[ 6] = ( v[ 6] << 1 ) | ( v[ 6] >>> 63 );
|
|
|
|
v[ 3] = v[ 3] + v[ 7] + m[10];
|
|
v[15] ^= v[ 3];
|
|
v[15] = ( v[15] << 32 ) | ( v[15] >>> 32 );
|
|
v[11] = v[11] + v[15];
|
|
v[ 7] ^= v[11];
|
|
v[ 7] = ( v[ 7] >>> 24 ) | ( v[ 7] << 40 );
|
|
v[ 3] = v[ 3] + v[ 7] + m[15];
|
|
v[15] ^= v[ 3];
|
|
v[15] = ( v[15] >>> 16 ) | ( v[15] << 48 );
|
|
v[11] = v[11] + v[15];
|
|
v[ 7] ^= v[11];
|
|
v[ 7] = ( v[ 7] << 1 ) | ( v[ 7] >>> 63 );
|
|
|
|
v[ 0] = v[ 0] + v[ 5] + m[14];
|
|
v[15] ^= v[ 0];
|
|
v[15] = ( v[15] << 32 ) | ( v[15] >>> 32 );
|
|
v[10] = v[10] + v[15];
|
|
v[ 5] ^= v[10];
|
|
v[ 5] = ( v[ 5] >>> 24 ) | ( v[ 5] << 40 );
|
|
v[ 0] = v[ 0] + v[ 5] + m[1];
|
|
v[15] ^= v[ 0];
|
|
v[15] = ( v[15] >>> 16 ) | ( v[15] << 48 );
|
|
v[10] = v[10] + v[15];
|
|
v[ 5] ^= v[10];
|
|
v[ 5] = ( v[ 5] << 1 ) | ( v[ 5] >>> 63 );
|
|
|
|
v[ 1] = v[ 1] + v[ 6] + m[11];
|
|
v[12] ^= v[ 1];
|
|
v[12] = ( v[12] << 32 ) | ( v[12] >>> 32 );
|
|
v[11] = v[11] + v[12];
|
|
v[ 6] ^= v[11];
|
|
v[ 6] = ( v[ 6] >>> 24 ) | ( v[ 6] << 40 );
|
|
v[ 1] = v[ 1] + v[ 6] + + m[12];
|
|
v[12] ^= v[ 1];
|
|
v[12] = ( v[12] >>> 16 ) | ( v[12] << 48 );
|
|
v[11] = v[11] + v[12];
|
|
v[ 6] ^= v[11];
|
|
v[ 6] = ( v[ 6] << 1 ) | ( v[ 6] >>> 63 );
|
|
|
|
v[ 2] = v[ 2] + v[ 7] + m[6];
|
|
v[13] ^= v[ 2];
|
|
v[13] = ( v[13] << 32 ) | ( v[13] >>> 32 );
|
|
v[ 8] = v[ 8] + v[13];
|
|
v[ 7] ^= v[ 8];
|
|
v[ 7] = ( v[ 7] >>> 24 ) | ( v[ 7] << 40 );
|
|
v[ 2] = v[ 2] + v[ 7] + m[8];
|
|
v[13] ^= v[ 2];
|
|
v[13] = ( v[13] >>> 16 ) | ( v[13] << 48 );
|
|
v[ 8] = v[ 8] + v[13];
|
|
v[ 7] ^= v[ 8];
|
|
v[ 7] = ( v[ 7] << 1 ) | ( v[ 7] >>> 63 );
|
|
|
|
v[ 3] = v[ 3] + v[ 4] + m[3];
|
|
v[14] ^= v[ 3];
|
|
v[14] = ( v[14] << 32 ) | ( v[14] >>> 32 );
|
|
v[ 9] = v[ 9] + v[14];
|
|
v[ 4] ^= v[ 9];
|
|
v[ 4] = ( v[ 4] >>> 24 ) | ( v[ 4] << 40 );
|
|
v[ 3] = v[ 3] + v[ 4] + m[13];
|
|
v[14] ^= v[ 3];
|
|
v[14] = ( v[14] >>> 16 ) | ( v[14] << 48 );
|
|
v[ 9] = v[ 9] + v[14];
|
|
v[ 4] ^= v[ 9];
|
|
v[ 4] = ( v[ 4] << 1 ) | ( v[ 4] >>> 63 );
|
|
}
|
|
private void round_5(final long[] v, final long[] m) {
|
|
v[ 0] = v[ 0] + v[ 4] + m[2];
|
|
v[12] ^= v[ 0];
|
|
v[12] = ( v[12] << 32 ) | ( v[12] >>> 32 );
|
|
v[ 8] = v[ 8] + v[12];
|
|
v[ 4] ^= v[ 8];
|
|
v[ 4] = ( v[ 4] >>> 24 ) | ( v[ 4] << 40 );
|
|
v[ 0] = v[ 0] + v[ 4] + m [12];
|
|
v[12] ^= v[ 0];
|
|
v[12] = ( v[12] >>> 16 ) | ( v[12] << 48 );
|
|
v[ 8] = v[ 8] + v[12];
|
|
v[ 4] ^= v[ 8];
|
|
v[ 4] = ( v[ 4] << 1 ) | ( v[ 4] >>> 63 );
|
|
|
|
v[ 1] = v[ 1] + v[ 5] + m[6];
|
|
v[13] ^= v[ 1];
|
|
v[13] = ( v[13] << 32 ) | ( v[13] >>> 32 );
|
|
v[ 9] = v[ 9] + v[13];
|
|
v[ 5] ^= v[ 9];
|
|
v[ 5] = ( v[ 5] >>> 24 ) | ( v[ 5] << 40 );
|
|
v[ 1] = v[ 1] + v[ 5] + m[10];
|
|
v[13] ^= v[ 1];
|
|
v[13] = ( v[13] >>> 16 ) | ( v[13] << 48 );
|
|
v[ 9] = v[ 9] + v[13];
|
|
v[ 5] ^= v[ 9];
|
|
v[ 5] = ( v[ 5] << 1 ) | ( v[ 5] >>> 63 );
|
|
|
|
v[ 2] = v[ 2] + v[ 6] + m[0];
|
|
v[14] ^= v[ 2];
|
|
v[14] = ( v[14] << 32 ) | ( v[14] >>> 32 );
|
|
v[10] = v[10] + v[14];
|
|
v[ 6] ^= v[10];
|
|
v[ 6] = ( v[ 6] >>> 24 ) | ( v[ 6] << 40 );
|
|
v[ 2] = v[ 2] + v[ 6] + m[11];
|
|
v[14] ^= v[ 2];
|
|
v[14] = ( v[14] >>> 16 ) | ( v[14] << 48 );
|
|
v[10] = v[10] + v[14];
|
|
v[ 6] ^= v[10];
|
|
v[ 6] = ( v[ 6] << 1 ) | ( v[ 6] >>> 63 );
|
|
|
|
v[ 3] = v[ 3] + v[ 7] + m[8];
|
|
v[15] ^= v[ 3];
|
|
v[15] = ( v[15] << 32 ) | ( v[15] >>> 32 );
|
|
v[11] = v[11] + v[15];
|
|
v[ 7] ^= v[11];
|
|
v[ 7] = ( v[ 7] >>> 24 ) | ( v[ 7] << 40 );
|
|
v[ 3] = v[ 3] + v[ 7] + m[3];
|
|
v[15] ^= v[ 3];
|
|
v[15] = ( v[15] >>> 16 ) | ( v[15] << 48 );
|
|
v[11] = v[11] + v[15];
|
|
v[ 7] ^= v[11];
|
|
v[ 7] = ( v[ 7] << 1 ) | ( v[ 7] >>> 63 );
|
|
|
|
v[ 0] = v[ 0] + v[ 5] + m[4];
|
|
v[15] ^= v[ 0];
|
|
v[15] = ( v[15] << 32 ) | ( v[15] >>> 32 );
|
|
v[10] = v[10] + v[15];
|
|
v[ 5] ^= v[10];
|
|
v[ 5] = ( v[ 5] >>> 24 ) | ( v[ 5] << 40 );
|
|
v[ 0] = v[ 0] + v[ 5] + m[13];
|
|
v[15] ^= v[ 0];
|
|
v[15] = ( v[15] >>> 16 ) | ( v[15] << 48 );
|
|
v[10] = v[10] + v[15];
|
|
v[ 5] ^= v[10];
|
|
v[ 5] = ( v[ 5] << 1 ) | ( v[ 5] >>> 63 );
|
|
|
|
v[ 1] = v[ 1] + v[ 6] + m[7];
|
|
v[12] ^= v[ 1];
|
|
v[12] = ( v[12] << 32 ) | ( v[12] >>> 32 );
|
|
v[11] = v[11] + v[12];
|
|
v[ 6] ^= v[11];
|
|
v[ 6] = ( v[ 6] >>> 24 ) | ( v[ 6] << 40 );
|
|
v[ 1] = v[ 1] + v[ 6] + + m[5];
|
|
v[12] ^= v[ 1];
|
|
v[12] = ( v[12] >>> 16 ) | ( v[12] << 48 );
|
|
v[11] = v[11] + v[12];
|
|
v[ 6] ^= v[11];
|
|
v[ 6] = ( v[ 6] << 1 ) | ( v[ 6] >>> 63 );
|
|
|
|
v[ 2] = v[ 2] + v[ 7] + m[15];
|
|
v[13] ^= v[ 2];
|
|
v[13] = ( v[13] << 32 ) | ( v[13] >>> 32 );
|
|
v[ 8] = v[ 8] + v[13];
|
|
v[ 7] ^= v[ 8];
|
|
v[ 7] = ( v[ 7] >>> 24 ) | ( v[ 7] << 40 );
|
|
v[ 2] = v[ 2] + v[ 7] + m[14];
|
|
v[13] ^= v[ 2];
|
|
v[13] = ( v[13] >>> 16 ) | ( v[13] << 48 );
|
|
v[ 8] = v[ 8] + v[13];
|
|
v[ 7] ^= v[ 8];
|
|
v[ 7] = ( v[ 7] << 1 ) | ( v[ 7] >>> 63 );
|
|
|
|
v[ 3] = v[ 3] + v[ 4] + m[1];
|
|
v[14] ^= v[ 3];
|
|
v[14] = ( v[14] << 32 ) | ( v[14] >>> 32 );
|
|
v[ 9] = v[ 9] + v[14];
|
|
v[ 4] ^= v[ 9];
|
|
v[ 4] = ( v[ 4] >>> 24 ) | ( v[ 4] << 40 );
|
|
v[ 3] = v[ 3] + v[ 4] + m[9];
|
|
v[14] ^= v[ 3];
|
|
v[14] = ( v[14] >>> 16 ) | ( v[14] << 48 );
|
|
v[ 9] = v[ 9] + v[14];
|
|
v[ 4] ^= v[ 9];
|
|
v[ 4] = ( v[ 4] << 1 ) | ( v[ 4] >>> 63 );
|
|
}
|
|
private void round_6(final long[] v, final long[] m) {
|
|
v[ 0] = v[ 0] + v[ 4] + m[12];
|
|
v[12] ^= v[ 0];
|
|
v[12] = ( v[12] << 32 ) | ( v[12] >>> 32 );
|
|
v[ 8] = v[ 8] + v[12];
|
|
v[ 4] ^= v[ 8];
|
|
v[ 4] = ( v[ 4] >>> 24 ) | ( v[ 4] << 40 );
|
|
v[ 0] = v[ 0] + v[ 4] + m [5];
|
|
v[12] ^= v[ 0];
|
|
v[12] = ( v[12] >>> 16 ) | ( v[12] << 48 );
|
|
v[ 8] = v[ 8] + v[12];
|
|
v[ 4] ^= v[ 8];
|
|
v[ 4] = ( v[ 4] << 1 ) | ( v[ 4] >>> 63 );
|
|
|
|
v[ 1] = v[ 1] + v[ 5] + m[1];
|
|
v[13] ^= v[ 1];
|
|
v[13] = ( v[13] << 32 ) | ( v[13] >>> 32 );
|
|
v[ 9] = v[ 9] + v[13];
|
|
v[ 5] ^= v[ 9];
|
|
v[ 5] = ( v[ 5] >>> 24 ) | ( v[ 5] << 40 );
|
|
v[ 1] = v[ 1] + v[ 5] + m[15];
|
|
v[13] ^= v[ 1];
|
|
v[13] = ( v[13] >>> 16 ) | ( v[13] << 48 );
|
|
v[ 9] = v[ 9] + v[13];
|
|
v[ 5] ^= v[ 9];
|
|
v[ 5] = ( v[ 5] << 1 ) | ( v[ 5] >>> 63 );
|
|
|
|
v[ 2] = v[ 2] + v[ 6] + m[14];
|
|
v[14] ^= v[ 2];
|
|
v[14] = ( v[14] << 32 ) | ( v[14] >>> 32 );
|
|
v[10] = v[10] + v[14];
|
|
v[ 6] ^= v[10];
|
|
v[ 6] = ( v[ 6] >>> 24 ) | ( v[ 6] << 40 );
|
|
v[ 2] = v[ 2] + v[ 6] + m[13];
|
|
v[14] ^= v[ 2];
|
|
v[14] = ( v[14] >>> 16 ) | ( v[14] << 48 );
|
|
v[10] = v[10] + v[14];
|
|
v[ 6] ^= v[10];
|
|
v[ 6] = ( v[ 6] << 1 ) | ( v[ 6] >>> 63 );
|
|
|
|
v[ 3] = v[ 3] + v[ 7] + m[4];
|
|
v[15] ^= v[ 3];
|
|
v[15] = ( v[15] << 32 ) | ( v[15] >>> 32 );
|
|
v[11] = v[11] + v[15];
|
|
v[ 7] ^= v[11];
|
|
v[ 7] = ( v[ 7] >>> 24 ) | ( v[ 7] << 40 );
|
|
v[ 3] = v[ 3] + v[ 7] + m[10];
|
|
v[15] ^= v[ 3];
|
|
v[15] = ( v[15] >>> 16 ) | ( v[15] << 48 );
|
|
v[11] = v[11] + v[15];
|
|
v[ 7] ^= v[11];
|
|
v[ 7] = ( v[ 7] << 1 ) | ( v[ 7] >>> 63 );
|
|
|
|
v[ 0] = v[ 0] + v[ 5] + m[0];
|
|
v[15] ^= v[ 0];
|
|
v[15] = ( v[15] << 32 ) | ( v[15] >>> 32 );
|
|
v[10] = v[10] + v[15];
|
|
v[ 5] ^= v[10];
|
|
v[ 5] = ( v[ 5] >>> 24 ) | ( v[ 5] << 40 );
|
|
v[ 0] = v[ 0] + v[ 5] + m[7];
|
|
v[15] ^= v[ 0];
|
|
v[15] = ( v[15] >>> 16 ) | ( v[15] << 48 );
|
|
v[10] = v[10] + v[15];
|
|
v[ 5] ^= v[10];
|
|
v[ 5] = ( v[ 5] << 1 ) | ( v[ 5] >>> 63 );
|
|
|
|
v[ 1] = v[ 1] + v[ 6] + m[6];
|
|
v[12] ^= v[ 1];
|
|
v[12] = ( v[12] << 32 ) | ( v[12] >>> 32 );
|
|
v[11] = v[11] + v[12];
|
|
v[ 6] ^= v[11];
|
|
v[ 6] = ( v[ 6] >>> 24 ) | ( v[ 6] << 40 );
|
|
v[ 1] = v[ 1] + v[ 6] + + m[3];
|
|
v[12] ^= v[ 1];
|
|
v[12] = ( v[12] >>> 16 ) | ( v[12] << 48 );
|
|
v[11] = v[11] + v[12];
|
|
v[ 6] ^= v[11];
|
|
v[ 6] = ( v[ 6] << 1 ) | ( v[ 6] >>> 63 );
|
|
|
|
v[ 2] = v[ 2] + v[ 7] + m[9];
|
|
v[13] ^= v[ 2];
|
|
v[13] = ( v[13] << 32 ) | ( v[13] >>> 32 );
|
|
v[ 8] = v[ 8] + v[13];
|
|
v[ 7] ^= v[ 8];
|
|
v[ 7] = ( v[ 7] >>> 24 ) | ( v[ 7] << 40 );
|
|
v[ 2] = v[ 2] + v[ 7] + m[2];
|
|
v[13] ^= v[ 2];
|
|
v[13] = ( v[13] >>> 16 ) | ( v[13] << 48 );
|
|
v[ 8] = v[ 8] + v[13];
|
|
v[ 7] ^= v[ 8];
|
|
v[ 7] = ( v[ 7] << 1 ) | ( v[ 7] >>> 63 );
|
|
|
|
v[ 3] = v[ 3] + v[ 4] + m[8];
|
|
v[14] ^= v[ 3];
|
|
v[14] = ( v[14] << 32 ) | ( v[14] >>> 32 );
|
|
v[ 9] = v[ 9] + v[14];
|
|
v[ 4] ^= v[ 9];
|
|
v[ 4] = ( v[ 4] >>> 24 ) | ( v[ 4] << 40 );
|
|
v[ 3] = v[ 3] + v[ 4] + m[11];
|
|
v[14] ^= v[ 3];
|
|
v[14] = ( v[14] >>> 16 ) | ( v[14] << 48 );
|
|
v[ 9] = v[ 9] + v[14];
|
|
v[ 4] ^= v[ 9];
|
|
v[ 4] = ( v[ 4] << 1 ) | ( v[ 4] >>> 63 );
|
|
}
|
|
private void round_7(final long[] v, final long[] m) {
|
|
v[ 0] = v[ 0] + v[ 4] + m[13];
|
|
v[12] ^= v[ 0];
|
|
v[12] = ( v[12] << 32 ) | ( v[12] >>> 32 );
|
|
v[ 8] = v[ 8] + v[12];
|
|
v[ 4] ^= v[ 8];
|
|
v[ 4] = ( v[ 4] >>> 24 ) | ( v[ 4] << 40 );
|
|
v[ 0] = v[ 0] + v[ 4] + m [11];
|
|
v[12] ^= v[ 0];
|
|
v[12] = ( v[12] >>> 16 ) | ( v[12] << 48 );
|
|
v[ 8] = v[ 8] + v[12];
|
|
v[ 4] ^= v[ 8];
|
|
v[ 4] = ( v[ 4] << 1 ) | ( v[ 4] >>> 63 );
|
|
|
|
v[ 1] = v[ 1] + v[ 5] + m[7];
|
|
v[13] ^= v[ 1];
|
|
v[13] = ( v[13] << 32 ) | ( v[13] >>> 32 );
|
|
v[ 9] = v[ 9] + v[13];
|
|
v[ 5] ^= v[ 9];
|
|
v[ 5] = ( v[ 5] >>> 24 ) | ( v[ 5] << 40 );
|
|
v[ 1] = v[ 1] + v[ 5] + m[14];
|
|
v[13] ^= v[ 1];
|
|
v[13] = ( v[13] >>> 16 ) | ( v[13] << 48 );
|
|
v[ 9] = v[ 9] + v[13];
|
|
v[ 5] ^= v[ 9];
|
|
v[ 5] = ( v[ 5] << 1 ) | ( v[ 5] >>> 63 );
|
|
|
|
v[ 2] = v[ 2] + v[ 6] + m[12];
|
|
v[14] ^= v[ 2];
|
|
v[14] = ( v[14] << 32 ) | ( v[14] >>> 32 );
|
|
v[10] = v[10] + v[14];
|
|
v[ 6] ^= v[10];
|
|
v[ 6] = ( v[ 6] >>> 24 ) | ( v[ 6] << 40 );
|
|
v[ 2] = v[ 2] + v[ 6] + m[1];
|
|
v[14] ^= v[ 2];
|
|
v[14] = ( v[14] >>> 16 ) | ( v[14] << 48 );
|
|
v[10] = v[10] + v[14];
|
|
v[ 6] ^= v[10];
|
|
v[ 6] = ( v[ 6] << 1 ) | ( v[ 6] >>> 63 );
|
|
|
|
v[ 3] = v[ 3] + v[ 7] + m[3];
|
|
v[15] ^= v[ 3];
|
|
v[15] = ( v[15] << 32 ) | ( v[15] >>> 32 );
|
|
v[11] = v[11] + v[15];
|
|
v[ 7] ^= v[11];
|
|
v[ 7] = ( v[ 7] >>> 24 ) | ( v[ 7] << 40 );
|
|
v[ 3] = v[ 3] + v[ 7] + m[9];
|
|
v[15] ^= v[ 3];
|
|
v[15] = ( v[15] >>> 16 ) | ( v[15] << 48 );
|
|
v[11] = v[11] + v[15];
|
|
v[ 7] ^= v[11];
|
|
v[ 7] = ( v[ 7] << 1 ) | ( v[ 7] >>> 63 );
|
|
|
|
v[ 0] = v[ 0] + v[ 5] + m[5];
|
|
v[15] ^= v[ 0];
|
|
v[15] = ( v[15] << 32 ) | ( v[15] >>> 32 );
|
|
v[10] = v[10] + v[15];
|
|
v[ 5] ^= v[10];
|
|
v[ 5] = ( v[ 5] >>> 24 ) | ( v[ 5] << 40 );
|
|
v[ 0] = v[ 0] + v[ 5] + m[0];
|
|
v[15] ^= v[ 0];
|
|
v[15] = ( v[15] >>> 16 ) | ( v[15] << 48 );
|
|
v[10] = v[10] + v[15];
|
|
v[ 5] ^= v[10];
|
|
v[ 5] = ( v[ 5] << 1 ) | ( v[ 5] >>> 63 );
|
|
|
|
v[ 1] = v[ 1] + v[ 6] + m[15];
|
|
v[12] ^= v[ 1];
|
|
v[12] = ( v[12] << 32 ) | ( v[12] >>> 32 );
|
|
v[11] = v[11] + v[12];
|
|
v[ 6] ^= v[11];
|
|
v[ 6] = ( v[ 6] >>> 24 ) | ( v[ 6] << 40 );
|
|
v[ 1] = v[ 1] + v[ 6] + + m[4];
|
|
v[12] ^= v[ 1];
|
|
v[12] = ( v[12] >>> 16 ) | ( v[12] << 48 );
|
|
v[11] = v[11] + v[12];
|
|
v[ 6] ^= v[11];
|
|
v[ 6] = ( v[ 6] << 1 ) | ( v[ 6] >>> 63 );
|
|
|
|
v[ 2] = v[ 2] + v[ 7] + m[8];
|
|
v[13] ^= v[ 2];
|
|
v[13] = ( v[13] << 32 ) | ( v[13] >>> 32 );
|
|
v[ 8] = v[ 8] + v[13];
|
|
v[ 7] ^= v[ 8];
|
|
v[ 7] = ( v[ 7] >>> 24 ) | ( v[ 7] << 40 );
|
|
v[ 2] = v[ 2] + v[ 7] + m[6];
|
|
v[13] ^= v[ 2];
|
|
v[13] = ( v[13] >>> 16 ) | ( v[13] << 48 );
|
|
v[ 8] = v[ 8] + v[13];
|
|
v[ 7] ^= v[ 8];
|
|
v[ 7] = ( v[ 7] << 1 ) | ( v[ 7] >>> 63 );
|
|
|
|
v[ 3] = v[ 3] + v[ 4] + m[2];
|
|
v[14] ^= v[ 3];
|
|
v[14] = ( v[14] << 32 ) | ( v[14] >>> 32 );
|
|
v[ 9] = v[ 9] + v[14];
|
|
v[ 4] ^= v[ 9];
|
|
v[ 4] = ( v[ 4] >>> 24 ) | ( v[ 4] << 40 );
|
|
v[ 3] = v[ 3] + v[ 4] + m[10];
|
|
v[14] ^= v[ 3];
|
|
v[14] = ( v[14] >>> 16 ) | ( v[14] << 48 );
|
|
v[ 9] = v[ 9] + v[14];
|
|
v[ 4] ^= v[ 9];
|
|
v[ 4] = ( v[ 4] << 1 ) | ( v[ 4] >>> 63 );
|
|
}
|
|
private void round_8(final long[] v, final long[] m) {
|
|
v[ 0] = v[ 0] + v[ 4] + m[6];
|
|
v[12] ^= v[ 0];
|
|
v[12] = ( v[12] << 32 ) | ( v[12] >>> 32 );
|
|
v[ 8] = v[ 8] + v[12];
|
|
v[ 4] ^= v[ 8];
|
|
v[ 4] = ( v[ 4] >>> 24 ) | ( v[ 4] << 40 );
|
|
v[ 0] = v[ 0] + v[ 4] + m [15];
|
|
v[12] ^= v[ 0];
|
|
v[12] = ( v[12] >>> 16 ) | ( v[12] << 48 );
|
|
v[ 8] = v[ 8] + v[12];
|
|
v[ 4] ^= v[ 8];
|
|
v[ 4] = ( v[ 4] << 1 ) | ( v[ 4] >>> 63 );
|
|
|
|
v[ 1] = v[ 1] + v[ 5] + m[14];
|
|
v[13] ^= v[ 1];
|
|
v[13] = ( v[13] << 32 ) | ( v[13] >>> 32 );
|
|
v[ 9] = v[ 9] + v[13];
|
|
v[ 5] ^= v[ 9];
|
|
v[ 5] = ( v[ 5] >>> 24 ) | ( v[ 5] << 40 );
|
|
v[ 1] = v[ 1] + v[ 5] + m[9];
|
|
v[13] ^= v[ 1];
|
|
v[13] = ( v[13] >>> 16 ) | ( v[13] << 48 );
|
|
v[ 9] = v[ 9] + v[13];
|
|
v[ 5] ^= v[ 9];
|
|
v[ 5] = ( v[ 5] << 1 ) | ( v[ 5] >>> 63 );
|
|
|
|
v[ 2] = v[ 2] + v[ 6] + m[11];
|
|
v[14] ^= v[ 2];
|
|
v[14] = ( v[14] << 32 ) | ( v[14] >>> 32 );
|
|
v[10] = v[10] + v[14];
|
|
v[ 6] ^= v[10];
|
|
v[ 6] = ( v[ 6] >>> 24 ) | ( v[ 6] << 40 );
|
|
v[ 2] = v[ 2] + v[ 6] + m[3];
|
|
v[14] ^= v[ 2];
|
|
v[14] = ( v[14] >>> 16 ) | ( v[14] << 48 );
|
|
v[10] = v[10] + v[14];
|
|
v[ 6] ^= v[10];
|
|
v[ 6] = ( v[ 6] << 1 ) | ( v[ 6] >>> 63 );
|
|
|
|
v[ 3] = v[ 3] + v[ 7] + m[0];
|
|
v[15] ^= v[ 3];
|
|
v[15] = ( v[15] << 32 ) | ( v[15] >>> 32 );
|
|
v[11] = v[11] + v[15];
|
|
v[ 7] ^= v[11];
|
|
v[ 7] = ( v[ 7] >>> 24 ) | ( v[ 7] << 40 );
|
|
v[ 3] = v[ 3] + v[ 7] + m[8];
|
|
v[15] ^= v[ 3];
|
|
v[15] = ( v[15] >>> 16 ) | ( v[15] << 48 );
|
|
v[11] = v[11] + v[15];
|
|
v[ 7] ^= v[11];
|
|
v[ 7] = ( v[ 7] << 1 ) | ( v[ 7] >>> 63 );
|
|
|
|
v[ 0] = v[ 0] + v[ 5] + m[12];
|
|
v[15] ^= v[ 0];
|
|
v[15] = ( v[15] << 32 ) | ( v[15] >>> 32 );
|
|
v[10] = v[10] + v[15];
|
|
v[ 5] ^= v[10];
|
|
v[ 5] = ( v[ 5] >>> 24 ) | ( v[ 5] << 40 );
|
|
v[ 0] = v[ 0] + v[ 5] + m[2];
|
|
v[15] ^= v[ 0];
|
|
v[15] = ( v[15] >>> 16 ) | ( v[15] << 48 );
|
|
v[10] = v[10] + v[15];
|
|
v[ 5] ^= v[10];
|
|
v[ 5] = ( v[ 5] << 1 ) | ( v[ 5] >>> 63 );
|
|
|
|
v[ 1] = v[ 1] + v[ 6] + m[13];
|
|
v[12] ^= v[ 1];
|
|
v[12] = ( v[12] << 32 ) | ( v[12] >>> 32 );
|
|
v[11] = v[11] + v[12];
|
|
v[ 6] ^= v[11];
|
|
v[ 6] = ( v[ 6] >>> 24 ) | ( v[ 6] << 40 );
|
|
v[ 1] = v[ 1] + v[ 6] + + m[7];
|
|
v[12] ^= v[ 1];
|
|
v[12] = ( v[12] >>> 16 ) | ( v[12] << 48 );
|
|
v[11] = v[11] + v[12];
|
|
v[ 6] ^= v[11];
|
|
v[ 6] = ( v[ 6] << 1 ) | ( v[ 6] >>> 63 );
|
|
|
|
v[ 2] = v[ 2] + v[ 7] + m[1];
|
|
v[13] ^= v[ 2];
|
|
v[13] = ( v[13] << 32 ) | ( v[13] >>> 32 );
|
|
v[ 8] = v[ 8] + v[13];
|
|
v[ 7] ^= v[ 8];
|
|
v[ 7] = ( v[ 7] >>> 24 ) | ( v[ 7] << 40 );
|
|
v[ 2] = v[ 2] + v[ 7] + m[4];
|
|
v[13] ^= v[ 2];
|
|
v[13] = ( v[13] >>> 16 ) | ( v[13] << 48 );
|
|
v[ 8] = v[ 8] + v[13];
|
|
v[ 7] ^= v[ 8];
|
|
v[ 7] = ( v[ 7] << 1 ) | ( v[ 7] >>> 63 );
|
|
|
|
v[ 3] = v[ 3] + v[ 4] + m[10];
|
|
v[14] ^= v[ 3];
|
|
v[14] = ( v[14] << 32 ) | ( v[14] >>> 32 );
|
|
v[ 9] = v[ 9] + v[14];
|
|
v[ 4] ^= v[ 9];
|
|
v[ 4] = ( v[ 4] >>> 24 ) | ( v[ 4] << 40 );
|
|
v[ 3] = v[ 3] + v[ 4] + m[5];
|
|
v[14] ^= v[ 3];
|
|
v[14] = ( v[14] >>> 16 ) | ( v[14] << 48 );
|
|
v[ 9] = v[ 9] + v[14];
|
|
v[ 4] ^= v[ 9];
|
|
v[ 4] = ( v[ 4] << 1 ) | ( v[ 4] >>> 63 );
|
|
}
|
|
private void round_9(final long[] v, final long[] m) {
|
|
v[ 0] = v[ 0] + v[ 4] + m[10];
|
|
v[12] ^= v[ 0];
|
|
v[12] = ( v[12] << 32 ) | ( v[12] >>> 32 );
|
|
v[ 8] = v[ 8] + v[12];
|
|
v[ 4] ^= v[ 8];
|
|
v[ 4] = ( v[ 4] >>> 24 ) | ( v[ 4] << 40 );
|
|
v[ 0] = v[ 0] + v[ 4] + m [2];
|
|
v[12] ^= v[ 0];
|
|
v[12] = ( v[12] >>> 16 ) | ( v[12] << 48 );
|
|
v[ 8] = v[ 8] + v[12];
|
|
v[ 4] ^= v[ 8];
|
|
v[ 4] = ( v[ 4] << 1 ) | ( v[ 4] >>> 63 );
|
|
|
|
v[ 1] = v[ 1] + v[ 5] + m[8];
|
|
v[13] ^= v[ 1];
|
|
v[13] = ( v[13] << 32 ) | ( v[13] >>> 32 );
|
|
v[ 9] = v[ 9] + v[13];
|
|
v[ 5] ^= v[ 9];
|
|
v[ 5] = ( v[ 5] >>> 24 ) | ( v[ 5] << 40 );
|
|
v[ 1] = v[ 1] + v[ 5] + m[4];
|
|
v[13] ^= v[ 1];
|
|
v[13] = ( v[13] >>> 16 ) | ( v[13] << 48 );
|
|
v[ 9] = v[ 9] + v[13];
|
|
v[ 5] ^= v[ 9];
|
|
v[ 5] = ( v[ 5] << 1 ) | ( v[ 5] >>> 63 );
|
|
|
|
v[ 2] = v[ 2] + v[ 6] + m[7];
|
|
v[14] ^= v[ 2];
|
|
v[14] = ( v[14] << 32 ) | ( v[14] >>> 32 );
|
|
v[10] = v[10] + v[14];
|
|
v[ 6] ^= v[10];
|
|
v[ 6] = ( v[ 6] >>> 24 ) | ( v[ 6] << 40 );
|
|
v[ 2] = v[ 2] + v[ 6] + m[6];
|
|
v[14] ^= v[ 2];
|
|
v[14] = ( v[14] >>> 16 ) | ( v[14] << 48 );
|
|
v[10] = v[10] + v[14];
|
|
v[ 6] ^= v[10];
|
|
v[ 6] = ( v[ 6] << 1 ) | ( v[ 6] >>> 63 );
|
|
|
|
v[ 3] = v[ 3] + v[ 7] + m[1];
|
|
v[15] ^= v[ 3];
|
|
v[15] = ( v[15] << 32 ) | ( v[15] >>> 32 );
|
|
v[11] = v[11] + v[15];
|
|
v[ 7] ^= v[11];
|
|
v[ 7] = ( v[ 7] >>> 24 ) | ( v[ 7] << 40 );
|
|
v[ 3] = v[ 3] + v[ 7] + m[5];
|
|
v[15] ^= v[ 3];
|
|
v[15] = ( v[15] >>> 16 ) | ( v[15] << 48 );
|
|
v[11] = v[11] + v[15];
|
|
v[ 7] ^= v[11];
|
|
v[ 7] = ( v[ 7] << 1 ) | ( v[ 7] >>> 63 );
|
|
|
|
v[ 0] = v[ 0] + v[ 5] + m[15];
|
|
v[15] ^= v[ 0];
|
|
v[15] = ( v[15] << 32 ) | ( v[15] >>> 32 );
|
|
v[10] = v[10] + v[15];
|
|
v[ 5] ^= v[10];
|
|
v[ 5] = ( v[ 5] >>> 24 ) | ( v[ 5] << 40 );
|
|
v[ 0] = v[ 0] + v[ 5] + m[11];
|
|
v[15] ^= v[ 0];
|
|
v[15] = ( v[15] >>> 16 ) | ( v[15] << 48 );
|
|
v[10] = v[10] + v[15];
|
|
v[ 5] ^= v[10];
|
|
v[ 5] = ( v[ 5] << 1 ) | ( v[ 5] >>> 63 );
|
|
|
|
v[ 1] = v[ 1] + v[ 6] + m[9];
|
|
v[12] ^= v[ 1];
|
|
v[12] = ( v[12] << 32 ) | ( v[12] >>> 32 );
|
|
v[11] = v[11] + v[12];
|
|
v[ 6] ^= v[11];
|
|
v[ 6] = ( v[ 6] >>> 24 ) | ( v[ 6] << 40 );
|
|
v[ 1] = v[ 1] + v[ 6] + + m[14];
|
|
v[12] ^= v[ 1];
|
|
v[12] = ( v[12] >>> 16 ) | ( v[12] << 48 );
|
|
v[11] = v[11] + v[12];
|
|
v[ 6] ^= v[11];
|
|
v[ 6] = ( v[ 6] << 1 ) | ( v[ 6] >>> 63 );
|
|
|
|
v[ 2] = v[ 2] + v[ 7] + m[3];
|
|
v[13] ^= v[ 2];
|
|
v[13] = ( v[13] << 32 ) | ( v[13] >>> 32 );
|
|
v[ 8] = v[ 8] + v[13];
|
|
v[ 7] ^= v[ 8];
|
|
v[ 7] = ( v[ 7] >>> 24 ) | ( v[ 7] << 40 );
|
|
v[ 2] = v[ 2] + v[ 7] + m[12];
|
|
v[13] ^= v[ 2];
|
|
v[13] = ( v[13] >>> 16 ) | ( v[13] << 48 );
|
|
v[ 8] = v[ 8] + v[13];
|
|
v[ 7] ^= v[ 8];
|
|
v[ 7] = ( v[ 7] << 1 ) | ( v[ 7] >>> 63 );
|
|
|
|
v[ 3] = v[ 3] + v[ 4] + m[13];
|
|
v[14] ^= v[ 3];
|
|
v[14] = ( v[14] << 32 ) | ( v[14] >>> 32 );
|
|
v[ 9] = v[ 9] + v[14];
|
|
v[ 4] ^= v[ 9];
|
|
v[ 4] = ( v[ 4] >>> 24 ) | ( v[ 4] << 40 );
|
|
v[ 3] = v[ 3] + v[ 4] + m[0];
|
|
v[14] ^= v[ 3];
|
|
v[14] = ( v[14] >>> 16 ) | ( v[14] << 48 );
|
|
v[ 9] = v[ 9] + v[14];
|
|
v[ 4] ^= v[ 9];
|
|
v[ 4] = ( v[ 4] << 1 ) | ( v[ 4] >>> 63 );
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// Compression Kernel //////////////////////////////////////////// FINI
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
/* TEMP - remove at will */
|
|
public static class Debug {
|
|
public static void dumpState (Engine e, final String mark) {
|
|
System.out.format("-- MARK == @ %s @ ===========\n", mark);
|
|
dumpArray("register t", e.state.t);
|
|
dumpArray("register h", e.state.h);
|
|
dumpArray("register f", e.state.f);
|
|
dumpArray("register offset", new long[]{e.state.buflen});
|
|
System.out.format("-- END MARK =================\n");
|
|
}
|
|
public static void dumpArray (final String label, final long[] b) {
|
|
System.out.format ( "-- %s -- :\n{\n", label );
|
|
for( int j = 0; j < b.length ; ++j ) {
|
|
System.out.format ( " [%2d] : %016X\n", j, b[j]);
|
|
}
|
|
System.out.format ( "}\n" );
|
|
}
|
|
public static void dumpBuffer (final PrintStream out, final String label, final byte[] b) {
|
|
dumpBuffer(out, label, b, 0, b.length);
|
|
}
|
|
public static void dumpBuffer (final PrintStream out, final byte[] b) {
|
|
dumpBuffer(out, null, b, 0, b.length);
|
|
}
|
|
public static void dumpBuffer (final PrintStream out, final byte[] b, final int offset, final int len) {
|
|
dumpBuffer(out, null, b, offset, len);
|
|
}
|
|
public static void dumpBuffer (final PrintStream out, final String label, final byte[] b, final int offset, final int len) {
|
|
if(label != null)
|
|
out.format ( "-- %s -- :\n", label );
|
|
out.format("{\n ", label);
|
|
for( int j = 0; j < len ; ++j ) {
|
|
out.format ("%02X", b[j + offset]);
|
|
if(j+1 < len) {
|
|
if ((j+1)%8==0) out.print("\n ");
|
|
else out.print(' ');
|
|
}
|
|
}
|
|
out.format("\n}\n");
|
|
}
|
|
}
|
|
/* TEMP - remove at will */
|
|
|
|
// ---------------------------------------------------------------------
|
|
// Helper for assert error messages
|
|
// ---------------------------------------------------------------------
|
|
public static final class Assert {
|
|
public final static String exclusiveUpperBound = "'%s' %d is >= %d";
|
|
public final static String inclusiveUpperBound = "'%s' %d is > %d";
|
|
public final static String exclusiveLowerBound = "'%s' %d is <= %d";
|
|
public final static String inclusiveLowerBound = "'%s' %d is < %d";
|
|
static <T extends Number> String assertFail(final String name, final T v, final String err, final T spec) {
|
|
new Exception().printStackTrace();
|
|
return String.format(err, name, v, spec);
|
|
}
|
|
}
|
|
// ---------------------------------------------------------------------
|
|
// Little Endian Codecs (inlined in the compressor)
|
|
/*
|
|
* impl note: these are not library funcs and used in hot loops, so no
|
|
* null or bounds checks are performed. For our purposes, this is OK.
|
|
*/
|
|
// ---------------------------------------------------------------------
|
|
|
|
public static class LittleEndian {
|
|
private static final byte[] hex_digits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
|
|
private static final byte[] HEX_digits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
|
|
/** @return hex rep of byte (lower case). */
|
|
static public String toHexStr (final byte[] b) {
|
|
return toHexStr (b, false); // because String class is slower.
|
|
}
|
|
static public String toHexStr (final byte[] b, boolean upperCase) {
|
|
final int len = b.length;
|
|
final byte[] digits = new byte[ len * 2 ];
|
|
final byte[] hex_rep = upperCase ? HEX_digits : hex_digits ;
|
|
for (int i = 0; i < len; i++) {
|
|
digits [ i*2 ] = hex_rep [ (byte) (b[i] >> 4 & 0x0F) ];
|
|
digits [ i*2+1 ] = hex_rep [ (byte) (b[i] & 0x0F) ];
|
|
}
|
|
return new String(digits);
|
|
}
|
|
public static int readInt (final byte[] b, final int off) {
|
|
int v0 = ((int)b [ off ] & 0xFF );
|
|
v0 |= ((int)b [ off + 1 ] & 0xFF ) << 8;
|
|
v0 |= ((int)b [ off + 2 ] & 0xFF ) << 16;
|
|
return v0 | ((int)b [ off + 3 ] ) << 24;
|
|
}
|
|
/** Little endian - byte[] to long */
|
|
public static long readLong (final byte[] b, final int off) {
|
|
long v0 = ((long)b [ off ] & 0xFF );
|
|
v0 |= ((long)b [ off + 1 ] & 0xFF ) << 8;
|
|
v0 |= ((long)b [ off + 2 ] & 0xFF ) << 16;
|
|
v0 |= ((long)b [ off + 3 ] & 0xFF ) << 24;
|
|
v0 |= ((long)b [ off + 4 ] & 0xFF ) << 32;
|
|
v0 |= ((long)b [ off + 5 ] & 0xFF ) << 40;
|
|
v0 |= ((long)b [ off + 6 ] & 0xFF ) << 48;
|
|
return v0 | ((long)b [ off + 7 ] ) << 56;
|
|
}
|
|
/** Little endian - long to byte[] */
|
|
public static void writeLong (long v, final byte[] b, final int off) {
|
|
b [ off ] = (byte) v; v >>>= 8;
|
|
b [ off + 1 ] = (byte) v; v >>>= 8;
|
|
b [ off + 2 ] = (byte) v; v >>>= 8;
|
|
b [ off + 3 ] = (byte) v; v >>>= 8;
|
|
b [ off + 4 ] = (byte) v; v >>>= 8;
|
|
b [ off + 5 ] = (byte) v; v >>>= 8;
|
|
b [ off + 6 ] = (byte) v; v >>>= 8;
|
|
b [ off + 7 ] = (byte) v;
|
|
}
|
|
/** Little endian - int to byte[] */
|
|
public static void writeInt (int v, final byte[] b, final int off) {
|
|
b [ off ] = (byte) v; v >>>= 8;
|
|
b [ off + 1 ] = (byte) v; v >>>= 8;
|
|
b [ off + 2 ] = (byte) v; v >>>= 8;
|
|
b [ off + 3 ] = (byte) v;
|
|
}
|
|
}
|
|
}
|
|
// ---------------------------------------------------------------------
|
|
// digest parameter (block)
|
|
// ---------------------------------------------------------------------
|
|
/** Blake2b configuration parameters block per spec */
|
|
// REVU: need to review a revert back to non-lazy impl TODO: do & bench
|
|
public static class Param implements AlgorithmParameterSpec {
|
|
interface Xoff {
|
|
int digest_length = 0;
|
|
int key_length = 1;
|
|
int fanout = 2;
|
|
int depth = 3;
|
|
int leaf_length = 4;
|
|
int node_offset = 8;
|
|
int node_depth = 16;
|
|
int inner_length = 17;
|
|
int reserved = 18;
|
|
int salt = 32;
|
|
int personal = 48;
|
|
}
|
|
public interface Default {
|
|
byte digest_length = Spec.max_digest_bytes;
|
|
byte key_length = 0;
|
|
byte fanout = 1;
|
|
byte depth = 1;
|
|
int leaf_length = 0;
|
|
long node_offset = 0;
|
|
byte node_depth = 0;
|
|
byte inner_length = 0;
|
|
}
|
|
/** default bytes of Blake2b parameter block */
|
|
final static byte[] default_bytes = new byte[ Spec.param_bytes ];
|
|
/** initialize default_bytes */
|
|
static {
|
|
default_bytes [ Xoff.digest_length ] = Default.digest_length;
|
|
default_bytes [ Xoff.key_length ] = Default.key_length;
|
|
default_bytes [ Xoff.fanout ] = Default.fanout;
|
|
default_bytes [ Xoff.depth ] = Default.depth;
|
|
/* def. leaf_length is 0 fill and already set by new byte[] */
|
|
/* def. node_offset is 0 fill and already set by new byte[] */
|
|
default_bytes [ Xoff.node_depth ] = Default.node_depth;
|
|
default_bytes [ Xoff.inner_length] = Default.inner_length;
|
|
/* def. salt is 0 fill and already set by new byte[] */
|
|
/* def. personal is 0 fill and already set by new byte[] */
|
|
}
|
|
/** default Blake2b h vector */
|
|
final static long[] default_h = new long [ Spec.state_space_len ];
|
|
static {
|
|
default_h [0] = readLong( default_bytes, 0 );
|
|
default_h [1] = readLong( default_bytes, 8 );
|
|
default_h [2] = readLong( default_bytes, 16 );
|
|
default_h [3] = readLong( default_bytes, 24 );
|
|
default_h [4] = readLong( default_bytes, 32 );
|
|
default_h [5] = readLong( default_bytes, 40 );
|
|
default_h [6] = readLong( default_bytes, 48 );
|
|
default_h [7] = readLong( default_bytes, 56 );
|
|
|
|
default_h [0] ^= Spec.IV [0];
|
|
default_h [1] ^= Spec.IV [1];
|
|
default_h [2] ^= Spec.IV [2];
|
|
default_h [3] ^= Spec.IV [3];
|
|
default_h [4] ^= Spec.IV [4];
|
|
default_h [5] ^= Spec.IV [5];
|
|
default_h [6] ^= Spec.IV [6];
|
|
default_h [7] ^= Spec.IV [7];
|
|
}
|
|
|
|
/** */
|
|
private boolean hasKey = false;
|
|
/** not sure how to make this secure - TODO */
|
|
private byte[] key_bytes = null;
|
|
/** */
|
|
private byte[] bytes = null;
|
|
/** */
|
|
private final long[] h = new long [ Spec.state_space_len ];
|
|
|
|
/** */
|
|
public Param() {
|
|
System.arraycopy( default_h, 0, h, 0, Spec.state_space_len );
|
|
}
|
|
/** */
|
|
public long[] initialized_H () {
|
|
return h;
|
|
}
|
|
/** package only - copy returned - do not use in functional loops */
|
|
public byte[] getBytes() {
|
|
lazyInitBytes();
|
|
byte[] copy = new byte[ bytes.length ];
|
|
System.arraycopy( bytes, 0, copy, 0, bytes.length );
|
|
return copy;
|
|
}
|
|
|
|
final byte getByteParam (final int xoffset) {
|
|
byte[] _bytes = bytes;
|
|
if(_bytes == null) _bytes = Param.default_bytes;
|
|
return _bytes[ xoffset];
|
|
}
|
|
final int getIntParam (final int xoffset) {
|
|
byte[] _bytes = bytes;
|
|
if(_bytes == null) _bytes = Param.default_bytes;
|
|
return readInt ( _bytes, xoffset);
|
|
}
|
|
final long getLongParam (final int xoffset) {
|
|
byte[] _bytes = bytes;
|
|
if(_bytes == null) _bytes = Param.default_bytes;
|
|
return readLong ( _bytes, xoffset);
|
|
}
|
|
// TODO same for tree params depth, fanout, inner, node-depth, node-offset
|
|
public final int getDigestLength() {
|
|
return (int) getByteParam ( Xoff.digest_length );
|
|
}
|
|
public final int getKeyLength() {
|
|
return (int) getByteParam ( Xoff.key_length );
|
|
}
|
|
public final int getFanout() {
|
|
return (int) getByteParam ( Xoff.fanout );
|
|
}
|
|
public final int getDepth() {
|
|
return (int) getByteParam ( Xoff.depth );
|
|
}
|
|
public final int getLeafLength() {
|
|
return getIntParam ( Xoff.leaf_length );
|
|
}
|
|
public final long getNodeOffset() {
|
|
return getLongParam ( Xoff.node_offset );
|
|
}
|
|
public final int getNodeDepth() {
|
|
return (int) getByteParam ( Xoff.node_depth );
|
|
}
|
|
public final int getInnerLength() {
|
|
return (int) getByteParam ( Xoff.inner_length );
|
|
}
|
|
|
|
public final boolean hasKey() { return this.hasKey; }
|
|
|
|
@Override public Param clone() {
|
|
final Param clone = new Param();
|
|
System.arraycopy(this.h, 0, clone.h, 0, h.length);
|
|
clone.lazyInitBytes();
|
|
System.arraycopy(this.bytes, 0, clone.bytes, 0, this.bytes.length);
|
|
|
|
if(this.hasKey){
|
|
clone.hasKey = this.hasKey;
|
|
clone.key_bytes = new byte [Spec.max_key_bytes * 2];
|
|
System.arraycopy(this.key_bytes, 0, clone.key_bytes, 0, this.key_bytes.length);
|
|
}
|
|
return clone;
|
|
}
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// lazy setters - write directly to the bytes image of param block ////
|
|
////////////////////////////////////////////////////////////////////////
|
|
final void lazyInitBytes () {
|
|
if( bytes == null ) {
|
|
bytes = new byte [ Spec.param_bytes ];
|
|
System.arraycopy(Param.default_bytes, 0, bytes, 0, Spec.param_bytes);
|
|
}
|
|
}
|
|
/* 0-7 inclusive */
|
|
public final Param setDigestLength(int len) {
|
|
assert len > 0 : assertFail("len", len, exclusiveLowerBound, 0);
|
|
assert len <= Spec.max_digest_bytes : assertFail("len", len, inclusiveUpperBound, Spec.max_digest_bytes);
|
|
|
|
lazyInitBytes();
|
|
bytes[ Xoff.digest_length ] = (byte) len;
|
|
h[ 0 ] = readLong( bytes, 0 );
|
|
h[ 0 ] ^= Spec.IV [ 0 ];
|
|
return this;
|
|
}
|
|
public final Param setKey (final Key key) {
|
|
assert key != null : "key is null";
|
|
final byte[] keybytes = key.getEncoded();
|
|
assert keybytes != null : "key.encoded() is null";
|
|
|
|
return this.setKey(keybytes);
|
|
}
|
|
public final Param setKey (final byte[] key) {
|
|
assert key != null : "key is null";
|
|
assert key.length >= 0 : assertFail("key.length", key.length, inclusiveUpperBound, 0);
|
|
assert key.length <= Spec.max_key_bytes : assertFail("key.length", key.length, inclusiveUpperBound, Spec.max_key_bytes);
|
|
|
|
// zeropad keybytes
|
|
this.key_bytes = new byte [Spec.max_key_bytes * 2];
|
|
System.arraycopy ( key, 0, this.key_bytes, 0, key.length );
|
|
lazyInitBytes();
|
|
bytes[ Xoff.key_length ] = (byte) key.length; // checked c ref; this is correct
|
|
h[ 0 ] = readLong( bytes, 0 );
|
|
h[ 0 ] ^= Spec.IV [ 0 ];
|
|
this.hasKey = true;
|
|
return this;
|
|
}
|
|
public final Param setFanout(int fanout) {
|
|
assert fanout > 0 : assertFail("fanout", fanout, exclusiveLowerBound, 0);
|
|
|
|
lazyInitBytes();
|
|
bytes[ Xoff.fanout ] = (byte) fanout;
|
|
h[ 0 ] = readLong( bytes, 0 );
|
|
h[ 0 ] ^= Spec.IV [ 0 ];
|
|
return this;
|
|
}
|
|
public final Param setDepth(int depth) {
|
|
assert depth > 0 : assertFail("depth", depth, exclusiveLowerBound, 0);
|
|
|
|
lazyInitBytes();
|
|
bytes[ Xoff.depth ] = (byte) depth;
|
|
h[ 0 ] = readLong( bytes, 0 );
|
|
h[ 0 ] ^= Spec.IV [ 0 ];
|
|
return this;
|
|
}
|
|
public final Param setLeafLength(int leaf_length) {
|
|
assert leaf_length >= 0 : assertFail("leaf_length", leaf_length, inclusiveLowerBound, 0);
|
|
|
|
lazyInitBytes();
|
|
writeInt (leaf_length, bytes, Xoff.leaf_length);
|
|
h[ 0 ] = readLong( bytes, 0 );
|
|
h[ 0 ] ^= Spec.IV [ 0 ];
|
|
return this;
|
|
}
|
|
|
|
/* 8-15 inclusive */
|
|
public final Param setNodeOffset(long node_offset) {
|
|
assert node_offset >= 0 : assertFail("node_offset", node_offset, inclusiveLowerBound, 0);
|
|
|
|
lazyInitBytes();
|
|
writeLong(node_offset, bytes, Xoff.node_offset);
|
|
h[ 1 ] = readLong( bytes, Xoff.node_offset );
|
|
h[ 1 ] ^= Spec.IV [ 1 ];
|
|
return this;
|
|
}
|
|
|
|
/* 16-23 inclusive */
|
|
public final Param setNodeDepth(int node_depth) {
|
|
assert node_depth >= 0 : assertFail("node_depth", node_depth, inclusiveLowerBound, 0);
|
|
|
|
lazyInitBytes();
|
|
bytes[ Xoff.node_depth ] = (byte) node_depth;
|
|
h[ 2 ] = readLong( bytes, Xoff.node_depth );
|
|
h[ 2 ] ^= Spec.IV [ 2 ];
|
|
h[ 3 ] = readLong( bytes, Xoff.node_depth + 8);
|
|
h[ 3 ] ^= Spec.IV [ 3 ];
|
|
return this;
|
|
}
|
|
public final Param setInnerLength(int inner_length) {
|
|
assert inner_length >= 0 : assertFail("inner_length", inner_length, inclusiveLowerBound, 0);
|
|
|
|
lazyInitBytes();
|
|
bytes[ Xoff.inner_length] = (byte) inner_length;
|
|
h[ 2 ] = readLong( bytes, Xoff.node_depth );
|
|
h[ 2 ] ^= Spec.IV [ 2 ];
|
|
h[ 3 ] = readLong( bytes, Xoff.node_depth + 8);
|
|
h[ 3 ] ^= Spec.IV [ 3 ];
|
|
return this;
|
|
}
|
|
|
|
/* 24-31 masked by reserved and remain unchanged */
|
|
|
|
/* 32-47 inclusive */
|
|
public final Param setSalt(final byte[] salt) {
|
|
assert salt != null : "salt is null";
|
|
assert salt.length <= Spec.max_salt_bytes : assertFail("salt.length", salt.length, inclusiveUpperBound, Spec.max_salt_bytes);
|
|
|
|
lazyInitBytes();
|
|
Arrays.fill ( bytes, Xoff.salt, Xoff.salt + Spec.max_salt_bytes, (byte)0);
|
|
System.arraycopy( salt, 0, bytes, Xoff.salt, salt.length );
|
|
h[ 4 ] = readLong( bytes, Xoff.salt );
|
|
h[ 4 ] ^= Spec.IV [ 4 ];
|
|
h[ 5 ] = readLong( bytes, Xoff.salt + 8 );
|
|
h[ 5 ] ^= Spec.IV [ 5 ];
|
|
return this;
|
|
}
|
|
|
|
/* 48-63 inclusive */
|
|
public final Param setPersonal(byte[] personal) {
|
|
assert personal != null : "personal is null";
|
|
assert personal.length <= Spec.max_personalization_bytes : assertFail("personal.length", personal.length, inclusiveUpperBound, Spec.max_personalization_bytes);
|
|
|
|
lazyInitBytes();
|
|
Arrays.fill ( bytes, Xoff.personal, Xoff.personal + Spec.max_personalization_bytes, (byte)0);
|
|
System.arraycopy( personal, 0, bytes, Xoff.personal, personal.length );
|
|
h[ 6 ] = readLong( bytes, Xoff.personal );
|
|
h[ 6 ] ^= Spec.IV [ 6 ];
|
|
h[ 7 ] = readLong( bytes, Xoff.personal + 8 );
|
|
h[ 7 ] ^= Spec.IV [ 7 ];
|
|
return this;
|
|
}
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// lazy setters /////////////////////////////////////////////////// END
|
|
////////////////////////////////////////////////////////////////////////
|
|
}
|
|
}
|