implement optimizations
This commit is contained in:
@@ -1,9 +1,11 @@
|
||||
package com.infendro.hash.md
|
||||
|
||||
import com.infendro.bytearray.ByteOrder.LITTLE_ENDIAN
|
||||
import com.infendro.bytearray.toUByteArray
|
||||
import com.infendro.bytearray.toUIntArray
|
||||
import com.infendro.bytes.ByteOrder.LITTLE_ENDIAN
|
||||
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 MD5 : HashFunction {
|
||||
override val bytes: Int
|
||||
@@ -15,18 +17,7 @@ object MD5 : HashFunction {
|
||||
private val initial = uintArrayOf(
|
||||
0x67452301U, 0xefcdab89U,
|
||||
0x98badcfeU, 0x10325476U,
|
||||
)
|
||||
|
||||
private val shifts = intArrayOf(
|
||||
7, 12, 17, 22, 7, 12, 17, 22,
|
||||
7, 12, 17, 22, 7, 12, 17, 22,
|
||||
5, 9, 14, 20, 5, 9, 14, 20,
|
||||
5, 9, 14, 20, 5, 9, 14, 20,
|
||||
4, 11, 16, 23, 4, 11, 16, 23,
|
||||
4, 11, 16, 23, 4, 11, 16, 23,
|
||||
6, 10, 15, 21, 6, 10, 15, 21,
|
||||
6, 10, 15, 21, 6, 10, 15, 21,
|
||||
)
|
||||
).asIntArray()
|
||||
|
||||
private val c = uintArrayOf(
|
||||
0xd76aa478U, 0xe8c7b756U, 0x242070dbU, 0xc1bdceeeU,
|
||||
@@ -45,54 +36,57 @@ object MD5 : HashFunction {
|
||||
0x655b59c3U, 0x8f0ccc92U, 0xffeff47dU, 0x85845dd1U,
|
||||
0x6fa87e4fU, 0xfe2ce6e0U, 0xa3014314U, 0x4e0811a1U,
|
||||
0xf7537e82U, 0xbd3af235U, 0x2ad7d2bbU, 0xeb86d391U,
|
||||
).asIntArray()
|
||||
|
||||
private val shifts = intArrayOf(
|
||||
7, 12, 17, 22, 7, 12, 17, 22,
|
||||
7, 12, 17, 22, 7, 12, 17, 22,
|
||||
5, 9, 14, 20, 5, 9, 14, 20,
|
||||
5, 9, 14, 20, 5, 9, 14, 20,
|
||||
4, 11, 16, 23, 4, 11, 16, 23,
|
||||
4, 11, 16, 23, 4, 11, 16, 23,
|
||||
6, 10, 15, 21, 6, 10, 15, 21,
|
||||
6, 10, 15, 21, 6, 10, 15, 21,
|
||||
)
|
||||
|
||||
override fun hash(
|
||||
value: UByteArray,
|
||||
): UByteArray {
|
||||
override fun hashInto(value: ByteArray, destination: ByteArray) {
|
||||
val input = pad(value)
|
||||
val h = initial.copyOf()
|
||||
val w = IntArray(16)
|
||||
val v = IntArray(4)
|
||||
|
||||
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(LITTLE_ENDIAN)
|
||||
h.copyInto(destination, order = LITTLE_ENDIAN)
|
||||
}
|
||||
|
||||
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(LITTLE_ENDIAN))
|
||||
}.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, order = LITTLE_ENDIAN)
|
||||
return result
|
||||
}
|
||||
|
||||
private fun process(
|
||||
h: UIntArray,
|
||||
block: UByteArray,
|
||||
) {
|
||||
val w = block.toUIntArray(LITTLE_ENDIAN)
|
||||
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, order = LITTLE_ENDIAN)
|
||||
h.copyInto(v)
|
||||
|
||||
repeat(64) { i ->
|
||||
var f = when (i) {
|
||||
in 0..15 -> (v[1] and v[2]) or (v[1].inv() and v[3])
|
||||
in 16..31 -> (v[3] and v[1]) or (v[3].inv() and v[2])
|
||||
in 32..47 -> v[1] xor v[2] xor v[3]
|
||||
in 0..<16 -> (v[1] and v[2]) or (v[1].inv() and v[3])
|
||||
in 16..<32 -> (v[3] and v[1]) or (v[3].inv() and v[2])
|
||||
in 32..<48 -> v[1] xor v[2] xor v[3]
|
||||
else -> v[2] xor (v[1] or v[3].inv())
|
||||
}
|
||||
val g = when (i) {
|
||||
in 0..15 -> i
|
||||
in 16..31 -> (5 * i + 1) % 16
|
||||
in 32..47 -> (3 * i + 5) % 16
|
||||
in 0..<16 -> i
|
||||
in 16..<32 -> (5 * i + 1) % 16
|
||||
in 32..<48 -> (3 * i + 5) % 16
|
||||
else -> (7 * i) % 16
|
||||
}
|
||||
f += v[0] + c[i] + w[g]
|
||||
@@ -102,7 +96,7 @@ object MD5 : HashFunction {
|
||||
v[1] += f.rotateLeft(shifts[i])
|
||||
}
|
||||
|
||||
for (i in 0..3) {
|
||||
for (i in 0..<4) {
|
||||
h[i] += v[i]
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user