78 lines
1.9 KiB
Kotlin
78 lines
1.9 KiB
Kotlin
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,
|
|
)
|
|
}
|
|
}
|