implement optimizations
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
package com.infendro.hash.sha1
|
||||
|
||||
import com.infendro.bytearray.toUByteArray
|
||||
import com.infendro.bytearray.toUIntArray
|
||||
import com.infendro.bytes.bytearray.copyInto
|
||||
import com.infendro.bytes.intarray.copyInto
|
||||
import com.infendro.bytes.ulong.copyInto
|
||||
import com.infendro.hash.HashFunction
|
||||
import com.infendro.hash.util.ceilPow2
|
||||
|
||||
object SHA1 : HashFunction {
|
||||
override val bytes: Int
|
||||
@@ -15,48 +17,42 @@ object SHA1 : HashFunction {
|
||||
0x67452301U, 0xefcdaB89U,
|
||||
0x98badcfeU, 0x10325476U,
|
||||
0xc3d2e1f0U,
|
||||
)
|
||||
).asIntArray()
|
||||
|
||||
override fun hash(
|
||||
value: UByteArray,
|
||||
): UByteArray {
|
||||
private val k = uintArrayOf(
|
||||
0x5a827999U, 0x6ed9eba1U,
|
||||
0x8f1bbcdcU, 0xca62c1d6U,
|
||||
).asIntArray()
|
||||
|
||||
override fun hashInto(value: ByteArray, destination: ByteArray) {
|
||||
val input = pad(value)
|
||||
val h = initial.copyOf()
|
||||
val w = IntArray(80)
|
||||
val v = IntArray(5)
|
||||
|
||||
val blocks = pad(value)
|
||||
.chunked(64) { it.toUByteArray() }
|
||||
for (block in blocks) {
|
||||
process(h, block)
|
||||
for (i in input.indices step block) {
|
||||
process(h, input, i, w, v)
|
||||
}
|
||||
|
||||
return h.toUByteArray()
|
||||
h.copyInto(destination)
|
||||
}
|
||||
|
||||
private fun pad(
|
||||
value: UByteArray,
|
||||
): UByteArray {
|
||||
val l = value.size.toULong() * 8UL
|
||||
return buildList {
|
||||
addAll(value)
|
||||
add(0x80U)
|
||||
while (size % 64 != 56) {
|
||||
add(0x00U)
|
||||
}
|
||||
addAll(l.toUByteArray())
|
||||
}.toUByteArray()
|
||||
private fun pad(value: ByteArray): ByteArray {
|
||||
val length = value.size.toULong() * 8UL
|
||||
|
||||
val size = ceilPow2(value.size + 9, block)
|
||||
val result = ByteArray(size)
|
||||
value.copyInto(result)
|
||||
result[value.size] = 0x80U.toByte()
|
||||
length.copyInto(result, result.size - 8)
|
||||
return result
|
||||
}
|
||||
|
||||
private fun process(
|
||||
h: UIntArray,
|
||||
block: UByteArray,
|
||||
) {
|
||||
val w = buildList {
|
||||
addAll(block.toUIntArray())
|
||||
for (i in 16..79) {
|
||||
val word = (get(i - 3) xor get(i - 8) xor get(i - 14) xor get(i - 16)).rotateLeft(1)
|
||||
add(word)
|
||||
}
|
||||
}.toUIntArray()
|
||||
val v = h.copyOf()
|
||||
private fun process(h: IntArray, value: ByteArray, offset: Int, w: IntArray, v: IntArray) {
|
||||
value.copyInto(w, startIndex = offset, endIndex = offset + block)
|
||||
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) {
|
||||
@@ -65,13 +61,7 @@ object SHA1 : HashFunction {
|
||||
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 k = when (i) {
|
||||
in 0..<20 -> 0x5a827999U
|
||||
in 20..<40 -> 0x6ed9eba1U
|
||||
in 40..<60 -> 0x8f1bbcdcU
|
||||
else -> 0xca62c1d6U
|
||||
}
|
||||
val temp = v[0].rotateLeft(5) + f + v[4] + k + w[i]
|
||||
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)
|
||||
@@ -79,7 +69,7 @@ object SHA1 : HashFunction {
|
||||
v[0] = temp
|
||||
}
|
||||
|
||||
for (i in 0..4) {
|
||||
for (i in 0..<5) {
|
||||
h[i] += v[i]
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user