/*
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-384)
 *
 * Generates a 384 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 main

package amcl

//import "fmt"

const SHA3_HASH224 int=28
const SHA3_HASH256 int=32
const SHA3_HASH384 int=48
const SHA3_HASH512 int=64
const SHA3_SHAKE128 int=16
const SHA3_SHAKE256 int=32


const sha3_ROUNDS int=24

var sha3_RC = [24]uint64 {
		0x0000000000000001,0x0000000000008082,0x800000000000808A,0x8000000080008000,
		0x000000000000808B,0x0000000080000001,0x8000000080008081,0x8000000000008009,
		0x000000000000008A,0x0000000000000088,0x0000000080008009,0x000000008000000A,
		0x000000008000808B,0x800000000000008B,0x8000000000008089,0x8000000000008003,
		0x8000000000008002,0x8000000000000080,0x000000000000800A,0x800000008000000A,
		0x8000000080008081,0x8000000000008080,0x0000000080000001,0x8000000080008008}


type SHA3 struct {
	length uint64
	rate int
	len int
	s [5][5] uint64
}

/* functions */

func sha3_ROTL(x uint64,n uint64) uint64 {
	return (((x)<<n) | ((x)>>(64-n)))
}

func (H *SHA3) transform() { /* basic transformation step */

	var c [5]uint64
	var d [5]uint64
	var b [5][5]uint64

	for k:=0;k<sha3_ROUNDS;k++ {
		c[0]=H.s[0][0]^H.s[0][1]^H.s[0][2]^H.s[0][3]^H.s[0][4];
		c[1]=H.s[1][0]^H.s[1][1]^H.s[1][2]^H.s[1][3]^H.s[1][4];
		c[2]=H.s[2][0]^H.s[2][1]^H.s[2][2]^H.s[2][3]^H.s[2][4];
		c[3]=H.s[3][0]^H.s[3][1]^H.s[3][2]^H.s[3][3]^H.s[3][4];
		c[4]=H.s[4][0]^H.s[4][1]^H.s[4][2]^H.s[4][3]^H.s[4][4];

		d[0]=c[4]^sha3_ROTL(c[1],1);
		d[1]=c[0]^sha3_ROTL(c[2],1);
		d[2]=c[1]^sha3_ROTL(c[3],1);
		d[3]=c[2]^sha3_ROTL(c[4],1);
		d[4]=c[3]^sha3_ROTL(c[0],1);

		for i:=0;i<5;i++ {
			for j:=0;j<5;j++ {
					H.s[i][j]^=d[i];
			}
		}

		b[0][0]=H.s[0][0];
		b[1][3]=sha3_ROTL(H.s[0][1],36);
		b[2][1]=sha3_ROTL(H.s[0][2],3);
		b[3][4]=sha3_ROTL(H.s[0][3],41);
		b[4][2]=sha3_ROTL(H.s[0][4],18);

		b[0][2]=sha3_ROTL(H.s[1][0],1);
		b[1][0]=sha3_ROTL(H.s[1][1],44);
		b[2][3]=sha3_ROTL(H.s[1][2],10);
		b[3][1]=sha3_ROTL(H.s[1][3],45);
		b[4][4]=sha3_ROTL(H.s[1][4],2);

		b[0][4]=sha3_ROTL(H.s[2][0],62);
		b[1][2]=sha3_ROTL(H.s[2][1],6);
		b[2][0]=sha3_ROTL(H.s[2][2],43);
		b[3][3]=sha3_ROTL(H.s[2][3],15);
		b[4][1]=sha3_ROTL(H.s[2][4],61);

		b[0][1]=sha3_ROTL(H.s[3][0],28);
		b[1][4]=sha3_ROTL(H.s[3][1],55);
		b[2][2]=sha3_ROTL(H.s[3][2],25);
		b[3][0]=sha3_ROTL(H.s[3][3],21);
		b[4][3]=sha3_ROTL(H.s[3][4],56);

		b[0][3]=sha3_ROTL(H.s[4][0],27);
		b[1][1]=sha3_ROTL(H.s[4][1],20);
		b[2][4]=sha3_ROTL(H.s[4][2],39);
		b[3][2]=sha3_ROTL(H.s[4][3],8);
		b[4][0]=sha3_ROTL(H.s[4][4],14);

		for i:=0;i<5;i++ {
			for j:=0;j<5;j++ {
				H.s[i][j]=b[i][j]^(^b[(i+1)%5][j]&b[(i+2)%5][j]);
			}
		}

		H.s[0][0]^=sha3_RC[k];
	}
} 

