Compare commits

...

3 Commits

Author SHA1 Message Date
324d907d0c implement blake 2025-12-01 19:40:20 +01:00
8a2848e6e3 refactor hash functions 2025-12-01 19:13:58 +01:00
10ba03dedc upgrade kotlin version and dependencies 2025-12-01 19:13:26 +01:00
16 changed files with 1167 additions and 394 deletions

View File

@@ -1,6 +1,6 @@
[versions] [versions]
kotlin = "2.1.20" kotlin = "2.2.21"
bytearray = "1.2.2" bytearray = "1.2.3"
[plugins] [plugins]
multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }

View File

@@ -0,0 +1,127 @@
package com.infendro.hash.blake
import com.infendro.bytearray.toUByteArray
import com.infendro.bytearray.toUIntArray
import com.infendro.hash.HashFunction
object `Blake-224` : HashFunction() {
override val bytes: Int
get() = 28
override val block: Int
get() = 64
private val initial = uintArrayOf(
0xc1059ed8U, 0x367cd507U,
0x3070dd17U, 0xf70e5939U,
0xffc00b31U, 0x68581511U,
0x64f98fa7U, 0xbefa4fa4U,
)
private val c = uintArrayOf(
0x243f6a88U, 0x85a308d3U,
0x13198a2eU, 0x03707344U,
0xa4093822U, 0x299f31d0U,
0x082efa98U, 0xec4e6c89U,
0x452821e6U, 0x38d01377U,
0xbe5466cfU, 0x34e90c6cU,
0xc0ac29b7U, 0xc97c50ddU,
0x3f84d5b5U, 0xb5470917U,
)
private val sigma = arrayOf(
intArrayOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15),
intArrayOf(14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3),
intArrayOf(11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4),
intArrayOf(7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8),
intArrayOf(9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13),
intArrayOf(2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9),
intArrayOf(12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11),
intArrayOf(13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10),
intArrayOf(6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5),
intArrayOf(10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0),
)
override fun hash(value: UByteArray): UByteArray {
val h = initial.copyOf()
var t = 0U
val l = value.size.toULong() * 8UL
// padding
val paddedValue = buildList {
addAll(value)
add(0x80U)
while (size % 64 != 56) {
add(0x00U)
}
addAll(l.toUByteArray())
}.toUByteArray()
// compress
val blocks = paddedValue
.chunked(64) { it.toUByteArray() }
for (block in blocks) {
t += minOf(l - t, 512UL).toUInt()
val m = block.toUIntArray()
compress(h, m, t)
}
return h.sliceArray(0..6).toUByteArray()
}
private fun compress(
h: UIntArray,
m: UIntArray,
t: UInt,
) {
// initialization
val v = UIntArray(16)
for (i in 0..<8) v[i] = h[i]
for (i in 0..<4) v[i + 8] = c[i]
for (i in 0..<2) v[i + 12] = c[i + 4] xor t
for (i in 0..<2) v[i + 14] = c[i + 6]
// rounds
for (r in 0..<14) {
val s = sigma[r % 10]
// column
g(v, 0, 4, 8, 12, m[s[0]] xor c[s[1]], m[s[1]] xor c[s[0]])
g(v, 1, 5, 9, 13, m[s[2]] xor c[s[3]], m[s[3]] xor c[s[2]])
g(v, 2, 6, 10, 14, m[s[4]] xor c[s[5]], m[s[5]] xor c[s[4]])
g(v, 3, 7, 11, 15, m[s[6]] xor c[s[7]], m[s[7]] xor c[s[6]])
// diagonal
g(v, 0, 5, 10, 15, m[s[8]] xor c[s[9]], m[s[9]] xor c[s[8]])
g(v, 1, 6, 11, 12, m[s[10]] xor c[s[11]], m[s[11]] xor c[s[10]])
g(v, 2, 7, 8, 13, m[s[12]] xor c[s[13]], m[s[13]] xor c[s[12]])
g(v, 3, 4, 9, 14, m[s[14]] xor c[s[15]], m[s[15]] xor c[s[14]])
}
// finalization
for (i in 0..7) {
h[i] = h[i] xor v[i] xor v[i + 8]
}
}
// round function
private fun g(
v: UIntArray,
a: Int,
b: Int,
c: Int,
d: Int,
x: UInt,
y: UInt,
) {
v[a] += v[b] + x
v[d] = (v[d] xor v[a]).rotateRight(16)
v[c] += v[d]
v[b] = (v[b] xor v[c]).rotateRight(12)
v[a] += v[b] + y
v[d] = (v[d] xor v[a]).rotateRight(8)
v[c] += v[d]
v[b] = (v[b] xor v[c]).rotateRight(7)
}
}

View File

@@ -0,0 +1,128 @@
package com.infendro.hash.blake
import com.infendro.bytearray.toUByteArray
import com.infendro.bytearray.toUIntArray
import com.infendro.hash.HashFunction
object `Blake-256` : HashFunction() {
override val bytes: Int
get() = 32
override val block: Int
get() = 64
private val initial = uintArrayOf(
0x6a09e667U, 0xbb67ae85U,
0x3c6ef372U, 0xa54ff53aU,
0x510e527fU, 0x9b05688cU,
0x1f83d9abU, 0x5be0cd19U,
)
private val c = uintArrayOf(
0x243f6a88U, 0x85a308d3U,
0x13198a2eU, 0x03707344U,
0xa4093822U, 0x299f31d0U,
0x082efa98U, 0xec4e6c89U,
0x452821e6U, 0x38d01377U,
0xbe5466cfU, 0x34e90c6cU,
0xc0ac29b7U, 0xc97c50ddU,
0x3f84d5b5U, 0xb5470917U,
)
private val sigma = arrayOf(
intArrayOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15),
intArrayOf(14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3),
intArrayOf(11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4),
intArrayOf(7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8),
intArrayOf(9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13),
intArrayOf(2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9),
intArrayOf(12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11),
intArrayOf(13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10),
intArrayOf(6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5),
intArrayOf(10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0),
)
override fun hash(value: UByteArray): UByteArray {
val h = initial.copyOf()
var t = 0U
val l = value.size.toULong() * 8UL
// padding
val paddedValue = buildList {
addAll(value)
add(0x80U)
while (size % 64 != 55) {
add(0x00U)
}
add(0x01U)
addAll(l.toUByteArray())
}.toUByteArray()
// compress
val blocks = paddedValue
.chunked(64) { it.toUByteArray() }
for (block in blocks) {
t += minOf(l - t, 512UL).toUInt()
val m = block.toUIntArray()
compress(h, m, t)
}
return h.toUByteArray()
}
private fun compress(
h: UIntArray,
m: UIntArray,
t: UInt,
) {
// initialization
val v = UIntArray(16)
for (i in 0..<8) v[i] = h[i]
for (i in 0..<4) v[i + 8] = c[i]
for (i in 0..<2) v[i + 12] = c[i + 4] xor t
for (i in 0..<2) v[i + 14] = c[i + 6]
// rounds
for (r in 0..<14) {
val s = sigma[r % 10]
// column
g(v, 0, 4, 8, 12, m[s[0]] xor c[s[1]], m[s[1]] xor c[s[0]])
g(v, 1, 5, 9, 13, m[s[2]] xor c[s[3]], m[s[3]] xor c[s[2]])
g(v, 2, 6, 10, 14, m[s[4]] xor c[s[5]], m[s[5]] xor c[s[4]])
g(v, 3, 7, 11, 15, m[s[6]] xor c[s[7]], m[s[7]] xor c[s[6]])
// diagonal
g(v, 0, 5, 10, 15, m[s[8]] xor c[s[9]], m[s[9]] xor c[s[8]])
g(v, 1, 6, 11, 12, m[s[10]] xor c[s[11]], m[s[11]] xor c[s[10]])
g(v, 2, 7, 8, 13, m[s[12]] xor c[s[13]], m[s[13]] xor c[s[12]])
g(v, 3, 4, 9, 14, m[s[14]] xor c[s[15]], m[s[15]] xor c[s[14]])
}
// finalization
for (i in 0..7) {
h[i] = h[i] xor v[i] xor v[i + 8]
}
}
// round function
private fun g(
v: UIntArray,
a: Int,
b: Int,
c: Int,
d: Int,
x: UInt,
y: UInt,
) {
v[a] += v[b] + x
v[d] = (v[d] xor v[a]).rotateRight(16)
v[c] += v[d]
v[b] = (v[b] xor v[c]).rotateRight(12)
v[a] += v[b] + y
v[d] = (v[d] xor v[a]).rotateRight(8)
v[c] += v[d]
v[b] = (v[b] xor v[c]).rotateRight(7)
}
}

View File

