87 lines
2.3 KiB
Kotlin
87 lines
2.3 KiB
Kotlin
package com.infendro.hash.sha1
|
|
|
|
import com.infendro.bytearray.toUByteArray
|
|
import com.infendro.bytearray.toUIntArray
|
|
import com.infendro.hash.HashFunction
|
|
|
|
object SHA1 : HashFunction() {
|
|
override val bytes: Int
|
|
get() = 20
|
|
|
|
override val block: Int
|
|
get() = 64
|
|
|
|
override fun hash(
|
|
value: UByteArray,
|
|
): UByteArray {
|
|
var h0 = 0x67452301U
|
|
var h1 = 0xefcdaB89U
|
|
var h2 = 0x98badcfeU
|
|
var h3 = 0x10325476U
|
|
var h4 = 0xc3d2e1f0U
|
|
val ml = value.size.toULong() * 8UL
|
|
|
|
val paddedValue = buildList {
|
|
addAll(value)
|
|
add(0x80U)
|
|
while (size % 64 != 56) {
|
|
add(0x00U)
|
|
}
|
|
addAll(ml.toUByteArray())
|
|
}
|
|
|
|
val chunks = paddedValue
|
|
.chunked(64) { it.toUByteArray() }
|
|
for (chunk in chunks) {
|
|
val w = buildList {
|
|
addAll(chunk.toUIntArray())
|
|
for (i in 16..<80) {
|
|
val word = (get(i - 3) xor get(i - 8) xor get(i - 14) xor get(i - 16)).rotateLeft(1)
|
|
add(word)
|
|
}
|
|
}
|
|
|
|
var a = h0
|
|
var b = h1
|
|
var c = h2
|
|
var d = h3
|
|
var e = h4
|
|
|
|
for (i in 0..<80) {
|
|
val f = when (i) {
|
|
in 0..<20 -> (b and c) or (b.inv() and d)
|
|
in 20..<40 -> b xor c xor d
|
|
in 40..<60 -> (b and c) or (b and d) or (c and d)
|
|
else -> b xor c xor d
|
|
}
|
|
val k = when (i) {
|
|
in 0..<20 -> 0x5a827999U
|
|
in 20..<40 -> 0x6ed9eba1U
|
|
in 40..<60 -> 0x8f1bbcdcU
|
|
else -> 0xca62c1d6U
|
|
}
|
|
val temp = a.rotateLeft(5) + f + e + k + w[i]
|
|
e = d
|
|
d = c
|
|
c = b.rotateLeft(30)
|
|
b = a
|
|
a = temp
|
|
}
|
|
|
|
h0 += a
|
|
h1 += b
|
|
h2 += c
|
|
h3 += d
|
|
h4 += e
|
|
}
|
|
|
|
return ubyteArrayOf(
|
|
*h0.toUByteArray(),
|
|
*h1.toUByteArray(),
|
|
*h2.toUByteArray(),
|
|
*h3.toUByteArray(),
|
|
*h4.toUByteArray(),
|
|
)
|
|
}
|
|
}
|