package com.infendro.hash.sha1 import com.infendro.bytes.bytearray.copyInto import com.infendro.bytes.intarray.copyInto import com.infendro.hash.HashFunction class SHA1 : HashFunction(20, 64) { private val h = initial.copyOf() private val w = IntArray(80) private val v = IntArray(5) override fun reset() { super.reset() initial.copyInto(h) } override fun process() = process(buffer.value) private fun finalize() { buffer.append(0x80.toByte()) if (buffer.free < 8) { process() buffer.reset() } buffer.jumpTo(56) buffer.append(length * 8) process() } override fun digestInto(destination: ByteArray, destinationOffset: Int) { finalize() h.copyInto(destination, destinationOffset) reset() } private fun process(block: ByteArray) { block.copyInto(w) for (i in 16..<80) { w[i] = (w[i - 3] xor w[i - 8] xor w[i - 14] xor w[i - 16]).rotateLeft(1) } h.copyInto(v) repeat(80) { i -> val f = when (i) { in 0..<20 -> (v[1] and v[2]) or (v[1].inv() and v[3]) in 20..<40 -> v[1] xor v[2] xor v[3] in 40..<60 -> (v[1] and v[2]) or (v[1] and v[3]) or (v[2] and v[3]) else -> v[1] xor v[2] xor v[3] } val temp = v[0].rotateLeft(5) + f + v[4] + k[i / 20] + w[i] v[4] = v[3] v[3] = v[2] v[2] = v[1].rotateLeft(30) v[1] = v[0] v[0] = temp } for (i in 0..<5) { h[i] += v[i] } } companion object { private val initial = intArrayOf( +0x67452301, -0x10325477, -0x67452302, +0x10325476, -0x3c2d1e10, ) private val k = intArrayOf( +0x5a827999, +0x6ed9eba1, -0x70e44324, -0x359d3e2a, ) } }