@@ -4,68 +4,60 @@ import com.infendro.bytes.ByteOrder.LITTLE_ENDIAN
import com.infendro.bytes.bytearray.copyInto
import com.infendro.bytes.long.copyInto
import com.infendro.hash.HashFunction
import com.infendro.hash.util.align
open class Keccak (
override val bytes: Int ,
bytes: Int ,
private val rate : Int ,
private val domain : Byte ,
) : HashFunction {
) : HashFunction ( bytes , rate ) {
init {
require ( bytes > 0 )
require ( rate in 8. . 192 step 8 )
}
overrid e val block : Int
get ( ) = rate
privat e var state = LongArray ( 25 )
private val rc = l ongArrayOf (
+ 0x0000000000000001 , + 0x0000000000008082 , - 0x7fffffffffff7f76 , - 0x7fffffff7fff8000 ,
+ 0x000000000000808b , + 0x0000000080000001 , - 0x7fffffff7fff7f7f , - 0x7fffffffffff7ff7 ,
+ 0x000000000000008a , + 0x0000000000000088 , + 0x0000000080008009 , + 0x000000008000000a ,
+ 0x000000008000808b , - 0x7fffffffffffff75 , - 0x7fffffffffff7f77 , - 0x7fffffffffff7ffd ,
- 0x7fffffffffff7ffe , - 0x7fffffffffffff80 , + 0x000000000000800a , - 0x7fffffff7ffffff6 ,
- 0x7fffffff7fff7f7f , - 0x7fffffffffff7f80 , + 0x0000000080000001 , - 0x7fffffff7fff7ff8 ,
)
private val w = L ongArray( block / 8 )
private val b = LongArray ( 25 )
private val c = LongArray ( 5 )
private val d = LongArray ( 5 )
private val rotation = arrayOf (
intArrayOf ( 0 , 36 , 3 , 41 , 18 ) ,
intArrayOf ( 1 , 44 , 10 , 45 , 2 ) ,
intArrayOf ( 62 , 6 , 43 , 15 , 61 ) ,
intArrayOf ( 28 , 55 , 25 , 21 , 56 ) ,
intArrayOf ( 27 , 20 , 39 , 8 , 14 ) ,
)
override fun hashInto ( value : ByteArray , destination : ByteArray , destinationOffset : Int ) {
val input = pad ( value )
val state = LongArray ( 25 )
for ( i in input . indices step block ) {
val block = input . sliceArray ( i .. < ( i + block ) )
absorb ( state , block )
permute ( state )
}
squeeze ( state , destination , destinationOffset )
override fun reset ( ) {
super . reset ( )
state . fill ( 0L )
}
privat e fun pad ( value : ByteArray ) : ByteArray {
val size = ( value . size + 2 ) . align ( block )
return ByteArray ( size ) . also {
value . copyInto ( it )
it [ value . size ] = domain
it [ size - 1 ] = - 0x80
}
overrid e fun process ( ) {
absorb ( buffer . value )
permute ( )
}
private fun absorb ( state : LongArray , block : ByteArray ) {
val w = LongArray ( this . block / 8 )
private fun finalize ( ) {
buffer . append ( domain )
if ( buffer . free < 1 ) {
process ( )
buffer . reset ( )
}
buffer . jumpTo ( block - 1 )
buffer . append ( 0x80 . toByte ( ) )
process ( )
}
override fun digestInto ( destination : ByteArray , destinationOffset : Int ) {
finalize ( )
squeeze ( destination , destinationOffset )
reset ( )
}
private fun absorb ( block : ByteArray ) {
block . copyInto ( w , order = LITTLE _ENDIAN )
for ( i in w . indices ) {
state [ i ] = state [ i ] xor w [ i ]
}
}
private fun squeeze ( state : LongArray , destination: ByteArray , destinationOffset : Int ) {
private fun squeeze ( destination : ByteArray , destinationOffset : Int ) {
val buffer = ByteArray ( 8 )
val threshold = rate / 8
@@ -73,7 +65,7 @@ open class Keccak(
var i = 0
while ( consumed < bytes ) {
if ( i == threshold ) {
permute ( state )
permute ( )
i = 0
}
@@ -86,10 +78,8 @@ open class Keccak(
}
}
private fun permute ( a : LongArray ) = repeat ( 24 ) { round ->
val b = LongArray ( 25 )
val c = LongArray ( 5 )
val d = LongArray ( 5 )
private fun permute ( ) = repeat ( 24 ) { round ->
val a = state
// θ
for ( x in 0. . 4 ) {
@@ -115,4 +105,23 @@ open class Keccak(
// ι
a [ 0 ] = a [ 0 ] xor rc [ round ]
}
companion object {
private val rc = longArrayOf (
+ 0x0000000000000001 , + 0x0000000000008082 , - 0x7fffffffffff7f76 , - 0x7fffffff7fff8000 ,
+ 0x000000000000808b , + 0x0000000080000001 , - 0x7fffffff7fff7f7f , - 0x7fffffffffff7ff7 ,
+ 0x000000000000008a , + 0x0000000000000088 , + 0x0000000080008009 , + 0x000000008000000a ,
+ 0x000000008000808b , - 0x7fffffffffffff75 , - 0x7fffffffffff7f77 , - 0x7fffffffffff7ffd ,
- 0x7fffffffffff7ffe , - 0x7fffffffffffff80 , + 0x000000000000800a , - 0x7fffffff7ffffff6 ,
- 0x7fffffff7fff7f7f , - 0x7fffffffffff7f80 , + 0x0000000080000001 , - 0x7fffffff7fff7ff8 ,
)
private val rotation = arrayOf (
intArrayOf ( 0 , 36 , 3 , 41 , 18 ) ,
intArrayOf ( 1 , 44 , 10 , 45 , 2 ) ,
intArrayOf ( 62 , 6 , 43 , 15 , 61 ) ,
intArrayOf ( 28 , 55 , 25 , 21 , 56 ) ,
intArrayOf ( 27 , 20 , 39 , 8 , 14 ) ,
)
}
}