Files
hash.kt/src/commonMain/kotlin/com/infendro/hash/sha1/SHA1.kt
2025-11-10 17:40:58 +01:00

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(),
)
}
}