Implement streaming API
This commit is contained in:
@@ -2,57 +2,45 @@ package com.infendro.hash.sha1
|
||||
|
||||
import com.infendro.bytes.bytearray.copyInto
|
||||
import com.infendro.bytes.intarray.copyInto
|
||||
import com.infendro.bytes.long.copyInto
|
||||
import com.infendro.hash.HashFunction
|
||||
import com.infendro.hash.util.align
|
||||
|
||||
object SHA1 : HashFunction {
|
||||
override val bytes: Int
|
||||
get() = 20
|
||||
class SHA1 : HashFunction(20, 64) {
|
||||
private val h = initial.copyOf()
|
||||
|
||||
override val block: Int
|
||||
get() = 64
|
||||
private val w = IntArray(80)
|
||||
private val v = IntArray(5)
|
||||
|
||||
private val initial = intArrayOf(
|
||||
+0x67452301, -0x10325477,
|
||||
-0x67452302, +0x10325476,
|
||||
-0x3c2d1e10,
|
||||
)
|
||||
override fun reset() {
|
||||
super.reset()
|
||||
initial.copyInto(h)
|
||||
}
|
||||
|
||||
private val k = intArrayOf(
|
||||
+0x5a827999, +0x6ed9eba1,
|
||||
-0x70e44324, -0x359d3e2a,
|
||||
)
|
||||
override fun process() = process(buffer.value)
|
||||
|
||||
override fun hashInto(value: ByteArray, destination: ByteArray, destinationOffset: Int) {
|
||||
val input = pad(value)
|
||||
val h = initial.copyOf()
|
||||
|
||||
for (i in input.indices step block) {
|
||||
val block = input.sliceArray(i..<(i + block))
|
||||
process(h, block)
|
||||
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 pad(value: ByteArray): ByteArray {
|
||||
val length = value.size * 8L
|
||||
|
||||
val size = (value.size + 9).align(block)
|
||||
return ByteArray(size).also {
|
||||
value.copyInto(it)
|
||||
it[value.size] = -0x80
|
||||
length.copyInto(it, size - 8)
|
||||
}
|
||||
}
|
||||
|
||||
private fun process(h: IntArray, block: ByteArray) {
|
||||
val w = IntArray(80)
|
||||
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)
|
||||
}
|
||||
val v = h.copyOf()
|
||||
h.copyInto(v)
|
||||
|
||||
repeat(80) { i ->
|
||||
val f = when (i) {
|
||||
@@ -73,4 +61,17 @@ object SHA1 : HashFunction {
|
||||
h[i] += v[i]
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val initial = intArrayOf(
|
||||
+0x67452301, -0x10325477,
|
||||
-0x67452302, +0x10325476,
|
||||
-0x3c2d1e10,
|
||||
)
|
||||
|
||||
private val k = intArrayOf(
|
||||
+0x5a827999, +0x6ed9eba1,
|
||||
-0x70e44324, -0x359d3e2a,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user