@@ -0,0 +1,127 @@
package com.infendro.hash.blake
import com.infendro.bytearray.toUByteArray
import com.infendro.bytearray.toULongArray
import com.infendro.hash.HashFunction
object `Blake-384` : HashFunction() {
override val bytes: Int
get() = 48
override val block: Int
get() = 128
private val initial = ulongArrayOf(
0xcbbb9d5dc1059ed8U, 0x629a292a367cd507U,
0x9159015a3070dd17U, 0x152fecd8f70e5939U,
0x67332667ffc00b31U, 0x8eb44a8768581511U,
0xdb0c2e0d64f98fa7U, 0x47b5481dbefa4fa4U,
)
private val c = ulongArrayOf(
0x243f6a8885a308d3UL, 0x13198a2e03707344UL,
0xa4093822299f31d0UL, 0x082efa98ec4e6c89UL,
0x452821e638d01377UL, 0xbe5466cf34e90c6cUL,
0xc0ac29b7c97c50ddUL, 0x3f84d5b5b5470917UL,
0x9216d5d98979fb1bUL, 0xd1310ba698dfb5acUL,
0x2ffd72dbd01adfb7UL, 0xb8e1afed6a267e96UL,
0xba7c9045f12c7f99UL, 0x24a19947b3916cf7UL,
0x0801f2e2858efc16UL, 0x636920d871574e69UL,
)
private val sigma = arrayOf(
intArrayOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15),
intArrayOf(14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3),
intArrayOf(11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4),
intArrayOf(7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8),
intArrayOf(9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13),
intArrayOf(2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9),
intArrayOf(12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11),
intArrayOf(13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10),
intArrayOf(6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5),
intArrayOf(10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0),
)
override fun hash(value: UByteArray): UByteArray {
val h = initial.copyOf()
var t = 0UL
val l = value.size.toULong() * 8UL
// padding
val paddedValue = buildList {
addAll(value)
add(0x80U)
while (size % 128 != 120) {
add(0x00U)
}
addAll(l.toUByteArray())
}.toUByteArray()
// compress
val blocks = paddedValue
.chunked(128) { it.toUByteArray() }
for (block in blocks) {
t += minOf(l - t, 1024UL)
val m = block.toULongArray()
compress(h, m, t)
}
return h.sliceArray(0..5).toUByteArray()
}
private fun compress(
h: ULongArray,
m: ULongArray,
t: ULong,
) {
// initialization
val v = ULongArray(16)
for (i in 0..<8) v[i] = h[i]
for (i in 0..<4) v[i + 8] = c[i]
for (i in 0..<2) v[i + 12] = c[i + 4] xor t
for (i in 0..<2) v[i + 14] = c[i + 6]
// rounds
for (r in 0..<16) {
val s = sigma[r % 10]
// column
g(v, 0, 4, 8, 12, m[s[0]] xor c[s[1]], m[s[1]] xor c[s[0]])
g(v, 1, 5, 9, 13, m[s[2]] xor c[s[3]], m[s[3]] xor c[s[2]])
g(v, 2, 6, 10, 14, m[s[4]] xor c[s[5]], m[s[5]] xor c[s[4]])
g(v, 3, 7, 11, 15, m[s[6]] xor c[s[7]], m[s[7]] xor c[s[6]])
// diagonal
g(v, 0, 5, 10, 15, m[s[8]] xor c[s[9]], m[s[9]] xor c[s[8]])
g(v, 1, 6, 11, 12, m[s[10]] xor c[s[11]], m[s[11]] xor c[s[10]])
g(v, 2, 7, 8, 13, m[s[12]] xor c[s[13]], m[s[13]] xor c[s[12]])
g(v, 3, 4, 9, 14, m[s[14]] xor c[s[15]], m[s[15]] xor c[s[14]])
}
// finalization
for (i in 0..7) {
h[i] = h[i] xor v[i] xor v[i + 8]
}
}
// round function
private fun g(
v: ULongArray,
a: Int,
b: Int,
c: Int,
d: Int,
x: ULong,
y: ULong,
) {
v[a] += v[b] + x
v[d] = (v[d] xor v[a]).rotateRight(32)
v[c] += v[d]
v[b] = (v[b] xor v[c]).rotateRight(25)
v[a] += v[b] + y
v[d] = (v[d] xor v[a]).rotateRight(16)
v[c] += v[d]
v[b] = (v[b] xor v[c]).rotateRight(11)
}
}

View File

@@ -0,0 +1,129 @@
package com.infendro.hash.blake
import com.infendro.bytearray.toUByteArray
import com.infendro.bytearray.toULongArray
import com.infendro.hash.HashFunction
object `Blake-512` : HashFunction() {
override val bytes: Int
get() = 64
override val block: Int
get() = 128
private val initial = ulongArrayOf(
0x6a09e667f3bcc908UL, 0xbb67ae8584caa73bUL,
0x3c6ef372fe94f82bUL, 0xa54ff53a5f1d36f1UL,
0x510e527fade682d1UL, 0x9b05688c2b3e6c1fUL,
0x1f83d9abfb41bd6bUL, 0x5be0cd19137e2179UL,
)
private val c = ulongArrayOf(
0x243f6a8885a308d3UL, 0x13198a2e03707344UL,
0xa4093822299f31d0UL, 0x082efa98ec4e6c89UL,
0x452821e638d01377UL, 0xbe5466cf34e90c6cUL,
0xc0ac29b7c97c50ddUL, 0x3f84d5b5b5470917UL,
0x9216d5d98979fb1bUL, 0xd1310ba698dfb5acUL,
0x2ffd72dbd01adfb7UL, 0xb8e1afed6a267e96UL,
0xba7c9045f12c7f99UL, 0x24a19947b3916cf7UL,
0x0801f2e2858efc16UL, 0x636920d871574e69UL,
)
private val sigma = arrayOf(
intArrayOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15),
intArrayOf(14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3),
intArrayOf(11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4),
intArrayOf(7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8),
intArrayOf(9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13),
intArrayOf(2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9),
intArrayOf(12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11),
intArrayOf(13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10),
intArrayOf(6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5),
intArrayOf(10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0),
)
override fun hash(value: UByteArray): UByteArray {
val h = initial.copyOf()
var t = 0UL
val l = value.size.toULong() * 8UL
// padding
val paddedValue = buildList {
addAll(value)
add(0x80U)
while (size % 128 != 111) {
add(0x00U)
}
add(0x01U)
repeat(8) { add(0x00U) }
addAll(l.toUByteArray())
}.toUByteArray()
// compress
val blocks = paddedValue
.chunked(128) { it.toUByteArray() }
for (block in blocks) {
t += minOf(l - t, 1024UL)
val m = block.toULongArray()
compress(h, m, t)
}
return h.toUByteArray()
}
private fun compress(
h: ULongArray,
m: ULongArray,
t: ULong,
) {
// initialization
val v = ULongArray(16)
for (i in 0..<8) v[i] = h[i]
for (i in 0..<4) v[i + 8] = c[i]
for (i in 0..<2) v[i + 12] = c[i + 4] xor t
for (i in 0..<2) v[i + 14] = c[i + 6]
// rounds
for (r in 0..<16) {
val s = sigma[r % 10]
// column
g(v, 0, 4, 8, 12, m[s[0]] xor c[s[1]], m[s[1]] xor c[s[0]])
g(v, 1, 5, 9, 13, m[s[2]] xor c[s[3]], m[s[3]] xor c[s[2]])
g(v, 2, 6, 10, 14, m[s[4]] xor c[s[5]], m[s[5]] xor c[s[4]])
g(v, 3, 7, 11, 15, m[s[6]] xor c[s[7]], m[s[7]] xor c[s[6]])
// diagonal
g(v, 0, 5, 10, 15, m[s[8]] xor c[s[9]], m[s[9]] xor c[s[8]])
g(v, 1, 6, 11, 12, m[s[10]] xor c[s[11]], m[s[11]] xor c[s[10]])
g(v, 2, 7, 8, 13, m[s[12]] xor c[s[13]], m[s[13]] xor c[s[12]])
g(v, 3, 4, 9, 14, m[s[14]] xor c[s[15]], m[s[15]] xor c[s[14]])
}
// finalization
for (i in 0..7) {
h[i] = h[i] xor v[i] xor v[i + 8]
}
}
// round function
private fun g(
v: ULongArray,
a: Int,
b: Int,
c: Int,
d: Int,
x: ULong,
y: ULong,
) {
v[a] += v[b] + x
v[d] = (v[d] xor v[a]).rotateRight(32)
v[c] += v[d]
v[b] = (v[b] xor v[c]).rotateRight(25)
v[a] += v[b] + y
v[d] = (v[d] xor v[a]).rotateRight(16)
v[c] += v[d]
v[b] = (v[b] xor v[c]).rotateRight(11)
}
}

View File

