Compare commits

..

4 Commits

Author SHA1 Message Date
17b765b13c refactor SHA1 and SHA2 2025-12-04 19:20:35 +01:00
b41debf948 refactor MD5 2025-12-04 19:13:43 +01:00
6dc3cf3b87 refactor Keccak 2025-12-04 19:13:39 +01:00
16390b0308 refactor Blake and Blake2 2025-12-04 19:05:54 +01:00
13 changed files with 296 additions and 296 deletions

View File

@@ -43,12 +43,25 @@ object `Blake-224` : HashFunction() {
) )
override fun hash(value: UByteArray): UByteArray { override fun hash(value: UByteArray): UByteArray {
val l = value.size.toULong() * 8UL
val h = initial.copyOf() val h = initial.copyOf()
var t = 0U var t = 0U
val l = value.size.toULong() * 8UL
// padding val blocks = pad(value)
val paddedValue = buildList { .chunked(64) { it.toUByteArray() }
for (block in blocks) {
t += minOf(l - t, 512UL).toUInt()
compress(h, block, t)
}
return h.sliceArray(0..6).toUByteArray()
}
private fun pad(
value: UByteArray,
): UByteArray {
val l = value.size.toULong() * 8UL
return buildList {
addAll(value) addAll(value)
add(0x80U) add(0x80U)
while (size % 64 != 56) { while (size % 64 != 56) {
@@ -56,56 +69,39 @@ object `Blake-224` : HashFunction() {
} }
addAll(l.toUByteArray()) addAll(l.toUByteArray())
}.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( private fun compress(
h: UIntArray, h: UIntArray,
m: UIntArray, block: UByteArray,
t: UInt, t: UInt,
) { ) {
// initialization val m = block.toUIntArray()
val v = UIntArray(16) val v = UIntArray(16)
for (i in 0..<8) v[i] = h[i] for (i in 0..<8) v[i] = h[i]
for (i in 0..<4) v[i + 8] = c[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 + 12] = c[i + 4] xor t
for (i in 0..<2) v[i + 14] = c[i + 6] for (i in 0..<2) v[i + 14] = c[i + 6]
// rounds repeat(14) { r ->
for (r in 0..<14) {
val s = sigma[r % 10] 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, 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, 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, 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]]) 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, 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, 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, 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]]) 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) { for (i in 0..7) {
h[i] = h[i] xor v[i] xor v[i + 8] h[i] = h[i] xor v[i] xor v[i + 8]
} }
} }
// round function
private fun g( private fun g(
v: UIntArray, v: UIntArray,
a: Int, a: Int,

View File

@@ -43,12 +43,25 @@ object `Blake-256` : HashFunction() {
) )
override fun hash(value: UByteArray): UByteArray { override fun hash(value: UByteArray): UByteArray {
val l = value.size.toULong() * 8UL
val h = initial.copyOf() val h = initial.copyOf()
var t = 0U var t = 0U
val l = value.size.toULong() * 8UL
// padding val blocks = pad(value)
val paddedValue = buildList { .chunked(64) { it.toUByteArray() }
for (block in blocks) {
t += minOf(l - t, 512UL).toUInt()
compress(h, block, t)
}
return h.toUByteArray()
}
private fun pad(
value: UByteArray,
): UByteArray {
val l = value.size.toULong() * 8UL
return buildList {
addAll(value) addAll(value)
add(0x80U) add(0x80U)
while (size % 64 != 55) { while (size % 64 != 55) {
@@ -57,56 +70,39 @@ object `Blake-256` : HashFunction() {
add(0x01U) add(0x01U)
addAll(l.toUByteArray()) addAll(l.toUByteArray())
}.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( private fun compress(
h: UIntArray, h: UIntArray,
m: UIntArray, block: UByteArray,
t: UInt, t: UInt,
) { ) {
// initialization val m = block.toUIntArray()
val v = UIntArray(16) val v = UIntArray(16)
for (i in 0..<8) v[i] = h[i] for (i in 0..<8) v[i] = h[i]
for (i in 0..<4) v[i + 8] = c[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 + 12] = c[i + 4] xor t
for (i in 0..<2) v[i + 14] = c[i + 6] for (i in 0..<2) v[i + 14] = c[i + 6]
// rounds repeat(14) { r ->
for (r in 0..<14) {
val s = sigma[r % 10] 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, 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, 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, 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]]) 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, 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, 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, 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]]) 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) { for (i in 0..7) {
h[i] = h[i] xor v[i] xor v[i + 8] h[i] = h[i] xor v[i] xor v[i + 8]
} }
} }
// round function
private fun g( private fun g(
v: UIntArray, v: UIntArray,
a: Int, a: Int,

View File

@@ -43,12 +43,25 @@ object `Blake-384` : HashFunction() {
) )
override fun hash(value: UByteArray): UByteArray { override fun hash(value: UByteArray): UByteArray {
val l = value.size.toULong() * 8UL
val h = initial.copyOf() val h = initial.copyOf()
var t = 0UL var t = 0UL
val l = value.size.toULong() * 8UL
// padding val blocks = pad(value)
val paddedValue = buildList { .chunked(128) { it.toUByteArray() }
for (block in blocks) {
t += minOf(l - t, 1024UL)
compress(h, block, t)
}
return h.sliceArray(0..5).toUByteArray()
}
private fun pad(
value: UByteArray,
): UByteArray {
val l = value.size.toULong() * 8UL
return buildList {
addAll(value) addAll(value)
add(0x80U) add(0x80U)
while (size % 128 != 120) { while (size % 128 != 120) {
@@ -56,56 +69,39 @@ object `Blake-384` : HashFunction() {
} }
addAll(l.toUByteArray()) addAll(l.toUByteArray())
}.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( private fun compress(
h: ULongArray, h: ULongArray,
m: ULongArray, block: UByteArray,
t: ULong, t: ULong,
) { ) {
// initialization val m = block.toULongArray()
val v = ULongArray(16) val v = ULongArray(16)
for (i in 0..<8) v[i] = h[i] for (i in 0..<8) v[i] = h[i]
for (i in 0..<4) v[i + 8] = c[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 + 12] = c[i + 4] xor t
for (i in 0..<2) v[i + 14] = c[i + 6] for (i in 0..<2) v[i + 14] = c[i + 6]
// rounds repeat(16) { r ->
for (r in 0..<16) {
val s = sigma[r % 10] 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, 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, 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, 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]]) 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, 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, 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, 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]]) 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) { for (i in 0..7) {
h[i] = h[i] xor v[i] xor v[i + 8] h[i] = h[i] xor v[i] xor v[i + 8]
} }
} }
// round function
private fun g( private fun g(
v: ULongArray, v: ULongArray,
a: Int, a: Int,

View File

@@ -43,12 +43,25 @@ object `Blake-512` : HashFunction() {
) )
override fun hash(value: UByteArray): UByteArray { override fun hash(value: UByteArray): UByteArray {
val l = value.size.toULong() * 8UL
val h = initial.copyOf() val h = initial.copyOf()
var t = 0UL var t = 0UL
val l = value.size.toULong() * 8UL
// padding val blocks = pad(value)
val paddedValue = buildList { .chunked(128) { it.toUByteArray() }
for (block in blocks) {
t += minOf(l - t, 1024UL)
compress(h, block, t)
}
return h.toUByteArray()
}
private fun pad(
value: UByteArray,
): UByteArray {
val l = value.size.toULong() * 8UL
return buildList {
addAll(value) addAll(value)
add(0x80U) add(0x80U)
while (size % 128 != 111) { while (size % 128 != 111) {
@@ -58,56 +71,39 @@ object `Blake-512` : HashFunction() {
repeat(8) { add(0x00U) } repeat(8) { add(0x00U) }
addAll(l.toUByteArray()) addAll(l.toUByteArray())
}.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( private fun compress(
h: ULongArray, h: ULongArray,
m: ULongArray, block: UByteArray,
t: ULong, t: ULong,
) { ) {
// initialization val m = block.toULongArray()
val v = ULongArray(16) val v = ULongArray(16)
for (i in 0..<8) v[i] = h[i] for (i in 0..<8) v[i] = h[i]
for (i in 0..<4) v[i + 8] = c[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 + 12] = c[i + 4] xor t
for (i in 0..<2) v[i + 14] = c[i + 6] for (i in 0..<2) v[i + 14] = c[i + 6]
// rounds repeat(16) { r ->
for (r in 0..<16) {
val s = sigma[r % 10] 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, 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, 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, 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]]) 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, 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, 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, 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]]) 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) { for (i in 0..7) {
h[i] = h[i] xor v[i] xor v[i + 8] h[i] = h[i] xor v[i] xor v[i + 8]
} }
} }
// round function
private fun g( private fun g(
v: ULongArray, v: ULongArray,
a: Int, a: Int,

View File

@@ -36,65 +36,60 @@ class Blake2b(
) )
override fun hash(value: UByteArray): UByteArray { override fun hash(value: UByteArray): UByteArray {
val l = value.size.toULong()
val h = initial.copyOf() val h = initial.copyOf()
h[0] = h[0] xor (0x01010000UL or bytes.toULong()) h[0] = h[0] xor (0x01010000UL or bytes.toULong())
var t = 0UL var t = 0UL
val l = value.size.toULong()
// padding val blocks = pad(value)
val paddedValue = buildList { .chunked(128) { it.toUByteArray() }
for ((i, block) in blocks.withIndex()) {
t += minOf(l - t, 128UL)
compress(h, block, t, i == blocks.lastIndex)
}
return h.toUByteArray(ByteOrder.LITTLE_ENDIAN).sliceArray(0..<bytes)
}
private fun pad(
value: UByteArray,
): UByteArray {
return buildList {
addAll(value) addAll(value)
if (isEmpty()) add(0x00U) if (isEmpty()) add(0x00U)
while (size % 128 != 0) { while (size % 128 != 0) {
add(0x00U) add(0x00U)
} }
}.toUByteArray() }.toUByteArray()
// compress
val blocks = paddedValue
.chunked(128) { it.toUByteArray() }
for ((i, block) in blocks.withIndex()) {
t += minOf(l - t, 128UL)
val m = block.toULongArray()
compress(h, m, t, i == blocks.lastIndex)
}
return h.toUByteArray(ByteOrder.LITTLE_ENDIAN).sliceArray(0..<bytes)
} }
private fun compress( private fun compress(
h: ULongArray, h: ULongArray,
m: ULongArray, block: UByteArray,
t: ULong, t: ULong,
last: Boolean, last: Boolean,
) { ) {
// initialization val m = block.toULongArray()
val v = ULongArray(16) val v = ULongArray(16)
for (i in 0..<8) v[i] = h[i] for (i in 0..<8) v[i] = h[i]
for (i in 0..<8) v[i + 8] = initial[i] for (i in 0..<8) v[i + 8] = initial[i]
v[12] = v[12] xor t v[12] = v[12] xor t
if (last) v[14] = v[14].inv() if (last) v[14] = v[14].inv()
// rounds repeat(12) { r ->
for (r in 0..<12) {
val s = sigma[r % 10] val s = sigma[r % 10]
// column
mix(v, 0, 4, 8, 12, m[s[0]], m[s[1]]) mix(v, 0, 4, 8, 12, m[s[0]], m[s[1]])
mix(v, 1, 5, 9, 13, m[s[2]], m[s[3]]) mix(v, 1, 5, 9, 13, m[s[2]], m[s[3]])
mix(v, 2, 6, 10, 14, m[s[4]], m[s[5]]) mix(v, 2, 6, 10, 14, m[s[4]], m[s[5]])
mix(v, 3, 7, 11, 15, m[s[6]], m[s[7]]) mix(v, 3, 7, 11, 15, m[s[6]], m[s[7]])
// diagonal
mix(v, 0, 5, 10, 15, m[s[8]], m[s[9]]) mix(v, 0, 5, 10, 15, m[s[8]], m[s[9]])
mix(v, 1, 6, 11, 12, m[s[10]], m[s[11]]) mix(v, 1, 6, 11, 12, m[s[10]], m[s[11]])
mix(v, 2, 7, 8, 13, m[s[12]], m[s[13]]) mix(v, 2, 7, 8, 13, m[s[12]], m[s[13]])
mix(v, 3, 4, 9, 14, m[s[14]], m[s[15]]) mix(v, 3, 4, 9, 14, m[s[14]], m[s[15]])
} }
// finalization
for (i in 0..7) { for (i in 0..7) {
h[i] = h[i] xor v[i] xor v[i + 8] h[i] = h[i] xor v[i] xor v[i + 8]
} }

View File

@@ -36,40 +36,40 @@ class Blake2s(
) )
override fun hash(value: UByteArray): UByteArray { override fun hash(value: UByteArray): UByteArray {
val l = value.size.toULong()
val h = initial.copyOf() val h = initial.copyOf()
h[0] = h[0] xor (0x01010000U or bytes.toUInt()) h[0] = h[0] xor (0x01010000U or bytes.toUInt())
var t = 0U var t = 0U
val l = value.size.toULong()
// padding val blocks = pad(value)
val paddedValue = buildList { .chunked(64) { it.toUByteArray() }
for ((i, block) in blocks.withIndex()) {
t += minOf(l - t, 64UL).toUInt()
compress(h, block, t, i == blocks.lastIndex)
}
return h.toUByteArray(LITTLE_ENDIAN).sliceArray(0..<bytes)
}
private fun pad(
value: UByteArray,
): UByteArray {
return buildList {
addAll(value) addAll(value)
if (isEmpty()) add(0x00U) if (isEmpty()) add(0x00U)
while (size % 64 != 0) { while (size % 64 != 0) {
add(0x00U) add(0x00U)
} }
}.toUByteArray() }.toUByteArray()
// compress
val blocks = paddedValue
.chunked(64) { it.toUByteArray() }
for ((i, block) in blocks.withIndex()) {
t += minOf(l - t, 64U).toUInt()
val m = block.toUIntArray()
compress(h, m, t, i == blocks.lastIndex)
}
return h.toUByteArray(LITTLE_ENDIAN).sliceArray(0..<bytes)
} }
private fun compress( private fun compress(
h: UIntArray, h: UIntArray,
m: UIntArray, block: UByteArray,
t: UInt, t: UInt,
last: Boolean, last: Boolean,
) { ) {
// initialization val m = block.toUIntArray()
val v = UIntArray(16) val v = UIntArray(16)
for (i in 0..<8) v[i] = h[i] for (i in 0..<8) v[i] = h[i]
for (i in 0..<8) v[i + 8] = initial[i] for (i in 0..<8) v[i + 8] = initial[i]
@@ -77,24 +77,20 @@ class Blake2s(
v[12] = v[12] xor t v[12] = v[12] xor t
if (last) v[14] = v[14].inv() if (last) v[14] = v[14].inv()
// rounds repeat(10) { r ->
for (r in 0..<10) {
val s = sigma[r] val s = sigma[r]
// column
mix(v, 0, 4, 8, 12, m[s[0]], m[s[1]]) mix(v, 0, 4, 8, 12, m[s[0]], m[s[1]])
mix(v, 1, 5, 9, 13, m[s[2]], m[s[3]]) mix(v, 1, 5, 9, 13, m[s[2]], m[s[3]])
mix(v, 2, 6, 10, 14, m[s[4]], m[s[5]]) mix(v, 2, 6, 10, 14, m[s[4]], m[s[5]])
mix(v, 3, 7, 11, 15, m[s[6]], m[s[7]]) mix(v, 3, 7, 11, 15, m[s[6]], m[s[7]])
// diagonal
mix(v, 0, 5, 10, 15, m[s[8]], m[s[9]]) mix(v, 0, 5, 10, 15, m[s[8]], m[s[9]])
mix(v, 1, 6, 11, 12, m[s[10]], m[s[11]]) mix(v, 1, 6, 11, 12, m[s[10]], m[s[11]])
mix(v, 2, 7, 8, 13, m[s[12]], m[s[13]]) mix(v, 2, 7, 8, 13, m[s[12]], m[s[13]])
mix(v, 3, 4, 9, 14, m[s[14]], m[s[15]]) mix(v, 3, 4, 9, 14, m[s[14]], m[s[15]])
} }
// finalization
for (i in 0..7) { for (i in 0..7) {
h[i] = h[i] xor v[i] xor v[i + 8] h[i] = h[i] xor v[i] xor v[i + 8]
} }

View File

@@ -41,44 +41,39 @@ open class Keccak(
): UByteArray { ): UByteArray {
val state = ULongArray(25) val state = ULongArray(25)
// padding val blocks = pad(value)
val paddedValue = buildList { .chunked(rate) { it.toUByteArray() }
for (block in blocks) {
absorb(state, block)
}
return squeeze(state)
}
private fun pad(
value: UByteArray,
): UByteArray {
return buildList {
addAll(value) addAll(value)
add(domain) add(domain)
while ((size % rate) != (rate - 1)) { while ((size % rate) != (rate - 1)) {
add(0x00U) add(0x00U)
} }
add(0x80U) add(0x80U)
}
// absorb
val blocks = paddedValue
.chunked(rate) { it.toUByteArray() }
for (block in blocks) {
val numbers = block.toULongArray(LITTLE_ENDIAN)
for ((i, number) in numbers.withIndex()) {
state[i] = state[i] xor number
}
permute(state)
}
// squeeze
return buildList {
var i = 0
while (size < bytes) {
if (i == rate / 8) {
permute(state)
i = 0
}
addAll(
state[i++].toUByteArray(LITTLE_ENDIAN)
.sliceArray(0..<min(bytes - size, 8))
)
}
}.toUByteArray() }.toUByteArray()
} }
private fun absorb(
state: ULongArray,
block: UByteArray,
) {
val numbers = block.toULongArray(LITTLE_ENDIAN)
for ((i, number) in numbers.withIndex()) {
state[i] = state[i] xor number
}
permute(state)
}
private fun permute( private fun permute(
a: ULongArray, a: ULongArray,
) { ) {
@@ -112,4 +107,22 @@ open class Keccak(
a[0] = a[0] xor rc[round] a[0] = a[0] xor rc[round]
} }
} }
fun squeeze(
state: ULongArray,
): UByteArray {
return buildList {
var i = 0
while (size < bytes) {
if (i == rate / 8) {
permute(state)
i = 0
}
addAll(
state[i++].toUByteArray(LITTLE_ENDIAN)
.sliceArray(0..<min(bytes - size, 8))
)
}
}.toUByteArray()
}
} }

