/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
*/

/*
 * Implementation of the Secure Hashing Algorithm (SHA-512)
 *
 * Generates a 512 bit message digest. It should be impossible to come
 * come up with two messages that hash to the same value ("collision free").
 *
 * For use with byte-oriented messages only. 
 */


package org.apache.milagro.amcl;

public class HASH512 {

	private long[] length=new long[2];
	private long[] h=new long[8];
	private long[] w=new long[80];

	public static final long H0=0x6a09e667f3bcc908L;
	public static final long H1=0xbb67ae8584caa73bL;
	public static final long H2=0x3c6ef372fe94f82bL;
	public static final long H3=0xa54ff53a5f1d36f1L;
	public static final long H4=0x510e527fade682d1L;
	public static final long H5=0x9b05688c2b3e6c1fL;
	public static final long H6=0x1f83d9abfb41bd6bL;
	public static final long H7=0x5be0cd19137e2179L;

	public static final int len=64;

	public static final long[] K=
	{0x428a2f98d728ae22L,0x7137449123ef65cdL,0xb5c0fbcfec4d3b2fL,0xe9b5dba58189dbbcL,
	0x3956c25bf348b538L,0x59f111f1b605d019L,0x923f82a4af194f9bL,0xab1c5ed5da6d8118L,
	0xd807aa98a3030242L,0x12835b0145706fbeL,0x243185be4ee4b28cL,0x550c7dc3d5ffb4e2L,
	0x72be5d74f27b896fL,0x80deb1fe3b1696b1L,0x9bdc06a725c71235L,0xc19bf174cf692694L,
	0xe49b69c19ef14ad2L,0xefbe4786384f25e3L,0x0fc19dc68b8cd5b5L,0x240ca1cc77ac9c65L,
	0x2de92c6f592b0275L,0x4a7484aa6ea6e483L,0x5cb0a9dcbd41fbd4L,0x76f988da831153b5L,
	0x983e5152ee66dfabL,0xa831c66d2db43210L,0xb00327c898fb213fL,0xbf597fc7beef0ee4L,
	0xc6e00bf33da88fc2L,0xd5a79147930aa725L,0x06ca6351e003826fL,0x142929670a0e6e70L,
	0x27b70a8546d22ffcL,0x2e1b21385c26c926L,0x4d2c6dfc5ac42aedL,0x53380d139d95b3dfL,
	0x650a73548baf63deL,0x766a0abb3c77b2a8L,0x81c2c92e47edaee6L,0x92722c851482353bL,
	0xa2bfe8a14cf10364L,0xa81a664bbc423001L,0xc24b8b70d0f89791L,0xc76c51a30654be30L,
	0xd192e819d6ef5218L,0xd69906245565a910L,0xf40e35855771202aL,0x106aa07032bbd1b8L,
	0x19a4c116b8d2d0c8L,0x1e376c085141ab53L,0x2748774cdf8eeb99L,0x34b0bcb5e19b48a8L,
	0x391c0cb3c5c95a63L,0x4ed8aa4ae3418acbL,0x5b9cca4f7763e373L,0x682e6ff3d6b2b8a3L,
	0x748f82ee5defb2fcL,0x78a5636f43172f60L,0x84c87814a1f0ab72L,0x8cc702081a6439ecL,
	0x90befffa23631e28L,0xa4506cebde82bde9L,0xbef9a3f7b2c67915L,0xc67178f2e372532bL,
	0xca273eceea26619cL,0xd186b8c721c0c207L,0xeada7dd6cde0eb1eL,0xf57d4f7fee6ed178L,
	0x06f067aa72176fbaL,0x0a637dc5a2c898a6L,0x113f9804bef90daeL,0x1b710b35131c471bL,
	0x28db77f523047d84L,0x32caab7b40c72493L,0x3c9ebe0a15c9bebcL,0x431d67c49c100d4cL,
	0x4cc5d4becb3e42b6L,0x597f299cfc657e2aL,0x5fcb6fab3ad6faecL,0x6c44198c4a475817L};

/* functions */
	private static long S(int n,long x)
	{
		return (((x)>>>n) | ((x)<<(64-n)));
	}