/* Initialise Hash function */
func (H *SHA3) Init(olen int) { 
	for i:=0;i<5;i++ {
		for j:=0;j<5;j++ {
			H.s[i][j]=0;
		}
	}
	H.length=0
	H.len=olen
	H.rate=200-2*olen
}


func NewSHA3(olen int) *SHA3 {
	H:= new(SHA3)
	H.Init(olen)
	return H
}

/* process a single byte */
func (H *SHA3) Process(byt byte) { /* process the next message byte */
	cnt:=int(H.length%uint64(H.rate))
	b:=cnt%8
	cnt/=8
	i:=cnt%5
	j:=cnt/5
	H.s[i][j]^=uint64(byt&0xff)<<uint(8*b);
	H.length++;
	if int(H.length%uint64(H.rate))==0 {
		H.transform()
	}
}

/* squeeze the sponge */
func (H *SHA3) Squeeze(buff []byte,olen int) {
//	olen:=len(buff)
	done:=false
	m:=0
/* extract by columns */
	for {
		for j:=0;j<5;j++ {
			for i:=0;i<5;i++ {
				el:=H.s[i][j]
				for k:=0;k<8;k++ {
					buff[m]=byte(el&0xff)
					m++
					if m>=olen || (m%H.rate)==0 {
						done=true
						break
					}
					el>>=8;
				}
				if done {break}
			}
			if done {break}
		}
		if m>=olen {break}
		done=false
		H.transform()

	}
}

/* Generate Hash */
func (H *SHA3) Hash(hash []byte) { /* generate a SHA3 hash of appropriate size */
	q:=H.rate-int(H.length%uint64(H.rate))
	if q==1 {
		H.Process(0x86)
	} else {
		H.Process(0x06)
		for int(H.length%uint64(H.rate)) != (H.rate-1) {H.Process(0x00)}
		H.Process(0x80)
	}
	H.Squeeze(hash,H.len);
}

func (H *SHA3) Shake(hash []byte,olen int) { /* generate a SHA3 hash of appropriate size */
	q:=H.rate-int(H.length%uint64(H.rate))
	if q==1 {
		H.Process(0x9f)
	} else {
		H.Process(0x1f)
		for int(H.length%uint64(H.rate))!=H.rate-1 {H.Process(0x00)}
		H.Process(0x80)
	}
	H.Squeeze(hash,olen);
}



/* test program: should produce digest */
//916f6061fe879741ca6469b43971dfdb28b1a32dc36cb3254e812be27aad1d18
//afebb2ef542e6579c50cad06d2e578f9f8dd6881d7dc824d26360feebf18a4fa73e3261122948efcfd492e74e82e2189ed0fb440d187f382270cb455f21dd185
//98be04516c04cc73593fef3ed0352ea9f6443942d6950e29a372a681c3deaf4535423709b02843948684e029010badcc0acd8303fc85fdad3eabf4f78cae165635f57afd28810fc2

/*
func main() {

	test := []byte("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu")
	var digest [172]byte

	sh:=NewSHA3(SHA3_HASH256)
	for i:=0;i<len(test);i++ {
		sh.Process(test[i])
	}	
	sh.Hash(digest[:])    
	for i:=0;i<32;i++ {fmt.Printf("%02x",digest[i])}
	fmt.Printf("\n");

	sh=NewSHA3(SHA3_HASH512)
	for i:=0;i<len(test);i++ {
		sh.Process(test[i])
	}	
	sh.Hash(digest[:])    
	for i:=0;i<64;i++ {fmt.Printf("%02x",digest[i])}
	fmt.Printf("\n");

	sh=NewSHA3(SHA3_SHAKE256)
	for i:=0;i<len(test);i++ {
		sh.Process(test[i])
	}	
	sh.Shake(digest[:],72)    
	for i:=0;i<72;i++ {fmt.Printf("%02x",digest[i])}
	fmt.Printf("\n");

} */