View File

@@ -51,36 +51,38 @@ object MD5 : HashFunction() {
value: UByteArray, value: UByteArray,
): UByteArray { ): UByteArray {
val h = initial.copyOf() val h = initial.copyOf()
val l = value.size.toULong() * 8UL
// padding val blocks = pad(value)
val paddedValue = buildList { .chunked(64) { it.toUByteArray() }
for (block in blocks) {
process(h, block)
}
return h.toUByteArray(LITTLE_ENDIAN)
}
private fun pad(
value: UByteArray,
): UByteArray {
val l = value.size.toULong() * 8UL
return buildList {
addAll(value) addAll(value)
add(0x80U) add(0x80U)
while (size % 64 != 56) { while (size % 64 != 56) {
add(0x00U) add(0x00U)
} }
addAll(l.toUByteArray(LITTLE_ENDIAN)) addAll(l.toUByteArray(LITTLE_ENDIAN))
} }.toUByteArray()
// process
val blocks = paddedValue
.chunked(64) { it.toUByteArray() }
for (block in blocks) {
val w = block.toUIntArray(LITTLE_ENDIAN)
process(h, w)
}
return h.toUByteArray(LITTLE_ENDIAN)
} }
private fun process( private fun process(
h: UIntArray, h: UIntArray,
w: UIntArray, block: UByteArray,
) { ) {
val w = block.toUIntArray(LITTLE_ENDIAN)
val v = h.copyOf() val v = h.copyOf()
for (i in 0..<64) { repeat(64) { i ->
var f = when (i) { var f = when (i) {
in 0..15 -> (v[1] and v[2]) or (v[1].inv() and v[3]) 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 16..31 -> (v[3] and v[1]) or (v[3].inv() and v[2])

View File

@@ -21,42 +21,44 @@ object SHA1 : HashFunction() {
value: UByteArray, value: UByteArray,
): UByteArray { ): UByteArray {
val h = initial.copyOf() val h = initial.copyOf()
val l = value.size.toULong() * 8UL
// padding val blocks = pad(value)
val paddedValue = buildList { .chunked(64) { it.toUByteArray() }
for (block in blocks) {
process(h, block)
}
return h.toUByteArray()
}
private fun pad(
value: UByteArray,
): UByteArray {
val l = value.size.toULong() * 8UL
return buildList {
addAll(value) addAll(value)
add(0x80U) add(0x80U)
while (size % 64 != 56) { while (size % 64 != 56) {
add(0x00U) add(0x00U)
} }
addAll(l.toUByteArray()) addAll(l.toUByteArray())
} }.toUByteArray()
// process
val blocks = paddedValue
.chunked(64) { it.toUByteArray() }
for (block in blocks) {
val w = buildList {
addAll(block.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)
}
}.toUIntArray()
process(h, w)
}
return h.toUByteArray()
} }
private fun process( private fun process(
h: UIntArray, h: UIntArray,
w: 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() val v = h.copyOf()
for (i in 0..<80) { repeat(80) { i ->
val f = when (i) { val f = when (i) {
in 0..<20 -> (v[1] and v[2]) or (v[1].inv() and v[3]) in 0..<20 -> (v[1] and v[2]) or (v[1].inv() and v[3])
in 20..<40 -> v[1] xor v[2] xor v[3] in 20..<40 -> v[1] xor v[2] xor v[3]

View File

@@ -33,43 +33,45 @@ object `SHA-224` : HashFunction() {
value: UByteArray, value: UByteArray,
): UByteArray { ): UByteArray {
val h = initial.copyOf() val h = initial.copyOf()
val l = value.size.toULong() * 8UL
// padding val blocks = pad(value)
val paddedValue = buildList { .chunked(64) { it.toUByteArray() }
for (block in blocks) {
process(h, block)
}
return h.sliceArray(0..6).toUByteArray()
}
private fun pad(
value: UByteArray,
): UByteArray {
val l = value.size.toULong() * 8UL
return buildList {
addAll(value) addAll(value)
add(0x80U) add(0x80U)
while (size % 64 != 56) { while (size % 64 != 56) {
add(0x00U) add(0x00U)
} }
addAll(l.toUByteArray()) addAll(l.toUByteArray())
} }.toUByteArray()
// process
val blocks = paddedValue
.chunked(64) { it.toUByteArray() }
for (block in blocks) {
val w = buildList {
addAll(block.toUIntArray())
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 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)
}
}.toUIntArray()
process(h, w)
}
return h.sliceArray(0..6).toUByteArray()
} }
private fun process( private fun process(
h: UIntArray, h: UIntArray,
w: UIntArray, block: UByteArray,
) { ) {
val w = buildList {
addAll(block.toUIntArray())
for (i in 16..63) {
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)
add(get(i - 16) + s0 + get(i - 7) + s1)
}
}.toUIntArray()
val v = h.copyOf() val v = h.copyOf()
for (i in 0..<64) { repeat(64) { i ->
val s0 = v[0].rotateRight(2) xor v[0].rotateRight(13) xor v[0].rotateRight(22) val s0 = v[0].rotateRight(2) xor v[0].rotateRight(13) xor v[0].rotateRight(22)
val s1 = v[4].rotateRight(6) xor v[4].rotateRight(11) xor v[4].rotateRight(25) val s1 = v[4].rotateRight(6) xor v[4].rotateRight(11) xor v[4].rotateRight(25)
val ch = (v[4] and v[5]) xor (v[4].inv() and v[6]) val ch = (v[4] and v[5]) xor (v[4].inv() and v[6])

View File

@@ -33,43 +33,45 @@ object `SHA-256` : HashFunction() {
value: UByteArray, value: UByteArray,
): UByteArray { ): UByteArray {
val h = initial.copyOf() val h = initial.copyOf()
val l = value.size.toULong() * 8UL
// padding val blocks = pad(value)
val paddedValue = buildList { .chunked(64) { it.toUByteArray() }
for (block in blocks) {
process(h, block)
}
return h.toUByteArray()
}
private fun pad(
value: UByteArray,
): UByteArray {
val l = value.size.toULong() * 8UL
return buildList {
addAll(value) addAll(value)
add(0x80U) add(0x80U)
while (size % 64 != 56) { while (size % 64 != 56) {
add(0x00U) add(0x00U)
} }
addAll(l.toUByteArray()) addAll(l.toUByteArray())
} }.toUByteArray()
// process
val chunks = paddedValue
.chunked(64) { it.toUByteArray() }
for (chunk in chunks) {
val w = buildList {
addAll(chunk.toUIntArray())
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 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)
}
}.toUIntArray()
process(h, w)
}
return h.toUByteArray()
} }
private fun process( private fun process(
h: UIntArray, h: UIntArray,
w: UIntArray, block: UByteArray,
) { ) {
val w = buildList {
addAll(block.toUIntArray())
for (i in 16..63) {
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)
add(get(i - 16) + s0 + get(i - 7) + s1)
}
}.toUIntArray()
val v = h.copyOf() val v = h.copyOf()
for (i in 0..<64) { repeat(64) { i ->
val s0 = v[0].rotateRight(2) xor v[0].rotateRight(13) xor v[0].rotateRight(22) val s0 = v[0].rotateRight(2) xor v[0].rotateRight(13) xor v[0].rotateRight(22)
val s1 = v[4].rotateRight(6) xor v[4].rotateRight(11) xor v[4].rotateRight(25) val s1 = v[4].rotateRight(6) xor v[4].rotateRight(11) xor v[4].rotateRight(25)
val ch = (v[4] and v[5]) xor (v[4].inv() and v[6]) val ch = (v[4] and v[5]) xor (v[4].inv() and v[6])

View File

@@ -45,43 +45,45 @@ object `SHA-384` : HashFunction() {
value: UByteArray, value: UByteArray,
): UByteArray { ): UByteArray {
val h = initial.copyOf() val h = initial.copyOf()
val l = value.size.toULong() * 8UL
// padding val blocks = pad(value)
val paddedValue = buildList { .chunked(128) { it.toUByteArray() }
for (block in blocks) {
process(h, block)
}
return h.sliceArray(0..5).toUByteArray()
}
private fun pad(
value: UByteArray,
): UByteArray {
val l = value.size.toULong() * 8UL
return buildList {
addAll(value) addAll(value)
add(0x80U) add(0x80U)
while (size % 128 != 120) { while (size % 128 != 120) {
add(0x00U) add(0x00U)
} }
addAll(l.toUByteArray()) addAll(l.toUByteArray())
} }.toUByteArray()
// process
val blocks = paddedValue
.chunked(128) { it.toUByteArray() }
for (block in blocks) {
val w = buildList {
addAll(block.toULongArray())
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 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)
}
}.toULongArray()
process(h, w)
}
return h.sliceArray(0..5).toUByteArray()
} }
private fun process( private fun process(
h: ULongArray, h: ULongArray,
w: ULongArray, block: UByteArray,
) { ) {
val w = buildList {
addAll(block.toULongArray())
for (i in 16..79) {
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)
add(get(i - 16) + s0 + get(i - 7) + s1)
}
}.toULongArray()
val v = h.copyOf() val v = h.copyOf()
for (i in 0..<80) { repeat(80) { i ->
val s0 = v[0].rotateRight(28) xor v[0].rotateRight(34) xor v[0].rotateRight(39) val s0 = v[0].rotateRight(28) xor v[0].rotateRight(34) xor v[0].rotateRight(39)
val s1 = v[4].rotateRight(14) xor v[4].rotateRight(18) xor v[4].rotateRight(41) val s1 = v[4].rotateRight(14) xor v[4].rotateRight(18) xor v[4].rotateRight(41)
val ch = (v[4] and v[5]) xor (v[4].inv() and v[6]) val ch = (v[4] and v[5]) xor (v[4].inv() and v[6])

View File

@@ -45,43 +45,45 @@ object `SHA-512` : HashFunction() {
value: UByteArray, value: UByteArray,
): UByteArray { ): UByteArray {
val h = initial.copyOf() val h = initial.copyOf()
val l = value.size.toULong() * 8UL
// padding val blocks = pad(value)
val paddedValue = buildList { .chunked(128) { it.toUByteArray() }
for (block in blocks) {
process(h, block)
}
return h.toUByteArray()
}
private fun pad(
value: UByteArray,
): UByteArray {
val l = value.size.toULong() * 8UL
return buildList {
addAll(value) addAll(value)
add(0x80U) add(0x80U)
while (size % 128 != 120) { while (size % 128 != 120) {
add(0x00U) add(0x00U)
} }
addAll(l.toUByteArray()) addAll(l.toUByteArray())
} }.toUByteArray()
// process
val blocks = paddedValue
.chunked(128) { it.toUByteArray() }
for (block in blocks) {
val w = buildList {
addAll(block.toULongArray())
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 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)
}
}.toULongArray()
process(h, w)
}
return h.toUByteArray()
} }
private fun process( private fun process(
h: ULongArray, h: ULongArray,
w: ULongArray, block: UByteArray,
) { ) {
val w = buildList {
addAll(block.toULongArray())
for (i in 16..79) {
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)
add(get(i - 16) + s0 + get(i - 7) + s1)
}
}.toULongArray()
val v = h.copyOf() val v = h.copyOf()
for (i in 0..<80) { repeat(80) { i ->
val s0 = v[0].rotateRight(28) xor v[0].rotateRight(34) xor v[0].rotateRight(39) val s0 = v[0].rotateRight(28) xor v[0].rotateRight(34) xor v[0].rotateRight(39)
val s1 = v[4].rotateRight(14) xor v[4].rotateRight(18) xor v[4].rotateRight(41) val s1 = v[4].rotateRight(14) xor v[4].rotateRight(18) xor v[4].rotateRight(41)
val ch = (v[4] and v[5]) xor (v[4].inv() and v[6]) val ch = (v[4] and v[5]) xor (v[4].inv() and v[6])