	private static long R(int n,long x)
	{
		return ((x)>>>n);
	}

	private static long Ch(long x,long y,long z)
	{
		return ((x&y)^(~(x)&z));
	}

	private static long Maj(long x,long y,long z)
	{
		return ((x&y)^(x&z)^(y&z));
	}

	private static long Sig0(long x)
	{
		return (S(28,x)^S(34,x)^S(39,x));
	}

	private static long Sig1(long x)
	{
		return (S(14,x)^S(18,x)^S(41,x));
	}

	private static long theta0(long x)
	{
		return (S(1,x)^S(8,x)^R(7,x));
	}

	private static long theta1(long x)
	{
		return (S(19,x)^S(61,x)^R(6,x));
	}


	private void transform()
	{ /* basic transformation step */
		long a,b,c,d,e,f,g,hh,t1,t2;
		int j;
		for (j=16;j<80;j++) 
			w[j]=theta1(w[j-2])+w[j-7]+theta0(w[j-15])+w[j-16];
		a=h[0]; b=h[1]; c=h[2]; d=h[3]; 
		e=h[4]; f=h[5]; g=h[6]; hh=h[7];

		for (j=0;j<80;j++)
		{ /* 80 times - mush it up */
			t1=hh+Sig1(e)+Ch(e,f,g)+K[j]+w[j];
			t2=Sig0(a)+Maj(a,b,c);
			hh=g; g=f; f=e;
			e=d+t1;
			d=c;
			c=b;
			b=a;
			a=t1+t2;   
		
		}
		h[0]+=a; h[1]+=b; h[2]+=c; h[3]+=d; 
		h[4]+=e; h[5]+=f; h[6]+=g; h[7]+=hh; 
	} 

/* Initialise Hash function */
	public void init()
	{ /* initialise */
		int i;
		for (i=0;i<80;i++) w[i]=0L;
		length[0]=length[1]=0L;
		h[0]=H0;
		h[1]=H1;
		h[2]=H2;
		h[3]=H3;
		h[4]=H4;
		h[5]=H5;
		h[6]=H6;
		h[7]=H7;
	}

/* Constructor */
	public HASH512()
	{
		init();
	}

/* process a single byte */
	public void process(int byt)
	{ /* process the next message byte */
		int cnt;
		cnt=(int)(length[0]/64)%16;
    
		w[cnt]<<=8;
		w[cnt]|=(byt&0xFF);
		length[0]+=8;
		if (length[0]==0L) { length[1]++; length[0]=0L; }
		if ((length[0]%1024)==0) transform();
	}

/* process an array of bytes */	
	public void process_array(byte[] b)
	{
		for (int i=0;i<b.length;i++) process((int)b[i]);
	}

/* process a 32-bit integer */
	public void process_num(int n)
	{
		process((n>>24)&0xff);
		process((n>>16)&0xff);
		process((n>>8)&0xff);
		process(n&0xff);
	}

/* Generate 64-byte Hash */
	public byte[] hash()
	{ /* pad message and finish - supply digest */
		int i;
		byte[] digest=new byte[64];
		long len0,len1;
		len0=length[0];
		len1=length[1];
		process(0x80);
		while ((length[0]%1024)!=896) process(0);
		w[14]=len1;
		w[15]=len0;    
		transform();
		for (i=0;i<len;i++)
		{ /* convert to bytes */
			digest[i]=(byte)((h[i/8]>>(8*(7-i%8))) & 0xffL);
		}
		init();
		return digest;
	}

/* test program: should produce digest */

//8e959b75dae313da 8cf4f72814fc143f 8f7779c6eb9f7fa1 7299aeadb6889018 501d289e4900f7e4 331b99dec4b5433a c7d329eeb6dd2654 5e96e55b874be909

	public static void main(String[] args) {

		byte[] test="abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu".getBytes();
		byte[] digest;
		int i;
		HASH512 sh=new HASH512();
  
		for (i=0;i<test.length;i++)
			sh.process(test[i]);
		
		digest=sh.hash();    
		for (i=0;i<64;i++) System.out.format("%02x",digest[i]);

	//	for (i=0;i<32;i++) System.out.format("%d ",digest[i]);

		System.out.println("");

	} 
}

