package com.infendro.hash.sha2 import com.infendro.bytes.bytearray.copyInto import com.infendro.bytes.longarray.copyInto import com.infendro.hash.HashFunction import com.infendro.hash.sha2.`SHA-512`.Companion.c class `SHA-384` : HashFunction(48, 128) { private val h = initial.copyOf() private val w = LongArray(80) private val v = LongArray(8) override fun reset() { super.reset() initial.copyInto(h) } override fun process() = process(buffer.value) private fun finalize() { buffer.append(0x80.toByte()) if (buffer.free < 16) { process(buffer.value) buffer.reset() } buffer.jumpTo(112) buffer.append(length * 8) process(buffer.value) } override fun digestInto(destination: ByteArray, destinationOffset: Int) { finalize() h.copyInto(destination, destinationOffset, endIndex = 6) reset() } private fun process(block: ByteArray) { block.copyInto(w) for (i in 16..<80) { val s0 = w[i - 15].rotateRight(1) xor w[i - 15].rotateRight(8) xor (w[i - 15] ushr 7) val s1 = w[i - 2].rotateRight(19) xor w[i - 2].rotateRight(61) xor (w[i - 2] ushr 6) w[i] = (w[i - 16] + s0 + w[i - 7] + s1) } h.copyInto(v) repeat(80) { i -> val s0 = v[0].rotateRight(28) xor v[0].rotateRight(34) xor v[0].rotateRight(39) val s1 = v[4].rotateRight(14) xor v[4].rotateRight(18) xor v[4].rotateRight(41) val ch = (v[4] and v[5]) xor (v[4].inv() and v[6]) val temp1 = v[7] + s1 + ch + c[i] + w[i] val maj = (v[0] and v[1]) xor (v[0] and v[2]) xor (v[1] and v[2]) val temp2 = s0 + maj v[7] = v[6] v[6] = v[5] v[5] = v[4] v[4] = v[3] + temp1 v[3] = v[2] v[2] = v[1] v[1] = v[0] v[0] = temp1 + temp2 } for (i in 0..<8) { h[i] += v[i] } } companion object { private val initial = longArrayOf( -0x344462a23efa6128, +0x629a292a367cd507, -0x6ea6fea5cf8f22e9, +0x152fecd8f70e5939, +0x67332667ffc00b31, -0x714bb57897a7eaef, -0x24f3d1f29b067059, +0x47b5481dbefa4fa4, ) } }