@@ -19,7 +19,7 @@ abstract class Keccak internal constructor(
0x000000000000008aUL, 0x0000000000000088UL, 0x0000000080008009UL, 0x000000008000000aUL, 0x000000000000008aUL, 0x0000000000000088UL, 0x0000000080008009UL, 0x000000008000000aUL,
0x000000008000808bUL, 0x800000000000008bUL, 0x8000000000008089UL, 0x8000000000008003UL, 0x000000008000808bUL, 0x800000000000008bUL, 0x8000000000008089UL, 0x8000000000008003UL,
0x8000000000008002UL, 0x8000000000000080UL, 0x000000000000800aUL, 0x800000008000000aUL, 0x8000000000008002UL, 0x8000000000000080UL, 0x000000000000800aUL, 0x800000008000000aUL,
0x8000000080008081UL, 0x8000000000008080UL, 0x0000000080000001UL, 0x8000000080008008UL 0x8000000080008081UL, 0x8000000000008080UL, 0x0000000080000001UL, 0x8000000080008008UL,
) )
private val rotation = arrayOf( private val rotation = arrayOf(
@@ -33,6 +33,9 @@ abstract class Keccak internal constructor(
override fun hash( override fun hash(
value: UByteArray, value: UByteArray,
): UByteArray { ): UByteArray {
val state = ULongArray(25)
// padding
val paddedValue = buildList { val paddedValue = buildList {
addAll(value) addAll(value)
add(domain) add(domain)
@@ -42,13 +45,11 @@ abstract class Keccak internal constructor(
add(0x80U) add(0x80U)
} }
val state = ULongArray(25)
// absorb // absorb
val chunks = paddedValue val blocks = paddedValue
.chunked(rate) { it.toUByteArray() } .chunked(rate) { it.toUByteArray() }
for (chunk in chunks) { for (block in blocks) {
val numbers = chunk.toULongArray(LITTLE_ENDIAN) val numbers = block.toULongArray(LITTLE_ENDIAN)
for ((i, number) in numbers.withIndex()) { for ((i, number) in numbers.withIndex()) {
state[i] = state[i] xor number state[i] = state[i] xor number
} }

View File

@@ -12,26 +12,23 @@ object MD5 : HashFunction() {
override val block: Int override val block: Int
get() = 64 get() = 64
private val s = intArrayOf( private val initial = uintArrayOf(
7, 12, 17, 22, 0x67452301U, 0xefcdab89U,
7, 12, 17, 22, 0x98badcfeU, 0x10325476U,
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,
) )
private val k = uintArrayOf( 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,
)
private val c = uintArrayOf(
0xd76aa478U, 0xe8c7b756U, 0x242070dbU, 0xc1bdceeeU, 0xd76aa478U, 0xe8c7b756U, 0x242070dbU, 0xc1bdceeeU,
0xf57c0fafU, 0x4787c62aU, 0xa8304613U, 0xfd469501U, 0xf57c0fafU, 0x4787c62aU, 0xa8304613U, 0xfd469501U,
0x698098d8U, 0x8b44f7afU, 0xffff5bb1U, 0x895cd7beU, 0x698098d8U, 0x8b44f7afU, 0xffff5bb1U, 0x895cd7beU,
@@ -53,39 +50,42 @@ object MD5 : HashFunction() {
override fun hash( override fun hash(
value: UByteArray, value: UByteArray,
): UByteArray { ): UByteArray {
var a0 = 0x67452301U val h = initial.copyOf()
var b0 = 0xefcdab89U val l = value.size.toULong() * 8UL
var c0 = 0x98badcfeU
var d0 = 0x10325476U
val ml = value.size.toULong() * 8UL
// padding
val paddedValue = buildList { val paddedValue = buildList {
addAll(value) addAll(value)
add(0x80U) add(0x80U)
while (size % 64 != 56) { while (size % 64 != 56) {
add(0x00U) add(0x00U)
} }
addAll(ml.toUByteArray(LITTLE_ENDIAN)) addAll(l.toUByteArray(LITTLE_ENDIAN))
} }
val chunks = paddedValue // process
val blocks = paddedValue
.chunked(64) { it.toUByteArray() } .chunked(64) { it.toUByteArray() }
for (chunk in chunks) { for (block in blocks) {
val w = buildList { val w = block.toUIntArray(LITTLE_ENDIAN)
addAll(chunk.toUIntArray(LITTLE_ENDIAN)) process(h, w)
} }
var a = a0 return h.toUByteArray(LITTLE_ENDIAN)
var b = b0 }
var c = c0
var d = d0 private fun process(
h: UIntArray,
w: UIntArray,
) {
val v = h.copyOf()
for (i in 0..<64) { for (i in 0..<64) {
val f = when (i) { var f = when (i) {
in 0..15 -> (b and c) or (b.inv() and d) in 0..15 -> (v[1] and v[2]) or (v[1].inv() and v[3])
in 16..31 -> (d and b) or (d.inv() and c) in 16..31 -> (v[3] and v[1]) or (v[3].inv() and v[2])
in 32..47 -> b xor c xor d in 32..47 -> v[1] xor v[2] xor v[3]
else -> c xor (b or d.inv()) else -> v[2] xor (v[1] or v[3].inv())
} }
val g = when (i) { val g = when (i) {
in 0..15 -> i in 0..15 -> i
@@ -93,24 +93,15 @@ object MD5 : HashFunction() {
in 32..47 -> (3 * i + 5) % 16 in 32..47 -> (3 * i + 5) % 16
else -> (7 * i) % 16 else -> (7 * i) % 16
} }
val temp = a f += v[0] + c[i] + w[g]
a = d v[0] = v[3]
d = c v[3] = v[2]
c = b v[2] = v[1]
b += (temp + f + k[i] + w[g]).rotateLeft(s[i]) v[1] += f.rotateLeft(shifts[i])
} }
a0 += a for (i in 0..3) {
b0 += b h[i] += v[i]
c0 += c }
d0 += d
}
return ubyteArrayOf(
*a0.toUByteArray(LITTLE_ENDIAN),
*b0.toUByteArray(LITTLE_ENDIAN),
*c0.toUByteArray(LITTLE_ENDIAN),
*d0.toUByteArray(LITTLE_ENDIAN),
)
} }
} }

View File

@@ -11,48 +11,57 @@ object SHA1 : HashFunction() {
override val block: Int override val block: Int
get() = 64 get() = 64
private val initial = uintArrayOf(
0x67452301U, 0xefcdaB89U,
0x98badcfeU, 0x10325476U,
0xc3d2e1f0U,
)
override fun hash( override fun hash(
value: UByteArray, value: UByteArray,
): UByteArray { ): UByteArray {
var h0 = 0x67452301U val h = initial.copyOf()
var h1 = 0xefcdaB89U val l = value.size.toULong() * 8UL
var h2 = 0x98badcfeU
var h3 = 0x10325476U
var h4 = 0xc3d2e1f0U
val ml = value.size.toULong() * 8UL
// padding
val paddedValue = buildList { val paddedValue = buildList {
addAll(value) addAll(value)
add(0x80U) add(0x80U)
while (size % 64 != 56) { while (size % 64 != 56) {
add(0x00U) add(0x00U)
} }
addAll(ml.toUByteArray()) addAll(l.toUByteArray())
} }
val chunks = paddedValue // process
val blocks = paddedValue
.chunked(64) { it.toUByteArray() } .chunked(64) { it.toUByteArray() }
for (chunk in chunks) { for (block in blocks) {
val w = buildList { val w = buildList {
addAll(chunk.toUIntArray()) addAll(block.toUIntArray())
for (i in 16..<80) { for (i in 16..<80) {
val word = (get(i - 3) xor get(i - 8) xor get(i - 14) xor get(i - 16)).rotateLeft(1) val word = (get(i - 3) xor get(i - 8) xor get(i - 14) xor get(i - 16)).rotateLeft(1)
add(word) add(word)
} }
}.toUIntArray()
process(h, w)
} }
var a = h0 return h.toUByteArray()
var b = h1 }
var c = h2
var d = h3 private fun process(
var e = h4 h: UIntArray,
w: UIntArray,
) {
val v = h.copyOf()
for (i in 0..<80) { for (i in 0..<80) {
val f = when (i) { val f = when (i) {
in 0..<20 -> (b and c) or (b.inv() and d) in 0..<20 -> (v[1] and v[2]) or (v[1].inv() and v[3])
in 20..<40 -> b xor c xor d in 20..<40 -> v[1] xor v[2] xor v[3]
in 40..<60 -> (b and c) or (b and d) or (c and d) in 40..<60 -> (v[1] and v[2]) or (v[1] and v[3]) or (v[2] and v[3])
else -> b xor c xor d else -> v[1] xor v[2] xor v[3]
} }
val k = when (i) { val k = when (i) {
in 0..<20 -> 0x5a827999U in 0..<20 -> 0x5a827999U
@@ -60,27 +69,16 @@ object SHA1 : HashFunction() {
in 40..<60 -> 0x8f1bbcdcU in 40..<60 -> 0x8f1bbcdcU
else -> 0xca62c1d6U else -> 0xca62c1d6U
} }
val temp = a.rotateLeft(5) + f + e + k + w[i] val temp = v[0].rotateLeft(5) + f + v[4] + k + w[i]
e = d v[4] = v[3]
d = c v[3] = v[2]
c = b.rotateLeft(30) v[2] = v[1].rotateLeft(30)
b = a v[1] = v[0]
a = temp v[0] = temp
} }
h0 += a for (i in 0..4) {
h1 += b h[i] += v[i]
h2 += c }
h3 += d
h4 += e
}
return ubyteArrayOf(
*h0.toUByteArray(),
*h1.toUByteArray(),
*h2.toUByteArray(),
*h3.toUByteArray(),
*h4.toUByteArray(),
)
} }
} }

View File

@@ -11,7 +11,14 @@ object `SHA-224` : HashFunction() {
override val block: Int override val block: Int
get() = 64 get() = 64
private val k = uintArrayOf( private val initial = uintArrayOf(
0xc1059ed8U, 0x367cd507U,
0x3070dd17U, 0xf70e5939U,
0xffc00b31U, 0x68581511U,
0x64f98fa7U, 0xbefa4fa4U,
)
private val c = uintArrayOf(
0x428a2f98U, 0x71374491U, 0xb5c0fbcfU, 0xe9b5dba5U, 0x3956c25bU, 0x59f111f1U, 0x923f82a4U, 0xab1c5ed5U, 0x428a2f98U, 0x71374491U, 0xb5c0fbcfU, 0xe9b5dba5U, 0x3956c25bU, 0x59f111f1U, 0x923f82a4U, 0xab1c5ed5U,
0xd807aa98U, 0x12835b01U, 0x243185beU, 0x550c7dc3U, 0x72be5d74U, 0x80deb1feU, 0x9bdc06a7U, 0xc19bf174U, 0xd807aa98U, 0x12835b01U, 0x243185beU, 0x550c7dc3U, 0x72be5d74U, 0x80deb1feU, 0x9bdc06a7U, 0xc19bf174U,
0xe49b69c1U, 0xefbe4786U, 0x0fc19dc6U, 0x240ca1ccU, 0x2de92c6fU, 0x4a7484aaU, 0x5cb0a9dcU, 0x76f988daU, 0xe49b69c1U, 0xefbe4786U, 0x0fc19dc6U, 0x240ca1ccU, 0x2de92c6fU, 0x4a7484aaU, 0x5cb0a9dcU, 0x76f988daU,
@@ -25,82 +32,63 @@ object `SHA-224` : HashFunction() {
override fun hash( override fun hash(
value: UByteArray, value: UByteArray,
): UByteArray { ): UByteArray {
var h0 = 0xc1059ed8U val h = initial.copyOf()
var h1 = 0x367cd507U val l = value.size.toULong() * 8UL
var h2 = 0x3070dd17U
var h3 = 0xf70e5939U
var h4 = 0xffc00b31U
var h5 = 0x68581511U
var h6 = 0x64f98fa7U
var h7 = 0xbefa4fa4U
val ml = value.size.toULong() * 8UL
// padding
val paddedValue = buildList { val paddedValue = buildList {
addAll(value) addAll(value)
add(0x80U) add(0x80U)
while (size % 64 != 56) { while (size % 64 != 56) {
add(0x00U) add(0x00U)
} }
addAll(ml.toUByteArray()) addAll(l.toUByteArray())
} }
val chunks = paddedValue // process
val blocks = paddedValue
.chunked(64) { it.toUByteArray() } .chunked(64) { it.toUByteArray() }
for (chunk in chunks) { for (block in blocks) {
val w = buildList { val w = buildList {
addAll(chunk.toUIntArray()) addAll(block.toUIntArray())
for (i in 16..<64) { for (i in 16..<64) {
val s0 = get(i - 15).rotateRight(7) xor get(i - 15).rotateRight(18) xor (get(i - 15) shr 3) val s0 = get(i - 15).rotateRight(7) xor get(i - 15).rotateRight(18) xor (get(i - 15) shr 3)
val s1 = get(i - 2).rotateRight(17) xor get(i - 2).rotateRight(19) xor (get(i - 2) shr 10) val s1 = get(i - 2).rotateRight(17) xor get(i - 2).rotateRight(19) xor (get(i - 2) shr 10)
add(get(i - 16) + s0 + get(i - 7) + s1) add(get(i - 16) + s0 + get(i - 7) + s1)
} }
}.toUIntArray()
process(h, w)
} }
var a = h0 return h.sliceArray(0..6).toUByteArray()
var b = h1 }
var c = h2
var d = h3 private fun process(
var e = h4 h: UIntArray,
var f = h5 w: UIntArray,
var g = h6 ) {
var h = h7 val v = h.copyOf()
for (i in 0..<64) { for (i in 0..<64) {
val s0 = a.rotateRight(2) xor a.rotateRight(13) xor a.rotateRight(22) val s0 = v[0].rotateRight(2) xor v[0].rotateRight(13) xor v[0].rotateRight(22)
val s1 = e.rotateRight(6) xor e.rotateRight(11) xor e.rotateRight(25) val s1 = v[4].rotateRight(6) xor v[4].rotateRight(11) xor v[4].rotateRight(25)
val ch = (e and f) xor (e.inv() and g) val ch = (v[4] and v[5]) xor (v[4].inv() and v[6])
val temp1 = h + s1 + ch + k[i] + w[i] val temp1 = v[7] + s1 + ch + this.c[i] + w[i]
val maj = (a and b) xor (a and c) xor (b and c) val maj = (v[0] and v[1]) xor (v[0] and v[2]) xor (v[1] and v[2])
val temp2 = s0 + maj val temp2 = s0 + maj
h = g v[7] = v[6]
g = f v[6] = v[5]
f = e v[5] = v[4]
e = d + temp1 v[4] = v[3] + temp1
d = c v[3] = v[2]
c = b v[2] = v[1]
b = a v[1] = v[0]
a = temp1 + temp2 v[0] = temp1 + temp2
} }
h0 += a for (i in 0..7) {
h1 += b h[i] += v[i]
h2 += c }
h3 += d
h4 += e
h5 += f
h6 += g
h7 += h
}
return ubyteArrayOf(
*h0.toUByteArray(),
*h1.toUByteArray(),
*h2.toUByteArray(),
*h3.toUByteArray(),
*h4.toUByteArray(),
*h5.toUByteArray(),
*h6.toUByteArray(),
)
} }
} }

View File

@@ -11,7 +11,14 @@ object `SHA-256` : HashFunction() {
override val block: Int override val block: Int
get() = 64 get() = 64
private val k = uintArrayOf( private val initial = uintArrayOf(
0x6a09e667U, 0xbb67ae85U,
0x3c6ef372U, 0xa54ff53aU,
0x510e527fU, 0x9b05688cU,
0x1f83d9abU, 0x5be0cd19U,
)
private val c = uintArrayOf(
0x428a2f98U, 0x71374491U, 0xb5c0fbcfU, 0xe9b5dba5U, 0x3956c25bU, 0x59f111f1U, 0x923f82a4U, 0xab1c5ed5U, 0x428a2f98U, 0x71374491U, 0xb5c0fbcfU, 0xe9b5dba5U, 0x3956c25bU, 0x59f111f1U, 0x923f82a4U, 0xab1c5ed5U,
0xd807aa98U, 0x12835b01U, 0x243185beU, 0x550c7dc3U, 0x72be5d74U, 0x80deb1feU, 0x9bdc06a7U, 0xc19bf174U, 0xd807aa98U, 0x12835b01U, 0x243185beU, 0x550c7dc3U, 0x72be5d74U, 0x80deb1feU, 0x9bdc06a7U, 0xc19bf174U,
0xe49b69c1U, 0xefbe4786U, 0x0fc19dc6U, 0x240ca1ccU, 0x2de92c6fU, 0x4a7484aaU, 0x5cb0a9dcU, 0x76f988daU, 0xe49b69c1U, 0xefbe4786U, 0x0fc19dc6U, 0x240ca1ccU, 0x2de92c6fU, 0x4a7484aaU, 0x5cb0a9dcU, 0x76f988daU,
@@ -25,25 +32,20 @@ object `SHA-256` : HashFunction() {
override fun hash( override fun hash(
value: UByteArray, value: UByteArray,
): UByteArray { ): UByteArray {
var h0 = 0x6a09e667U val h = initial.copyOf()
var h1 = 0xbb67ae85U val l = value.size.toULong() * 8UL
var h2 = 0x3c6ef372U
var h3 = 0xa54ff53aU
var h4 = 0x510e527fU
var h5 = 0x9b05688cU
var h6 = 0x1f83d9abU
var h7 = 0x5be0cd19U
val ml = value.size.toULong() * 8UL
// padding
val paddedValue = buildList { val paddedValue = buildList {
addAll(value) addAll(value)
add(0x80U) add(0x80U)
while (size % 64 != 56) { while (size % 64 != 56) {
add(0x00U) add(0x00U)
} }
addAll(ml.toUByteArray()) addAll(l.toUByteArray())
} }
// process
val chunks = paddedValue val chunks = paddedValue
.chunked(64) { it.toUByteArray() } .chunked(64) { it.toUByteArray() }
for (chunk in chunks) { for (chunk in chunks) {
@@ -54,54 +56,39 @@ object `SHA-256` : HashFunction() {
val s1 = get(i - 2).rotateRight(17) xor get(i - 2).rotateRight(19) xor (get(i - 2) shr 10) val s1 = get(i - 2).rotateRight(17) xor get(i - 2).rotateRight(19) xor (get(i - 2) shr 10)
add(get(i - 16) + s0 + get(i - 7) + s1) add(get(i - 16) + s0 + get(i - 7) + s1)
} }
}.toUIntArray()
process(h, w)
} }
var a = h0 return h.toUByteArray()
var b = h1 }
var c = h2
var d = h3 private fun process(
var e = h4 h: UIntArray,
var f = h5 w: UIntArray,
var g = h6 ) {
var h = h7 val v = h.copyOf()
for (i in 0..<64) { for (i in 0..<64) {
val s0 = a.rotateRight(2) xor a.rotateRight(13) xor a.rotateRight(22) val s0 = v[0].rotateRight(2) xor v[0].rotateRight(13) xor v[0].rotateRight(22)
val s1 = e.rotateRight(6) xor e.rotateRight(11) xor e.rotateRight(25) val s1 = v[4].rotateRight(6) xor v[4].rotateRight(11) xor v[4].rotateRight(25)
val ch = (e and f) xor (e.inv() and g) val ch = (v[4] and v[5]) xor (v[4].inv() and v[6])
val temp1 = h + s1 + ch + k[i] + w[i] val temp1 = v[7] + s1 + ch + this.c[i] + w[i]
val maj = (a and b) xor (a and c) xor (b and c) val maj = (v[0] and v[1]) xor (v[0] and v[2]) xor (v[1] and v[2])
val temp2 = s0 + maj val temp2 = s0 + maj
h = g v[7] = v[6]
g = f v[6] = v[5]
f = e v[5] = v[4]
e = d + temp1 v[4] = v[3] + temp1
d = c v[3] = v[2]
c = b v[2] = v[1]
b = a v[1] = v[0]
a = temp1 + temp2 v[0] = temp1 + temp2
} }
h0 += a for (i in 0..7) {
h1 += b h[i] += v[i]
h2 += c }
h3 += d
h4 += e
h5 += f
h6 += g
h7 += h
}
return ubyteArrayOf(
*h0.toUByteArray(),
*h1.toUByteArray(),
*h2.toUByteArray(),
*h3.toUByteArray(),
*h4.toUByteArray(),
*h5.toUByteArray(),
*h6.toUByteArray(),
*h7.toUByteArray(),
)
} }
} }

View File

@@ -11,103 +11,96 @@ object `SHA-384` : HashFunction() {
override val block: Int override val block: Int
get() = 128 get() = 128
private val k = ulongArrayOf( private val initial = ulongArrayOf(
0x428a2f98d728ae22UL, 0x7137449123ef65cdUL, 0xb5c0fbcfec4d3b2fUL, 0xe9b5dba58189dbbcUL, 0x3956c25bf348b538UL, 0xcbbb9d5dc1059ed8UL, 0x629a292a367cd507UL,
0x59f111f1b605d019UL, 0x923f82a4af194f9bUL, 0xab1c5ed5da6d8118UL, 0xd807aa98a3030242UL, 0x12835b0145706fbeUL, 0x9159015a3070dd17UL, 0x152fecd8f70e5939UL,
0x243185be4ee4b28cUL, 0x550c7dc3d5ffb4e2UL, 0x72be5d74f27b896fUL, 0x80deb1fe3b1696b1UL, 0x9bdc06a725c71235UL, 0x67332667ffc00b31UL, 0x8eb44a8768581511UL,
0xc19bf174cf692694UL, 0xe49b69c19ef14ad2UL, 0xefbe4786384f25e3UL, 0x0fc19dc68b8cd5b5UL, 0x240ca1cc77ac9c65UL, 0xdb0c2e0d64f98fa7UL, 0x47b5481dbefa4fa4UL,
0x2de92c6f592b0275UL, 0x4a7484aa6ea6e483UL, 0x5cb0a9dcbd41fbd4UL, 0x76f988da831153b5UL, 0x983e5152ee66dfabUL, )
0xa831c66d2db43210UL, 0xb00327c898fb213fUL, 0xbf597fc7beef0ee4UL, 0xc6e00bf33da88fc2UL, 0xd5a79147930aa725UL,
0x06ca6351e003826fUL, 0x142929670a0e6e70UL, 0x27b70a8546d22ffcUL, 0x2e1b21385c26c926UL, 0x4d2c6dfc5ac42aedUL, private val c = ulongArrayOf(
0x53380d139d95b3dfUL, 0x650a73548baf63deUL, 0x766a0abb3c77b2a8UL, 0x81c2c92e47edaee6UL, 0x92722c851482353bUL, 0x428a2f98d728ae22UL, 0x7137449123ef65cdUL, 0xb5c0fbcfec4d3b2fUL, 0xe9b5dba58189dbbcUL,
0xa2bfe8a14cf10364UL, 0xa81a664bbc423001UL, 0xc24b8b70d0f89791UL, 0xc76c51a30654be30UL, 0xd192e819d6ef5218UL, 0x3956c25bf348b538UL, 0x59f111f1b605d019UL, 0x923f82a4af194f9bUL, 0xab1c5ed5da6d8118UL,
0xd69906245565a910UL, 0xf40e35855771202aUL, 0x106aa07032bbd1b8UL, 0x19a4c116b8d2d0c8UL, 0x1e376c085141ab53UL, 0xd807aa98a3030242UL, 0x12835b0145706fbeUL, 0x243185be4ee4b28cUL, 0x550c7dc3d5ffb4e2UL,
0x2748774cdf8eeb99UL, 0x34b0bcb5e19b48a8UL, 0x391c0cb3c5c95a63UL, 0x4ed8aa4ae3418acbUL, 0x5b9cca4f7763e373UL, 0x72be5d74f27b896fUL, 0x80deb1fe3b1696b1UL, 0x9bdc06a725c71235UL, 0xc19bf174cf692694UL,
0x682e6ff3d6b2b8a3UL, 0x748f82ee5defb2fcUL, 0x78a5636f43172f60UL, 0x84c87814a1f0ab72UL, 0x8cc702081a6439ecUL, 0xe49b69c19ef14ad2UL, 0xefbe4786384f25e3UL, 0x0fc19dc68b8cd5b5UL, 0x240ca1cc77ac9c65UL,
0x90befffa23631e28UL, 0xa4506cebde82bde9UL, 0xbef9a3f7b2c67915UL, 0xc67178f2e372532bUL, 0xca273eceea26619cUL, 0x2de92c6f592b0275UL, 0x4a7484aa6ea6e483UL, 0x5cb0a9dcbd41fbd4UL, 0x76f988da831153b5UL,
0xd186b8c721c0c207UL, 0xeada7dd6cde0eb1eUL, 0xf57d4f7fee6ed178UL, 0x06f067aa72176fbaUL, 0x0a637dc5a2c898a6UL, 0x983e5152ee66dfabUL, 0xa831c66d2db43210UL, 0xb00327c898fb213fUL, 0xbf597fc7beef0ee4UL,
0x113f9804bef90daeUL, 0x1b710b35131c471bUL, 0x28db77f523047d84UL, 0x32caab7b40c72493UL, 0x3c9ebe0a15c9bebcUL, 0xc6e00bf33da88fc2UL, 0xd5a79147930aa725UL, 0x06ca6351e003826fUL, 0x142929670a0e6e70UL,
0x431d67c49c100d4cUL, 0x4cc5d4becb3e42b6UL, 0x597f299cfc657e2aUL, 0x5fcb6fab3ad6faecUL, 0x6c44198c4a475817UL, 0x27b70a8546d22ffcUL, 0x2e1b21385c26c926UL, 0x4d2c6dfc5ac42aedUL, 0x53380d139d95b3dfUL,
0x650a73548baf63deUL, 0x766a0abb3c77b2a8UL, 0x81c2c92e47edaee6UL, 0x92722c851482353bUL,
0xa2bfe8a14cf10364UL, 0xa81a664bbc423001UL, 0xc24b8b70d0f89791UL, 0xc76c51a30654be30UL,
0xd192e819d6ef5218UL, 0xd69906245565a910UL, 0xf40e35855771202aUL, 0x106aa07032bbd1b8UL,
0x19a4c116b8d2d0c8UL, 0x1e376c085141ab53UL, 0x2748774cdf8eeb99UL, 0x34b0bcb5e19b48a8UL,
0x391c0cb3c5c95a63UL, 0x4ed8aa4ae3418acbUL, 0x5b9cca4f7763e373UL, 0x682e6ff3d6b2b8a3UL,
0x748f82ee5defb2fcUL, 0x78a5636f43172f60UL, 0x84c87814a1f0ab72UL, 0x8cc702081a6439ecUL,
0x90befffa23631e28UL, 0xa4506cebde82bde9UL, 0xbef9a3f7b2c67915UL, 0xc67178f2e372532bUL,
0xca273eceea26619cUL, 0xd186b8c721c0c207UL, 0xeada7dd6cde0eb1eUL, 0xf57d4f7fee6ed178UL,
0x06f067aa72176fbaUL, 0x0a637dc5a2c898a6UL, 0x113f9804bef90daeUL, 0x1b710b35131c471bUL,
0x28db77f523047d84UL, 0x32caab7b40c72493UL, 0x3c9ebe0a15c9bebcUL, 0x431d67c49c100d4cUL,
0x4cc5d4becb3e42b6UL, 0x597f299cfc657e2aUL, 0x5fcb6fab3ad6faecUL, 0x6c44198c4a475817UL,
) )
override fun hash( override fun hash(
value: UByteArray, value: UByteArray,
): UByteArray { ): UByteArray {
var h0 = 0xcbbb9d5dc1059ed8UL val h = initial.copyOf()
var h1 = 0x629a292a367cd507UL val l = value.size.toULong() * 8UL
var h2 = 0x9159015a3070dd17UL
var h3 = 0x152fecd8f70e5939UL
var h4 = 0x67332667ffc00b31UL
var h5 = 0x8eb44a8768581511UL
var h6 = 0xdb0c2e0d64f98fa7UL
var h7 = 0x47b5481dbefa4fa4UL
val ml = value.size.toULong() * 8UL
// padding
val paddedValue = buildList { val paddedValue = buildList {
addAll(value) addAll(value)
add(0x80U) add(0x80U)
while (size % 128 != 120) { while (size % 128 != 120) {
add(0x00U) add(0x00U)
} }
addAll(ml.toUByteArray()) addAll(l.toUByteArray())
} }
val chunks = paddedValue // process
val blocks = paddedValue
.chunked(128) { it.toUByteArray() } .chunked(128) { it.toUByteArray() }
for (chunk in chunks) { for (block in blocks) {
val w = buildList { val w = buildList {
addAll(chunk.toULongArray()) addAll(block.toULongArray())
for (i in 16..<80) { for (i in 16..<80) {
val s0 = get(i - 15).rotateRight(1) xor get(i - 15).rotateRight(8) xor (get(i - 15) shr 7) val s0 = get(i - 15).rotateRight(1) xor get(i - 15).rotateRight(8) xor (get(i - 15) shr 7)
val s1 = get(i - 2).rotateRight(19) xor get(i - 2).rotateRight(61) xor (get(i - 2) shr 6) val s1 = get(i - 2).rotateRight(19) xor get(i - 2).rotateRight(61) xor (get(i - 2) shr 6)
add(get(i - 16) + s0 + get(i - 7) + s1) add(get(i - 16) + s0 + get(i - 7) + s1)
} }
}.toULongArray()
process(h, w)
} }
var a = h0 return h.sliceArray(0..5).toUByteArray()
var b = h1 }
var c = h2
var d = h3 private fun process(
var e = h4 h: ULongArray,
var f = h5 w: ULongArray,
var g = h6 ) {
var h = h7 val v = h.copyOf()
for (i in 0..<80) { for (i in 0..<80) {
val s0 = a.rotateRight(28) xor a.rotateRight(34) xor a.rotateRight(39) val s0 = v[0].rotateRight(28) xor v[0].rotateRight(34) xor v[0].rotateRight(39)
val s1 = e.rotateRight(14) xor e.rotateRight(18) xor e.rotateRight(41) val s1 = v[4].rotateRight(14) xor v[4].rotateRight(18) xor v[4].rotateRight(41)
val ch = (e and f) xor (e.inv() and g) val ch = (v[4] and v[5]) xor (v[4].inv() and v[6])
val temp1 = h + s1 + ch + k[i] + w[i] val temp1 = v[7] + s1 + ch + this.c[i] + w[i]
val maj = (a and b) xor (a and c) xor (b and c) val maj = (v[0] and v[1]) xor (v[0] and v[2]) xor (v[1] and v[2])
val temp2 = s0 + maj val temp2 = s0 + maj
h = g v[7] = v[6]
g = f v[6] = v[5]
f = e v[5] = v[4]
e = d + temp1 v[4] = v[3] + temp1
d = c v[3] = v[2]
c = b v[2] = v[1]
b = a v[1] = v[0]
a = temp1 + temp2 v[0] = temp1 + temp2
} }
h0 += a for (i in 0..7) {
h1 += b h[i] += v[i]
h2 += c }
h3 += d
h4 += e
h5 += f
h6 += g
h7 += h
}
return ubyteArrayOf(
*h0.toUByteArray(),
*h1.toUByteArray(),
*h2.toUByteArray(),
*h3.toUByteArray(),
*h4.toUByteArray(),
*h5.toUByteArray(),
)
} }
} }

View File

@@ -11,105 +11,96 @@ object `SHA-512` : HashFunction() {
override val block: Int override val block: Int
get() = 128 get() = 128
private val k = ulongArrayOf( private val initial = ulongArrayOf(
0x428a2f98d728ae22UL, 0x7137449123ef65cdUL, 0xb5c0fbcfec4d3b2fUL, 0xe9b5dba58189dbbcUL, 0x3956c25bf348b538UL, 0x6a09e667f3bcc908UL, 0xbb67ae8584caa73bUL,
0x59f111f1b605d019UL, 0x923f82a4af194f9bUL, 0xab1c5ed5da6d8118UL, 0xd807aa98a3030242UL, 0x12835b0145706fbeUL, 0x3c6ef372fe94f82bUL, 0xa54ff53a5f1d36f1UL,
0x243185be4ee4b28cUL, 0x550c7dc3d5ffb4e2UL, 0x72be5d74f27b896fUL, 0x80deb1fe3b1696b1UL, 0x9bdc06a725c71235UL, 0x510e527fade682d1UL, 0x9b05688c2b3e6c1fUL,
0xc19bf174cf692694UL, 0xe49b69c19ef14ad2UL, 0xefbe4786384f25e3UL, 0x0fc19dc68b8cd5b5UL, 0x240ca1cc77ac9c65UL, 0x1f83d9abfb41bd6bUL, 0x5be0cd19137e2179UL,
0x2de92c6f592b0275UL, 0x4a7484aa6ea6e483UL, 0x5cb0a9dcbd41fbd4UL, 0x76f988da831153b5UL, 0x983e5152ee66dfabUL, )
0xa831c66d2db43210UL, 0xb00327c898fb213fUL, 0xbf597fc7beef0ee4UL, 0xc6e00bf33da88fc2UL, 0xd5a79147930aa725UL,
0x06ca6351e003826fUL, 0x142929670a0e6e70UL, 0x27b70a8546d22ffcUL, 0x2e1b21385c26c926UL, 0x4d2c6dfc5ac42aedUL, private val c = ulongArrayOf(
0x53380d139d95b3dfUL, 0x650a73548baf63deUL, 0x766a0abb3c77b2a8UL, 0x81c2c92e47edaee6UL, 0x92722c851482353bUL, 0x428a2f98d728ae22UL, 0x7137449123ef65cdUL, 0xb5c0fbcfec4d3b2fUL, 0xe9b5dba58189dbbcUL,
0xa2bfe8a14cf10364UL, 0xa81a664bbc423001UL, 0xc24b8b70d0f89791UL, 0xc76c51a30654be30UL, 0xd192e819d6ef5218UL, 0x3956c25bf348b538UL, 0x59f111f1b605d019UL, 0x923f82a4af194f9bUL, 0xab1c5ed5da6d8118UL,
0xd69906245565a910UL, 0xf40e35855771202aUL, 0x106aa07032bbd1b8UL, 0x19a4c116b8d2d0c8UL, 0x1e376c085141ab53UL, 0xd807aa98a3030242UL, 0x12835b0145706fbeUL, 0x243185be4ee4b28cUL, 0x550c7dc3d5ffb4e2UL,
0x2748774cdf8eeb99UL, 0x34b0bcb5e19b48a8UL, 0x391c0cb3c5c95a63UL, 0x4ed8aa4ae3418acbUL, 0x5b9cca4f7763e373UL, 0x72be5d74f27b896fUL, 0x80deb1fe3b1696b1UL, 0x9bdc06a725c71235UL, 0xc19bf174cf692694UL,
0x682e6ff3d6b2b8a3UL, 0x748f82ee5defb2fcUL, 0x78a5636f43172f60UL, 0x84c87814a1f0ab72UL, 0x8cc702081a6439ecUL, 0xe49b69c19ef14ad2UL, 0xefbe4786384f25e3UL, 0x0fc19dc68b8cd5b5UL, 0x240ca1cc77ac9c65UL,
0x90befffa23631e28UL, 0xa4506cebde82bde9UL, 0xbef9a3f7b2c67915UL, 0xc67178f2e372532bUL, 0xca273eceea26619cUL, 0x2de92c6f592b0275UL, 0x4a7484aa6ea6e483UL, 0x5cb0a9dcbd41fbd4UL, 0x76f988da831153b5UL,
0xd186b8c721c0c207UL, 0xeada7dd6cde0eb1eUL, 0xf57d4f7fee6ed178UL, 0x06f067aa72176fbaUL, 0x0a637dc5a2c898a6UL, 0x983e5152ee66dfabUL, 0xa831c66d2db43210UL, 0xb00327c898fb213fUL, 0xbf597fc7beef0ee4UL,
0x113f9804bef90daeUL, 0x1b710b35131c471bUL, 0x28db77f523047d84UL, 0x32caab7b40c72493UL, 0x3c9ebe0a15c9bebcUL, 0xc6e00bf33da88fc2UL, 0xd5a79147930aa725UL, 0x06ca6351e003826fUL, 0x142929670a0e6e70UL,
0x431d67c49c100d4cUL, 0x4cc5d4becb3e42b6UL, 0x597f299cfc657e2aUL, 0x5fcb6fab3ad6faecUL, 0x6c44198c4a475817UL, 0x27b70a8546d22ffcUL, 0x2e1b21385c26c926UL, 0x4d2c6dfc5ac42aedUL, 0x53380d139d95b3dfUL,
0x650a73548baf63deUL, 0x766a0abb3c77b2a8UL, 0x81c2c92e47edaee6UL, 0x92722c851482353bUL,
0xa2bfe8a14cf10364UL, 0xa81a664bbc423001UL, 0xc24b8b70d0f89791UL, 0xc76c51a30654be30UL,
0xd192e819d6ef5218UL, 0xd69906245565a910UL, 0xf40e35855771202aUL, 0x106aa07032bbd1b8UL,
0x19a4c116b8d2d0c8UL, 0x1e376c085141ab53UL, 0x2748774cdf8eeb99UL, 0x34b0bcb5e19b48a8UL,
0x391c0cb3c5c95a63UL, 0x4ed8aa4ae3418acbUL, 0x5b9cca4f7763e373UL, 0x682e6ff3d6b2b8a3UL,
0x748f82ee5defb2fcUL, 0x78a5636f43172f60UL, 0x84c87814a1f0ab72UL, 0x8cc702081a6439ecUL,
0x90befffa23631e28UL, 0xa4506cebde82bde9UL, 0xbef9a3f7b2c67915UL, 0xc67178f2e372532bUL,
0xca273eceea26619cUL, 0xd186b8c721c0c207UL, 0xeada7dd6cde0eb1eUL, 0xf57d4f7fee6ed178UL,
0x06f067aa72176fbaUL, 0x0a637dc5a2c898a6UL, 0x113f9804bef90daeUL, 0x1b710b35131c471bUL,
0x28db77f523047d84UL, 0x32caab7b40c72493UL, 0x3c9ebe0a15c9bebcUL, 0x431d67c49c100d4cUL,
0x4cc5d4becb3e42b6UL, 0x597f299cfc657e2aUL, 0x5fcb6fab3ad6faecUL, 0x6c44198c4a475817UL,
) )
override fun hash( override fun hash(
value: UByteArray, value: UByteArray,
): UByteArray { ): UByteArray {
var h0 = 0x6a09e667f3bcc908UL val h = initial.copyOf()
var h1 = 0xbb67ae8584caa73bUL val l = value.size.toULong() * 8UL
var h2 = 0x3c6ef372fe94f82bUL
var h3 = 0xa54ff53a5f1d36f1UL
var h4 = 0x510e527fade682d1UL
var h5 = 0x9b05688c2b3e6c1fUL
var h6 = 0x1f83d9abfb41bd6bUL
var h7 = 0x5be0cd19137e2179UL
val ml = value.size.toULong() * 8UL
// padding
val paddedValue = buildList { val paddedValue = buildList {
addAll(value) addAll(value)
add(0x80U) add(0x80U)
while (size % 128 != 120) { while (size % 128 != 120) {
add(0x00U) add(0x00U)
} }
addAll(ml.toUByteArray()) addAll(l.toUByteArray())
} }
val chunks = paddedValue // process
val blocks = paddedValue
.chunked(128) { it.toUByteArray() } .chunked(128) { it.toUByteArray() }
for (chunk in chunks) { for (block in blocks) {
val w = buildList { val w = buildList {
addAll(chunk.toULongArray()) addAll(block.toULongArray())
for (i in 16..<80) { for (i in 16..<80) {
val s0 = get(i - 15).rotateRight(1) xor get(i - 15).rotateRight(8) xor (get(i - 15) shr 7) val s0 = get(i - 15).rotateRight(1) xor get(i - 15).rotateRight(8) xor (get(i - 15) shr 7)
val s1 = get(i - 2).rotateRight(19) xor get(i - 2).rotateRight(61) xor (get(i - 2) shr 6) val s1 = get(i - 2).rotateRight(19) xor get(i - 2).rotateRight(61) xor (get(i - 2) shr 6)
add(get(i - 16) + s0 + get(i - 7) + s1) add(get(i - 16) + s0 + get(i - 7) + s1)
} }
}.toULongArray()
process(h, w)
} }
var a = h0 return h.toUByteArray()
var b = h1 }
var c = h2
var d = h3 private fun process(
var e = h4 h: ULongArray,
var f = h5 w: ULongArray,
var g = h6 ) {
var h = h7 val v = h.copyOf()
for (i in 0..<80) { for (i in 0..<80) {
val s0 = a.rotateRight(28) xor a.rotateRight(34) xor a.rotateRight(39) val s0 = v[0].rotateRight(28) xor v[0].rotateRight(34) xor v[0].rotateRight(39)
val s1 = e.rotateRight(14) xor e.rotateRight(18) xor e.rotateRight(41) val s1 = v[4].rotateRight(14) xor v[4].rotateRight(18) xor v[4].rotateRight(41)
val ch = (e and f) xor (e.inv() and g) val ch = (v[4] and v[5]) xor (v[4].inv() and v[6])
val temp1 = h + s1 + ch + k[i] + w[i] val temp1 = v[7] + s1 + ch + this.c[i] + w[i]
val maj = (a and b) xor (a and c) xor (b and c) val maj = (v[0] and v[1]) xor (v[0] and v[2]) xor (v[1] and v[2])
val temp2 = s0 + maj val temp2 = s0 + maj
h = g v[7] = v[6]
g = f v[6] = v[5]
f = e v[5] = v[4]
e = d + temp1 v[4] = v[3] + temp1
d = c v[3] = v[2]
c = b v[2] = v[1]
b = a v[1] = v[0]
a = temp1 + temp2 v[0] = temp1 + temp2
} }
h0 += a for (i in 0..7) {
h1 += b h[i] += v[i]
h2 += c }
h3 += d
h4 += e
h5 += f
h6 += g
h7 += h
}
return ubyteArrayOf(
*h0.toUByteArray(),
*h1.toUByteArray(),
*h2.toUByteArray(),
*h3.toUByteArray(),
*h4.toUByteArray(),
*h5.toUByteArray(),
*h6.toUByteArray(),
*h7.toUByteArray(),
)
} }
} }

View File

@@ -0,0 +1,67 @@
package com.infendro.hash.blake
import kotlin.test.Test
import kotlin.test.assertContentEquals
import kotlin.test.assertEquals
class `Blake-224 Test` {
val function = `Blake-224`
@Test
fun `bytes and block`() {
assertEquals(28, function.bytes)
assertEquals(224, function.bits)
assertEquals(64, function.block)
}
@Test
fun `empty bytearray`() {
val expected = ubyteArrayOf(
0x7dU, 0xc5U, 0x31U, 0x3bU,
0x1cU, 0x04U, 0x51U, 0x2aU,
0x17U, 0x4bU, 0xd6U, 0x50U,
0x3bU, 0x89U, 0x60U, 0x7aU,
0xecU, 0xbeU, 0xe0U, 0x90U,
0x3dU, 0x40U, 0xa8U, 0xa5U,
0x69U, 0xc9U, 0x4eU, 0xedU,
)
val actual = function.hash(
UByteArray(0)
)
assertContentEquals(expected, actual)
}
@Test
fun `one block`() {
val expected = ubyteArrayOf(
0x45U, 0x04U, 0xcbU, 0x03U,
0x14U, 0xfbU, 0x2aU, 0x4fU,
0x7aU, 0x69U, 0x2eU, 0x69U,
0x6eU, 0x48U, 0x79U, 0x12U,
0xfeU, 0x3fU, 0x24U, 0x68U,
0xfeU, 0x31U, 0x2cU, 0x73U,
0xa5U, 0x27U, 0x8eU, 0xc5U,
)
val actual = function.hash(
UByteArray(1)
)
assertContentEquals(expected, actual)
}
@Test
fun `two blocks`() {
val expected = ubyteArrayOf(
0xf5U, 0xaaU, 0x00U, 0xddU,
0x1cU, 0xb8U, 0x47U, 0xe3U,
0x14U, 0x03U, 0x72U, 0xafU,
0x7bU, 0x5cU, 0x46U, 0xb4U,
0x88U, 0x8dU, 0x82U, 0xc8U,
0xc0U, 0xa9U, 0x17U, 0x91U,
0x3cU, 0xfbU, 0x5dU, 0x04U,
)
val actual = function.hash(
UByteArray(72)
)
assertContentEquals(expected, actual)
}
}

View File

@@ -0,0 +1,70 @@
package com.infendro.hash.blake
import kotlin.test.Test
import kotlin.test.assertContentEquals
import kotlin.test.assertEquals
class `Blake-256 Test` {
val function = `Blake-256`
@Test
fun `bytes and block`() {
assertEquals(32, function.bytes)
assertEquals(256, function.bits)
assertEquals(64, function.block)
}
@Test
fun `empty bytearray`() {
val expected = ubyteArrayOf(
0x71U, 0x6fU, 0x6eU, 0x86U,
0x3fU, 0x74U, 0x4bU, 0x9aU,
0xc2U, 0x2cU, 0x97U, 0xecU,
0x7bU, 0x76U, 0xeaU, 0x5fU,
0x59U, 0x08U, 0xbcU, 0x5bU,
0x2fU, 0x67U, 0xc6U, 0x15U,
0x10U, 0xbfU, 0xc4U, 0x75U,
0x13U, 0x84U, 0xeaU, 0x7aU,
)
val actual = function.hash(
UByteArray(0)
)
assertContentEquals(expected, actual)
}
@Test
fun `one block`() {
val expected = ubyteArrayOf(
0x0cU, 0xe8U, 0xd4U, 0xefU,
0x4dU, 0xd7U, 0xcdU, 0x8dU,
0x62U, 0xdfU, 0xdeU, 0xd9U,
0xd4U, 0xedU, 0xb0U, 0xa7U,
0x74U, 0xaeU, 0x6aU, 0x41U,
0x92U, 0x9aU, 0x74U, 0xdaU,
0x23U, 0x10U, 0x9eU, 0x8fU,
0x11U, 0x13U, 0x9cU, 0x87U,
)
val actual = function.hash(
UByteArray(1)
)
assertContentEquals(expected, actual)
}
@Test
fun `two blocks`() {
val expected = ubyteArrayOf(
0xd4U, 0x19U, 0xbaU, 0xd3U,
0x2dU, 0x50U, 0x4fU, 0xb7U,
0xd4U, 0x4dU, 0x46U, 0x0cU,
0x42U, 0xc5U, 0x59U, 0x3fU,
0xe5U, 0x44U, 0xfaU, 0x4cU,
0x13U, 0x5dU, 0xecU, 0x31U,
0xe2U, 0x1bU, 0xd9U, 0xabU,
0xdcU, 0xc2U, 0x2dU, 0x41U,
)
val actual = function.hash(
UByteArray(72)
)
assertContentEquals(expected, actual)
}
}

View File

@@ -0,0 +1,82 @@
package com.infendro.hash.blake
import kotlin.test.Test
import kotlin.test.assertContentEquals
import kotlin.test.assertEquals
class `Blake-384 Test` {
val function = `Blake-384`
@Test
fun `bytes and block`() {
assertEquals(48, function.bytes)
assertEquals(384, function.bits)
assertEquals(128, function.block)
}
@Test
fun `empty bytearray`() {
val expected = ubyteArrayOf(
0xc6U, 0xcbU, 0xd8U, 0x9cU,
0x92U, 0x6aU, 0xb5U, 0x25U,
0xc2U, 0x42U, 0xe6U, 0x62U,
0x1fU, 0x2fU, 0x5fU, 0xa7U,
0x3aU, 0xa4U, 0xafU, 0xe3U,
0xd9U, 0xe2U, 0x4aU, 0xedU,
0x72U, 0x7fU, 0xaaU, 0xadU,
0xd6U, 0xafU, 0x38U, 0xb6U,
0x20U, 0xbdU, 0xb6U, 0x23U,
0xddU, 0x2bU, 0x47U, 0x88U,
0xb1U, 0xc8U, 0x08U, 0x69U,
0x84U, 0xafU, 0x87U, 0x06U,
)
val actual = function.hash(
UByteArray(0)
)
assertContentEquals(expected, actual)
}
@Test
fun `one block`() {
val expected = ubyteArrayOf(
0x10U, 0x28U, 0x1fU, 0x67U,
0xe1U, 0x35U, 0xe9U, 0x0aU,
0xe8U, 0xe8U, 0x82U, 0x25U,
0x1aU, 0x35U, 0x55U, 0x10U,
0xa7U, 0x19U, 0x36U, 0x7aU,
0xd7U, 0x02U, 0x27U, 0xb1U,
0x37U, 0x34U, 0x3eU, 0x1bU,
0xc1U, 0x22U, 0x01U, 0x5cU,
0x29U, 0x39U, 0x1eU, 0x85U,
0x45U, 0xb5U, 0x27U, 0x2dU,
0x13U, 0xa7U, 0xc2U, 0x87U,
0x9dU, 0xa3U, 0xd8U, 0x07U
)
val actual = function.hash(
UByteArray(1)
)
assertContentEquals(expected, actual)
}
@Test
fun `two blocks`() {
val expected = ubyteArrayOf(
0x0bU, 0x98U, 0x45U, 0xddU,
0x42U, 0x95U, 0x66U, 0xcdU,
0xabU, 0x77U, 0x2bU, 0xa1U,
0x95U, 0xd2U, 0x71U, 0xefU,
0xfeU, 0x2dU, 0x02U, 0x11U,
0xf1U, 0x69U, 0x91U, 0xd7U,
0x66U, 0xbaU, 0x74U, 0x94U,
0x47U, 0xc5U, 0xcdU, 0xe5U,
0x69U, 0x78U, 0x0bU, 0x2dU,
0xaaU, 0x66U, 0xc4U, 0xb2U,
0x24U, 0xa2U, 0xecU, 0x2eU,
0x5dU, 0x09U, 0x17U, 0x4cU
)
val actual = function.hash(
UByteArray(144)
)
assertContentEquals(expected, actual)
}
}

View File

@@ -0,0 +1,94 @@
package com.infendro.hash.blake
import kotlin.test.Test
import kotlin.test.assertContentEquals
import kotlin.test.assertEquals
class `Blake-512 Test` {
val function = `Blake-512`
@Test
fun `bytes and block`() {
assertEquals(64, function.bytes)
assertEquals(512, function.bits)
assertEquals(128, function.block)
}
@Test
fun `empty bytearray`() {
val expected = ubyteArrayOf(
0xa8U, 0xcfU, 0xbbU, 0xd7U,
0x37U, 0x26U, 0x06U, 0x2dU,
0xf0U, 0xc6U, 0x86U, 0x4dU,
0xdaU, 0x65U, 0xdeU, 0xfeU,
0x58U, 0xefU, 0x0cU, 0xc5U,
0x2aU, 0x56U, 0x25U, 0x09U,
0x0fU, 0xa1U, 0x76U, 0x01U,
0xe1U, 0xeeU, 0xcdU, 0x1bU,
0x62U, 0x8eU, 0x94U, 0xf3U,
0x96U, 0xaeU, 0x40U, 0x2aU,
0x00U, 0xacU, 0xc9U, 0xeaU,
0xb7U, 0x7bU, 0x4dU, 0x4cU,
0x2eU, 0x85U, 0x2aU, 0xaaU,
0xa2U, 0x5aU, 0x63U, 0x6dU,
0x80U, 0xafU, 0x3fU, 0xc7U,
0x91U, 0x3eU, 0xf5U, 0xb8U,
)
val actual = function.hash(
UByteArray(0)
)
assertContentEquals(expected, actual)
}
@Test
fun `one block`() {
val expected = ubyteArrayOf(
0x97U, 0x96U, 0x15U, 0x87U,
0xf6U, 0xd9U, 0x70U, 0xfaU,
0xbaU, 0x6dU, 0x24U, 0x78U,
0x04U, 0x5dU, 0xe6U, 0xd1U,
0xfaU, 0xbdU, 0x09U, 0xb6U,
0x1aU, 0xe5U, 0x09U, 0x32U,
0x05U, 0x4dU, 0x52U, 0xbcU,
0x29U, 0xd3U, 0x1bU, 0xe4U,
0xffU, 0x91U, 0x02U, 0xb9U,
0xf6U, 0x9eU, 0x2bU, 0xbdU,
0xb8U, 0x3bU, 0xe1U, 0x3dU,
0x4bU, 0x9cU, 0x06U, 0x09U,
0x1eU, 0x5fU, 0xa0U, 0xb4U,
0x8bU, 0xd0U, 0x81U, 0xb6U,
0x34U, 0x05U, 0x8bU, 0xe0U,
0xecU, 0x49U, 0xbeU, 0xb3U,
)
val actual = function.hash(
UByteArray(1)
)
assertContentEquals(expected, actual)
}
@Test
fun `two blocks`() {
val expected = ubyteArrayOf(
0x31U, 0x37U, 0x17U, 0xd6U,
0x08U, 0xe9U, 0xcfU, 0x75U,
0x8dU, 0xcbU, 0x1eU, 0xb0U,
0xf0U, 0xc3U, 0xcfU, 0x9fU,
0xc1U, 0x50U, 0xb2U, 0xd5U,
0x00U, 0xfbU, 0x33U, 0xf5U,
0x1cU, 0x52U, 0xafU, 0xc9U,
0x9dU, 0x35U, 0x8aU, 0x2fU,
0x13U, 0x74U, 0xb8U, 0xa3U,
0x8bU, 0xbaU, 0x79U, 0x74U,
0xe7U, 0xf6U, 0xefU, 0x79U,
0xcaU, 0xb1U, 0x6fU, 0x22U,
0xceU, 0x1eU, 0x64U, 0x9dU,
0x6eU, 0x01U, 0xadU, 0x95U,
0x89U, 0xc2U, 0x13U, 0x04U,
0x5dU, 0x54U, 0x5dU, 0xdeU,
)
val actual = function.hash(
UByteArray(144)
)
assertContentEquals(expected, actual)
}
}