Compare commits

..

32 Commits

Author SHA1 Message Date
8627e2c562 Update README.md 2026-04-16 16:11:28 +00:00
8400f76964 Upgrade Dependency
All checks were successful
/ test (pull_request) Successful in 47s
2026-03-11 22:24:59 +01:00
e74c35ef40 Refactor 2026-03-11 21:58:51 +01:00
6df6547ef4 Bump version to 1.7.0 2026-03-11 18:53:57 +01:00
328d4b957e Implement streaming API 2026-03-11 18:53:00 +01:00
cb3ff7ec6c Upgrade bytes-kt
All checks were successful
/ test (pull_request) Successful in 44s
2026-02-14 16:32:50 +01:00
902cb060a1 remove unsigned support
All checks were successful
/ test (pull_request) Successful in 1m45s
2026-02-08 14:04:41 +01:00
e138ec0b6d refactor padding 2026-01-22 12:44:59 +01:00
5547e77c58 Merge pull request '1.5.1 release' (#8) from develop into main
All checks were successful
/ publish (push) Successful in 1m18s
Reviewed-on: Infendro/hash-kt#8
2026-01-22 11:20:04 +00:00
8535476674 implement destination offset
All checks were successful
/ test (pull_request) Successful in 27s
2026-01-22 12:18:22 +01:00
750bcf72c5 Merge pull request '1.5.0 release' (#7) from develop into main
All checks were successful
/ publish (push) Successful in 2m41s
Reviewed-on: Infendro/hash-kt#7
2026-01-22 11:10:57 +00:00
b00d231da5 upgrade dependency
All checks were successful
/ test (pull_request) Successful in 39s
2026-01-22 12:09:23 +01:00
4331145c34 refactor math utility
All checks were successful
/ test (pull_request) Successful in 32s
2026-01-17 15:44:50 +01:00
62d6b8b01e small refactor to ci caching
All checks were successful
/ test (pull_request) Successful in 24s
2026-01-17 12:37:57 +01:00
681f2146b4 make Keccak an open class
All checks were successful
/ test (pull_request) Successful in 45s
2026-01-15 22:36:58 +01:00
d06674c28c change tests to use ByteArray 2026-01-15 22:12:52 +01:00
d40df04e2e implement optimizations 2026-01-15 22:06:28 +01:00
ab036f4f9f improve ci
All checks were successful
/ test (push) Successful in 1m9s
/ publish (push) Has been skipped
2026-01-13 16:03:10 +01:00
e9cf958ef7 update README
small rewording, link wikipedia article
2025-12-14 14:24:46 +01:00
f3af9d3361 bump version to 1.4.0
All checks were successful
/ publish (push) Successful in 3m51s
2025-12-14 14:11:49 +01:00
87c606d6dd replace IllegalArgumentException with require 2025-12-14 00:13:41 +01:00
197beb828a upgrade dependency 2025-12-13 21:00:33 +01:00
ab57683797 update README 2025-12-13 21:00:22 +01:00
b0bb2e66a8 fix workflow 2025-12-13 01:29:31 +01:00
ebdf640934 small refactor 2025-12-13 01:09:19 +01:00
6c74c64dec refactor build.gradle.kts 2025-12-13 00:59:33 +01:00
a2731bd60c use common plugin 2025-12-13 00:56:02 +01:00
1ddda4889a convert HashFunction to interface 2025-12-12 14:08:52 +01:00
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
48 changed files with 1353 additions and 1587 deletions

View File

@@ -1,36 +0,0 @@
on:
push:
branches:
- main
env:
GIT__TOKEN: ${{ secrets.TOKEN }}
jobs:
publish:
runs-on: linux
steps:
- uses: actions/checkout@v4
- uses: actions/cache/restore@v4
with:
key: gradle
path: |
~/.gradle/caches/
~/.gradle/wrapper/
~/.konan/
- uses: actions/setup-java@v4
with:
java-version: '24'
distribution: 'temurin'
- run: ./gradlew publish
- uses: actions/cache/save@v4
with:
key: gradle
path: |
~/.gradle/caches/
~/.gradle/wrapper/
~/.konan/

View File

@@ -0,0 +1,47 @@
on:
push:
branches: [ main ]
jobs:
publish:
runs-on: linux
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Java
uses: actions/setup-java@v4
with:
java-version: '24'
distribution: 'temurin'
- name: Cache Gradle
uses: actions/cache@v4
with:
key: gradle-${{ hashFiles('**/libs.versions.toml') }}
restore-keys: gradle
path: |
~/.gradle/caches/
~/.gradle/wrapper/
- name: Cache Konan
uses: actions/cache@v4
with:
key: konan-${{ hashFiles('**/libs.versions.toml') }}
restore-keys: konan
path: |
~/.konan/
- name: Cache Node
uses: actions/cache@v4
with:
key: node-${{ hashFiles('**/libs.versions.toml') }}
restore-keys: node
path: |
~/.gradle/nodejs
~/.gradle/yarn
- name: Publish
run: ./gradlew publish
env:
INFENDRO__TOKEN: ${{ secrets.TOKEN }}

View File

@@ -0,0 +1,28 @@
on:
pull_request:
branches: [ main ]
jobs:
test:
runs-on: linux
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Java
uses: actions/setup-java@v4
with:
java-version: '24'
distribution: 'temurin'
- name: Cache Gradle
uses: actions/cache@v4
with:
key: gradle-${{ hashFiles('**/libs.versions.toml') }}
restore-keys: gradle
path: |
~/.gradle/caches/
~/.gradle/wrapper/
- name: Test
run: ./gradlew jvmTest

View File

@@ -1,20 +1,15 @@
# Kotlin Hash
# hash.kt
This library provides various [Cryptographic Hash Function](https://en.wikipedia.org/wiki/Cryptographic_hash_function)
implementations in Kotlin Multiplatform.
`hash.kt` is a Kotlin Multiplatform library that provides common [Cryptographic Hash Functions](https://en.wikipedia.org/wiki/Cryptographic_hash_function).
## Features
* [MD5](https://en.wikipedia.org/wiki/MD5)
* [SHA1](https://en.wikipedia.org/wiki/SHA-1)
* [SHA224](https://en.wikipedia.org/wiki/SHA-2)
* [SHA256](https://en.wikipedia.org/wiki/SHA-2)
* [SHA384](https://en.wikipedia.org/wiki/SHA-2)
* [SHA512](https://en.wikipedia.org/wiki/SHA-2)
* Multiplatform support
* JVM
* JavaScript
* Native (Linux)
Supported algorithms:
- MD5
- SHA-1
- SHA-2 (SHA-224, SHA-256, SHA-384, SHA-512)
- SHA-3 (SHA3-224, SHA3-256, SHA3-384, SHA3-512)
- SHAKE (SHAKE128, SHAKE256)
- Blake (Blake-224, Blake-256, Blake-384, Blake-512)
- Blake2 (Blake2s, Blake2b)
## Installation
@@ -26,18 +21,16 @@ repositories {
}
dependencies {
implementation("com.infendro:hash:1.2.2")
implementation("com.infendro:hash:1.7.0")
}
```
## Usage
```kotlin
import com.infendro.hash.SHA256
fun main() {
// hash some value using SHA256
val value = "...".encodeToByteArray()
val hash = SHA256.hash(value)
// hash some value using SHA-256
val value = "Hello World!".encodeToByteArray()
val hash = `SHA-256`().hash(value)
}
```

View File

@@ -1,62 +1,44 @@
group = "com.infendro"
version = "1.3.2"
@file:OptIn(ExperimentalWasmDsl::class)
repositories {
maven("https://git.infendro.com/api/packages/Infendro/maven")
mavenCentral()
}
import com.infendro.plugin.infendro
import com.infendro.plugin.token
import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
group = "com.infendro"
version = "1.7.0"
plugins {
alias(libs.plugins.infendro)
alias(libs.plugins.multiplatform)
id("maven-publish")
}
kotlin {
jvm()
js {
nodejs()
}
linuxX64()
linuxArm64()
mingwX64()
macosX64()
macosArm64()
js { nodejs() }
wasmJs { nodejs() }
wasmWasi { nodejs() }
repositories {
infendro()
mavenCentral()
}
sourceSets {
commonMain.dependencies {
implementation(libs.bytearray)
implementation(libs.bytes)
}
commonTest.dependencies {
implementation(libs.test)
}
}
compilerOptions {
freeCompilerArgs.add("-opt-in=kotlin.ExperimentalUnsignedTypes")
}
}
publishing {
repositories {
maven {
url = uri("https://git.infendro.com/api/packages/Infendro/maven")
authentication.create("header", HttpHeaderAuthentication::class)
credentials(HttpHeaderCredentials::class) {
val token = secret("git.token") ?: throw GradleException()
name = "Authorization"
value = "token $token"
}
}
}
}
fun secret(
key: String,
): String? {
val property = key
val environment = key
.uppercase()
.replace(".", "__")
val prop = properties[property] as String?
val env = System.getenv(environment)
return prop ?: env
publishing.repositories {
infendro(token)
}

View File

@@ -1,10 +1,12 @@
[versions]
kotlin = "2.2.21"
bytearray = "1.2.3"
infendro = "1.1.0"
kotlin = "2.3.0"
bytes = "1.4.1"
[plugins]
infendro = { id = "com.infendro.plugin", version.ref = "infendro" }
multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
[libraries]
bytearray = { module = "com.infendro:bytearray", version.ref = "bytearray" }
bytes = { module = "com.infendro:bytes", version.ref = "bytes" }
test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" }

View File

@@ -1 +1,6 @@
rootProject.name = "hash"
pluginManagement.repositories {
maven("https://git.infendro.com/api/packages/Infendro/maven")
mavenCentral()
}

View File

@@ -0,0 +1,47 @@
package com.infendro.hash
import com.infendro.bytes.ByteOrder
import com.infendro.bytes.int.copyInto
import com.infendro.bytes.long.copyInto
class Buffer(
val size: Int,
) {
val value = ByteArray(size)
var offset = 0
val free: Int
get() = size - offset
fun isEmpty(): Boolean = offset == 0
fun isNotEmpty(): Boolean = !isEmpty()
fun isFull(): Boolean = offset == size
fun reset() {
value.fill(0x00)
offset = 0
}
fun jumpTo(offset: Int) {
this.offset = offset
}
fun append(byte: Byte) {
value[offset++] = byte
}
fun append(bytes: ByteArray, startIndex: Int = 0, endIndex: Int = bytes.size) {
bytes.copyInto(value, offset, startIndex, endIndex)
offset += (endIndex - startIndex)
}
fun append(n: Int, order: ByteOrder = ByteOrder.BIG_ENDIAN) {
n.copyInto(value, offset, order = order)
offset += 4
}
fun append(n: Long, order: ByteOrder = ByteOrder.BIG_ENDIAN) {
n.copyInto(value, offset, order = order)
offset += 8
}
}

View File

@@ -1,13 +1,67 @@
package com.infendro.hash
abstract class HashFunction {
abstract val bytes: Int
abstract class HashFunction(
val bytes: Int,
val block: Int,
) {
val bits: Int
get() = bytes * 8
abstract val block: Int
protected val buffer = Buffer(block)
protected var length = 0L
abstract fun hash(
value: UByteArray,
): UByteArray
open fun reset() {
buffer.reset()
length = 0L
}
open fun update(byte: Byte) {
buffer.append(byte)
length++
if (buffer.isFull()) {
process()
buffer.reset()
}
}
open fun update(bytes: ByteArray) {
var i = 0
var free = buffer.free
while (i + free < bytes.size) {
buffer.append(bytes, startIndex = i, endIndex = i + free)
length += free
process()
buffer.reset()
free = buffer.free
i += block
}
buffer.append(bytes, startIndex = i)
length += (bytes.size - i)
if (buffer.isFull()) {
process()
buffer.reset()
}
}
protected abstract fun process()
abstract fun digestInto(destination: ByteArray, destinationOffset: Int = 0)
fun digest(): ByteArray {
val result = ByteArray(bytes)
digestInto(result)
return result
}
fun hashInto(value: ByteArray, destination: ByteArray, destinationOffset: Int = 0) {
update(value)
digestInto(destination, destinationOffset)
}
fun hash(value: ByteArray): ByteArray {
update(value)
return digest()
}
}

View File

@@ -1,120 +1,69 @@
package com.infendro.hash.blake
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.hash.HashFunction
import com.infendro.hash.blake.`Blake-256`.Companion.c
import com.infendro.hash.blake.`Blake-256`.Companion.sigma
object `Blake-224` : HashFunction() {
override val bytes: Int
get() = 28
class `Blake-224` : HashFunction(28, 64) {
private val h = initial.copyOf()
override val block: Int
get() = 64
private val m = IntArray(16)
private val v = IntArray(16)
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)
override fun reset() {
super.reset()
initial.copyInto(h)
}
return h.sliceArray(0..6).toUByteArray()
override fun process() = compress(buffer.value, length * 8L)
private fun finalize() {
buffer.append(0x80.toByte())
if (buffer.free < 8) {
process()
buffer.reset()
}
buffer.jumpTo(56)
buffer.append(length * 8L)
process()
}
private fun compress(
h: UIntArray,
m: UIntArray,
t: UInt,
) {
// initialization
val v = UIntArray(16)
override fun digestInto(destination: ByteArray, destinationOffset: Int) {
finalize()
h.copyInto(destination, destinationOffset, endIndex = 7)
reset()
}
private fun compress(block: ByteArray, t: Long) {
block.copyInto(m)
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]
for (i in 0..<2) v[i + 12] = c[i + 4] xor t.toInt()
for (i in 0..<2) v[i + 14] = c[i + 6] xor (t ushr 32).toInt()
// rounds
for (r in 0..<14) {
repeat(14) { r ->
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) {
for (i in 0..<8) {
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,
) {
private fun g(v: IntArray, a: Int, b: Int, c: Int, d: Int, x: Int, y: Int) {
v[a] += v[b] + x
v[d] = (v[d] xor v[a]).rotateRight(16)
v[c] += v[d]
@@ -124,4 +73,13 @@ object `Blake-224` : HashFunction() {
v[c] += v[d]
v[b] = (v[b] xor v[c]).rotateRight(7)
}
companion object {
private val initial = intArrayOf(
-0x3efa6128, +0x367cd507,
+0x3070dd17, -0x08f1a6c7,
-0x003ff4cf, +0x68581511,
+0x64f98fa7, -0x4105b05c,
)
}
}

View File

@@ -1,35 +1,98 @@
package com.infendro.hash.blake
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.hash.HashFunction
object `Blake-256` : HashFunction() {
override val bytes: Int
get() = 32
class `Blake-256` : HashFunction(32, 64) {
private val h = initial.copyOf()
override val block: Int
get() = 64
private val m = IntArray(16)
private val v = IntArray(16)
private val initial = uintArrayOf(
0x6a09e667U, 0xbb67ae85U,
0x3c6ef372U, 0xa54ff53aU,
0x510e527fU, 0x9b05688cU,
0x1f83d9abU, 0x5be0cd19U,
override fun reset() {
super.reset()
initial.copyInto(h)
}
override fun process() = compress(buffer.value, length * 8L)
private fun finalize() {
buffer.append(0x80.toByte())
if (buffer.free < 9) {
process()
buffer.reset()
}
buffer.jumpTo(55)
buffer.append(0x01.toByte())
buffer.append(length * 8L)
process()
}
override fun digestInto(destination: ByteArray, destinationOffset: Int) {
finalize()
h.copyInto(destination, destinationOffset)
reset()
}
private fun compress(block: ByteArray, t: Long) {
block.copyInto(m)
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.toInt()
for (i in 0..<2) v[i + 14] = c[i + 6] xor (t ushr 32).toInt()
repeat(14) { r ->
val s = sigma[r % 10]
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]])
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]])
}
for (i in 0..<8) {
h[i] = h[i] xor v[i] xor v[i + 8]
}
}
private fun g(v: IntArray, a: Int, b: Int, c: Int, d: Int, x: Int, y: Int) {
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)
}
companion object {
private val initial = intArrayOf(
+0x6a09e667, -0x4498517b,
+0x3c6ef372, -0x5ab00ac6,
+0x510e527f, -0x64fa9774,
+0x1f83d9ab, +0x5be0cd19,
)
private val c = uintArrayOf(
0x243f6a88U, 0x85a308d3U,
0x13198a2eU, 0x03707344U,
0xa4093822U, 0x299f31d0U,
0x082efa98U, 0xec4e6c89U,
0x452821e6U, 0x38d01377U,
0xbe5466cfU, 0x34e90c6cU,
0xc0ac29b7U, 0xc97c50ddU,
0x3f84d5b5U, 0xb5470917U,
internal val c = intArrayOf(
+0x243f6a88, -0x7a5cf72d,
+0x13198a2e, +0x03707344,
-0x5bf6c7de, +0x299f31d0,
+0x082efa98, -0x13b19377,
+0x452821e6, +0x38d01377,
-0x41ab9931, +0x34e90c6c,
-0x3f53d649, -0x3683af23,
+0x3f84d5b5, -0x4ab8f6e9,
)
private val sigma = arrayOf(
internal 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),
@@ -41,88 +104,5 @@ object `Blake-256` : HashFunction() {
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

@@ -1,120 +1,70 @@
package com.infendro.hash.blake
import com.infendro.bytearray.toUByteArray
import com.infendro.bytearray.toULongArray
import com.infendro.bytes.bytearray.copyInto
import com.infendro.bytes.longarray.copyInto
import com.infendro.hash.HashFunction
import com.infendro.hash.blake.`Blake-512`.Companion.c
import com.infendro.hash.blake.`Blake-512`.Companion.sigma
object `Blake-384` : HashFunction() {
override val bytes: Int
get() = 48
class `Blake-384` : HashFunction(48, 128) {
private val h = initial.copyOf()
override val block: Int
get() = 128
private val m = LongArray(16)
private val v = LongArray(16)
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)
override fun reset() {
super.reset()
initial.copyInto(h)
}
return h.sliceArray(0..5).toUByteArray()
override fun process() = compress(buffer.value, length * 8L)
private fun finalize() {
buffer.append(0x80.toByte())
if (buffer.free < 16) {
process()
buffer.reset()
}
buffer.jumpTo(112)
buffer.append(0L)
buffer.append(length * 8L)
process()
}
private fun compress(
h: ULongArray,
m: ULongArray,
t: ULong,
) {
// initialization
val v = ULongArray(16)
override fun digestInto(destination: ByteArray, destinationOffset: Int) {
finalize()
h.copyInto(destination, destinationOffset, endIndex = 6)
reset()
}
private fun compress(block: ByteArray, t: Long) {
block.copyInto(m)
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) {
repeat(16) { r ->
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) {
for (i in 0..<8) {
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,
) {
private fun g(v: LongArray, a: Int, b: Int, c: Int, d: Int, x: Long, y: Long) {
v[a] += v[b] + x
v[d] = (v[d] xor v[a]).rotateRight(32)
v[c] += v[d]
@@ -124,4 +74,13 @@ object `Blake-384` : HashFunction() {
v[c] += v[d]
v[b] = (v[b] xor v[c]).rotateRight(11)
}
companion object {
private val initial = longArrayOf(
-0x344462a23efa6128, +0x629a292a367cd507,
-0x6ea6fea5cf8f22e9, +0x152fecd8f70e5939,
+0x67332667ffc00b31, -0x714bb57897a7eaef,
-0x24f3d1f29b067059, +0x47b5481dbefa4fa4,
)
}
}

View File

@@ -1,35 +1,99 @@
package com.infendro.hash.blake
import com.infendro.bytearray.toUByteArray
import com.infendro.bytearray.toULongArray
import com.infendro.bytes.bytearray.copyInto
import com.infendro.bytes.longarray.copyInto
import com.infendro.hash.HashFunction
object `Blake-512` : HashFunction() {
override val bytes: Int
get() = 64
class `Blake-512` : HashFunction(64, 128) {
private val h = initial.copyOf()
override val block: Int
get() = 128
private val m = LongArray(16)
private val v = LongArray(16)
private val initial = ulongArrayOf(
0x6a09e667f3bcc908UL, 0xbb67ae8584caa73bUL,
0x3c6ef372fe94f82bUL, 0xa54ff53a5f1d36f1UL,
0x510e527fade682d1UL, 0x9b05688c2b3e6c1fUL,
0x1f83d9abfb41bd6bUL, 0x5be0cd19137e2179UL,
override fun reset() {
super.reset()
initial.copyInto(h)
}
override fun process() = compress(buffer.value, length * 8L)
private fun finalize() {
buffer.append(0x80.toByte())
if (buffer.free < 17) {
process()
buffer.reset()
}
buffer.jumpTo(111)
buffer.append(0x01.toByte())
buffer.append(0L)
buffer.append(length * 8L)
process()
}
override fun digestInto(destination: ByteArray, destinationOffset: Int) {
finalize()
h.copyInto(destination, destinationOffset)
reset()
}
private fun compress(block: ByteArray, t: Long) {
block.copyInto(m)
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]
repeat(16) { r ->
val s = sigma[r % 10]
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]])
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]])
}
for (i in 0..<8) {
h[i] = h[i] xor v[i] xor v[i + 8]
}
}
private fun g(v: LongArray, a: Int, b: Int, c: Int, d: Int, x: Long, y: Long) {
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)
}
companion object {
private val initial = longArrayOf(
+0x6a09e667f3bcc908L, -0x4498517a7b3558c5L,
+0x3c6ef372fe94f82bL, -0x5ab00ac5a0e2c90fL,
+0x510e527fade682d1L, -0x64fa9773d4c193e1L,
+0x1f83d9abfb41bd6bL, +0x5be0cd19137e2179L,
)
private val c = ulongArrayOf(
0x243f6a8885a308d3UL, 0x13198a2e03707344UL,
0xa4093822299f31d0UL, 0x082efa98ec4e6c89UL,
0x452821e638d01377UL, 0xbe5466cf34e90c6cUL,
0xc0ac29b7c97c50ddUL, 0x3f84d5b5b5470917UL,
0x9216d5d98979fb1bUL, 0xd1310ba698dfb5acUL,
0x2ffd72dbd01adfb7UL, 0xb8e1afed6a267e96UL,
0xba7c9045f12c7f99UL, 0x24a19947b3916cf7UL,
0x0801f2e2858efc16UL, 0x636920d871574e69UL,
internal val c = longArrayOf(
+0x243f6a8885a308d3L, +0x13198a2e03707344L,
-0x5bf6c7ddd660ce30L, +0x082efa98ec4e6c89L,
+0x452821e638d01377L, -0x41ab9930cb16f394L,
-0x3f53d6483683af23L, +0x3f84d5b5b5470917L,
-0x6de92a26768604e5L, -0x2ecef45967204a54L,
+0x2ffd72dbd01adfb7L, -0x471e501295d9816aL,
-0x45836fba0ed38067L, +0x24a19947b3916cf7L,
+0x0801f2e2858efc16L, +0x636920d871574e69L,
)
private val sigma = arrayOf(
internal 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),
@@ -41,89 +105,5 @@ object `Blake-512` : HashFunction() {
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

@@ -1,25 +1,113 @@
package com.infendro.hash.blake2
import com.infendro.bytearray.ByteOrder
import com.infendro.bytearray.toUByteArray
import com.infendro.bytearray.toULongArray
import com.infendro.bytes.ByteOrder.LITTLE_ENDIAN
import com.infendro.bytes.bytearray.copyInto
import com.infendro.bytes.longarray.toByteArray
import com.infendro.hash.HashFunction
class Blake2b(
override val bytes: Int,
) : HashFunction() {
class Blake2b(bytes: Int) : HashFunction(bytes, 128) {
init {
if (bytes !in 1..64) throw IllegalArgumentException()
require(bytes in 1..64)
}
override val block: Int
get() = 128
private val h = initial.copyOf()
.also { h ->
h[0] = h[0] xor (0x01010000L or bytes.toLong())
}
private val initial = ulongArrayOf(
0x6a09e667f3bcc908UL, 0xbb67ae8584caa73bUL,
0x3c6ef372fe94f82bUL, 0xa54ff53a5f1d36f1UL,
0x510e527fade682d1UL, 0x9b05688c2b3e6c1fUL,
0x1f83d9abfb41bd6bUL, 0x5be0cd19137e2179UL,
private val m = LongArray(16)
private val v = LongArray(16)
override fun reset() {
super.reset()
initial.copyInto(h)
h[0] = h[0] xor (0x01010000L or bytes.toLong())
}
override fun update(byte: Byte) {
if (buffer.isFull()) {
process()
buffer.reset()
}
buffer.append(byte)
length++
}
override fun update(bytes: ByteArray) {
if (buffer.isFull() && bytes.isNotEmpty()) {
process()
buffer.reset()
}
var i = 0
var free = buffer.free
while (i + free < bytes.size) {
buffer.append(bytes, startIndex = i, endIndex = i + free)
length += free
process()
buffer.reset()
free = buffer.free
i += block
}
buffer.append(bytes, startIndex = i)
length += (bytes.size - i)
}
override fun process() = compress(buffer.value, length, false)
private fun finalize() = compress(buffer.value, length, true)
override fun digestInto(destination: ByteArray, destinationOffset: Int) {
finalize()
h.toByteArray(order = LITTLE_ENDIAN).copyInto(destination, destinationOffset, endIndex = bytes)
reset()
}
private fun compress(block: ByteArray, t: Long, last: Boolean) {
block.copyInto(m)
for (i in 0..<8) v[i] = h[i]
for (i in 0..<8) v[i + 8] = initial[i]
v[12] = v[12] xor t
if (last) v[14] = v[14].inv()
repeat(12) { r ->
val s = sigma[r % 10]
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, 2, 6, 10, 14, m[s[4]], m[s[5]])
mix(v, 3, 7, 11, 15, m[s[6]], m[s[7]])
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, 2, 7, 8, 13, m[s[12]], m[s[13]])
mix(v, 3, 4, 9, 14, m[s[14]], m[s[15]])
}
for (i in 0..<8) {
h[i] = h[i] xor v[i] xor v[i + 8]
}
}
private fun mix(v: LongArray, a: Int, b: Int, c: Int, d: Int, x: Long, y: Long) {
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(24)
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(63)
}
companion object {
private val initial = longArrayOf(
+0x6a09e667f3bcc908L, -0x4498517a7b3558c5L,
+0x3c6ef372fe94f82bL, -0x5ab00ac5a0e2c90fL,
+0x510e527fade682d1L, -0x64fa9773d4c193e1L,
+0x1f83d9abfb41bd6bL, +0x5be0cd19137e2179L,
)
private val sigma = arrayOf(
@@ -34,88 +122,5 @@ class Blake2b(
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()
h[0] = h[0] xor (0x01010000UL or bytes.toULong())
var t = 0UL
val l = value.size.toULong()
// padding
val paddedValue = buildList {
addAll(value)
if (isEmpty()) add(0x00U)
while (size % 128 != 0) {
add(0x00U)
}
}.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(
h: ULongArray,
m: ULongArray,
t: ULong,
last: Boolean,
) {
// initialization
val v = ULongArray(16)
for (i in 0..<8) v[i] = h[i]
for (i in 0..<8) v[i + 8] = initial[i]
v[12] = v[12] xor t
if (last) v[14] = v[14].inv()
// rounds
for (r in 0..<12) {
val s = sigma[r % 10]
// column
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, 2, 6, 10, 14, m[s[4]], m[s[5]])
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, 1, 6, 11, 12, m[s[10]], m[s[11]])
mix(v, 2, 7, 8, 13, m[s[12]], m[s[13]])
mix(v, 3, 4, 9, 14, m[s[14]], m[s[15]])
}
// finalization
for (i in 0..7) {
h[i] = h[i] xor v[i] xor v[i + 8]
}
}
private fun mix(
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(24)
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(63)
}
}

View File

@@ -1,25 +1,114 @@
package com.infendro.hash.blake2
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.toByteArray
import com.infendro.hash.HashFunction
class Blake2s(
override val bytes: Int,
) : HashFunction() {
class Blake2s(bytes: Int) : HashFunction(bytes, 64) {
init {
if (bytes !in 1..32) throw IllegalArgumentException()
require(bytes in 1..32)
}
override val block: Int
get() = 64
private val h = initial.copyOf()
.also { h ->
h[0] = h[0] xor (0x01010000 or bytes)
}
private val initial = uintArrayOf(
0x6a09e667U, 0xbb67ae85U,
0x3c6ef372U, 0xa54ff53aU,
0x510e527fU, 0x9b05688cU,
0x1f83d9abU, 0x5be0cd19U,
private val m = IntArray(16)
private val v = IntArray(16)
override fun reset() {
super.reset()
initial.copyInto(h)
h[0] = h[0] xor (0x01010000 or bytes)
}
override fun update(byte: Byte) {
if (buffer.isFull()) {
process()
buffer.reset()
}
buffer.append(byte)
length++
}
override fun update(bytes: ByteArray) {
if (buffer.isFull() && bytes.isNotEmpty()) {
process()
buffer.reset()
}
var i = 0
var free = buffer.free
while (i + free < bytes.size) {
buffer.append(bytes, startIndex = i, endIndex = i + free)
length += free
process()
buffer.reset()
free = buffer.free
i += block
}
buffer.append(bytes, startIndex = i)
length += (bytes.size - i)
}
override fun process() = compress(buffer.value, length, false)
private fun finalize() = compress(buffer.value, length, true)
override fun digestInto(destination: ByteArray, destinationOffset: Int) {
finalize()
h.toByteArray(order = LITTLE_ENDIAN).copyInto(destination, destinationOffset, endIndex = bytes)
reset()
}
private fun compress(block: ByteArray, t: Long, last: Boolean) {
block.copyInto(m)
for (i in 0..<8) v[i] = h[i]
for (i in 0..<8) v[i + 8] = initial[i]
v[12] = v[12] xor t.toInt()
v[13] = v[13] xor (t ushr 32).toInt()
if (last) v[14] = v[14].inv()
repeat(10) { r ->
val s = sigma[r]
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, 2, 6, 10, 14, m[s[4]], m[s[5]])
mix(v, 3, 7, 11, 15, m[s[6]], m[s[7]])
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, 2, 7, 8, 13, m[s[12]], m[s[13]])
mix(v, 3, 4, 9, 14, m[s[14]], m[s[15]])
}
for (i in 0..<8) {
h[i] = h[i] xor v[i] xor v[i + 8]
}
}
private fun mix(v: IntArray, a: Int, b: Int, c: Int, d: Int, x: Int, y: Int) {
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)
}
companion object {
private val initial = intArrayOf(
+0x6a09e667, -0x4498517b,
+0x3c6ef372, -0x5ab00ac6,
+0x510e527f, -0x64fa9774,
+0x1f83d9ab, +0x5be0cd19,
)
private val sigma = arrayOf(
@@ -34,88 +123,5 @@ class Blake2s(
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()
h[0] = h[0] xor (0x01010000U or bytes.toUInt())
var t = 0U
val l = value.size.toULong()
// padding
val paddedValue = buildList {
addAll(value)
if (isEmpty()) add(0x00U)
while (size % 64 != 0) {
add(0x00U)
}
}.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(
h: UIntArray,
m: UIntArray,
t: UInt,
last: Boolean,
) {
// initialization
val v = UIntArray(16)
for (i in 0..<8) v[i] = h[i]
for (i in 0..<8) v[i + 8] = initial[i]
v[12] = v[12] xor t
if (last) v[14] = v[14].inv()
// rounds
for (r in 0..<10) {
val s = sigma[r]
// column
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, 2, 6, 10, 14, m[s[4]], m[s[5]])
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, 1, 6, 11, 12, m[s[10]], m[s[11]])
mix(v, 2, 7, 8, 13, m[s[12]], m[s[13]])
mix(v, 3, 4, 9, 14, m[s[14]], m[s[15]])
}
// finalization
for (i in 0..7) {
h[i] = h[i] xor v[i] xor v[i + 8]
}
}
private fun mix(
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

@@ -1,92 +1,86 @@
package com.infendro.hash.keccak
import com.infendro.bytearray.ByteOrder.LITTLE_ENDIAN
import com.infendro.bytearray.toUByteArray
import com.infendro.bytearray.toULongArray
import com.infendro.bytes.ByteOrder.LITTLE_ENDIAN
import com.infendro.bytes.bytearray.copyInto
import com.infendro.bytes.long.copyInto
import com.infendro.hash.HashFunction
import kotlin.math.min
open class Keccak(
override val bytes: Int,
bytes: Int,
private val rate: Int,
private val domain: UByte,
) : HashFunction() {
private val domain: Byte,
) : HashFunction(bytes, rate) {
init {
if (bytes < 1) throw IllegalArgumentException()
if (rate !in 8..168) throw IllegalArgumentException()
require(bytes > 0)
require(rate in 8..192 step 8)
}
override val block: Int
get() = rate
private var state = LongArray(25)
private val rc = ulongArrayOf(
0x0000000000000001UL, 0x0000000000008082UL, 0x800000000000808aUL, 0x8000000080008000UL,
0x000000000000808bUL, 0x0000000080000001UL, 0x8000000080008081UL, 0x8000000000008009UL,
0x000000000000008aUL, 0x0000000000000088UL, 0x0000000080008009UL, 0x000000008000000aUL,
0x000000008000808bUL, 0x800000000000008bUL, 0x8000000000008089UL, 0x8000000000008003UL,
0x8000000000008002UL, 0x8000000000000080UL, 0x000000000000800aUL, 0x800000008000000aUL,
0x8000000080008081UL, 0x8000000000008080UL, 0x0000000080000001UL, 0x8000000080008008UL,
)
private val w = LongArray(block / 8)
private val b = LongArray(25)
private val c = LongArray(5)
private val d = LongArray(5)
private val rotation = arrayOf(
intArrayOf(0, 36, 3, 41, 18),
intArrayOf(1, 44, 10, 45, 2),
intArrayOf(62, 6, 43, 15, 61),
intArrayOf(28, 55, 25, 21, 56),
intArrayOf(27, 20, 39, 8, 14),
)
override fun hash(
value: UByteArray,
): UByteArray {
val state = ULongArray(25)
// padding
val paddedValue = buildList {
addAll(value)
add(domain)
while ((size % rate) != (rate - 1)) {
add(0x00U)
}
add(0x80U)
override fun reset() {
super.reset()
state.fill(0L)
}
// 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)
override fun process() {
absorb(buffer.value)
permute()
}
// squeeze
return buildList {
private fun finalize() {
buffer.append(domain)
if (buffer.free < 1) {
process()
buffer.reset()
}
buffer.jumpTo(block - 1)
buffer.append(0x80.toByte())
process()
}
override fun digestInto(destination: ByteArray, destinationOffset: Int) {
finalize()
squeeze(destination, destinationOffset)
reset()
}
private fun absorb(block: ByteArray) {
block.copyInto(w, order = LITTLE_ENDIAN)
for (i in w.indices) {
state[i] = state[i] xor w[i]
}
}
private fun squeeze(destination: ByteArray, destinationOffset: Int) {
val buffer = ByteArray(8)
val threshold = rate / 8
var consumed = 0
var i = 0
while (size < bytes) {
if (i == rate / 8) {
permute(state)
while (consumed < bytes) {
if (i == threshold) {
permute()
i = 0
}
addAll(
state[i++].toUByteArray(LITTLE_ENDIAN)
.sliceArray(0..<min(bytes - size, 8))
)
val length = minOf(bytes - consumed, 8)
state[i].copyInto(buffer, order = LITTLE_ENDIAN)
buffer.copyInto(destination, destinationOffset + consumed, endIndex = length)
consumed += length
i++
}
}.toUByteArray()
}
private fun permute(
a: ULongArray,
) {
val b = ULongArray(25)
val c = ULongArray(5)
val d = ULongArray(5)
private fun permute() = repeat(24) { round ->
val a = state
repeat(24) { round ->
// θ
for (x in 0..4) {
c[x] = a[x] xor a[x + 5] xor a[x + 10] xor a[x + 15] xor a[x + 20]
@@ -111,5 +105,23 @@ open class Keccak(
// ι
a[0] = a[0] xor rc[round]
}
companion object {
private val rc = longArrayOf(
+0x0000000000000001, +0x0000000000008082, -0x7fffffffffff7f76, -0x7fffffff7fff8000,
+0x000000000000808b, +0x0000000080000001, -0x7fffffff7fff7f7f, -0x7fffffffffff7ff7,
+0x000000000000008a, +0x0000000000000088, +0x0000000080008009, +0x000000008000000a,
+0x000000008000808b, -0x7fffffffffffff75, -0x7fffffffffff7f77, -0x7fffffffffff7ffd,
-0x7fffffffffff7ffe, -0x7fffffffffffff80, +0x000000000000800a, -0x7fffffff7ffffff6,
-0x7fffffff7fff7f7f, -0x7fffffffffff7f80, +0x0000000080000001, -0x7fffffff7fff7ff8,
)
private val rotation = arrayOf(
intArrayOf(0, 36, 3, 41, 18),
intArrayOf(1, 44, 10, 45, 2),
intArrayOf(62, 6, 43, 15, 61),
intArrayOf(28, 55, 25, 21, 56),
intArrayOf(27, 20, 39, 8, 14),
)
}
}

View File

@@ -2,4 +2,4 @@ package com.infendro.hash.keccak.sha3
import com.infendro.hash.keccak.Keccak
object `SHA3-224` : Keccak(28, 144, 0x06U)
class `SHA3-224` : Keccak(28, 144, 0x06)

View File

@@ -2,4 +2,4 @@ package com.infendro.hash.keccak.sha3
import com.infendro.hash.keccak.Keccak
object `SHA3-256` : Keccak(32, 136, 0x06U)
class `SHA3-256` : Keccak(32, 136, 0x06)

View File

@@ -2,4 +2,4 @@ package com.infendro.hash.keccak.sha3
import com.infendro.hash.keccak.Keccak
object `SHA3-384` : Keccak(48, 104, 0x06U)
class `SHA3-384` : Keccak(48, 104, 0x06)

View File

@@ -2,4 +2,4 @@ package com.infendro.hash.keccak.sha3
import com.infendro.hash.keccak.Keccak
object `SHA3-512` : Keccak(64, 72, 0x06U)
class `SHA3-512` : Keccak(64, 72, 0x06)

View File

@@ -2,6 +2,4 @@ package com.infendro.hash.keccak.shake
import com.infendro.hash.keccak.Keccak
class SHAKE128(
bytes: Int,
) : Keccak(bytes, 168, 0x1FU)
class SHAKE128(bytes: Int) : Keccak(bytes, 168, 0x1F)

View File

@@ -2,6 +2,4 @@ package com.infendro.hash.keccak.shake
import com.infendro.hash.keccak.Keccak
class SHAKE256(
bytes: Int,
) : Keccak(bytes, 136, 0x1FU)
class SHAKE256(bytes: Int) : Keccak(bytes, 136, 0x1F)

View File

@@ -1,96 +1,56 @@
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.hash.HashFunction
object MD5 : HashFunction() {
override val bytes: Int
get() = 16
class MD5 : HashFunction(16, 64) {
private val h = initial.copyOf()
override val block: Int
get() = 64
private val w = IntArray(16)
private val v = IntArray(4)
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,
)
private val c = uintArrayOf(
0xd76aa478U, 0xe8c7b756U, 0x242070dbU, 0xc1bdceeeU,
0xf57c0fafU, 0x4787c62aU, 0xa8304613U, 0xfd469501U,
0x698098d8U, 0x8b44f7afU, 0xffff5bb1U, 0x895cd7beU,
0x6b901122U, 0xfd987193U, 0xa679438eU, 0x49b40821U,
0xf61e2562U, 0xc040b340U, 0x265e5a51U, 0xe9b6c7aaU,
0xd62f105dU, 0x02441453U, 0xd8a1e681U, 0xe7d3fbc8U,
0x21e1cde6U, 0xc33707d6U, 0xf4d50d87U, 0x455a14edU,
0xa9e3e905U, 0xfcefa3f8U, 0x676f02d9U, 0x8d2a4c8aU,
0xfffa3942U, 0x8771f681U, 0x6d9d6122U, 0xfde5380cU,
0xa4beea44U, 0x4bdecfa9U, 0xf6bb4b60U, 0xbebfbc70U,
0x289b7ec6U, 0xeaa127faU, 0xd4ef3085U, 0x04881d05U,
0xd9d4d039U, 0xe6db99e5U, 0x1fa27cf8U, 0xc4ac5665U,
0xf4292244U, 0x432aff97U, 0xab9423a7U, 0xfc93a039U,
0x655b59c3U, 0x8f0ccc92U, 0xffeff47dU, 0x85845dd1U,
0x6fa87e4fU, 0xfe2ce6e0U, 0xa3014314U, 0x4e0811a1U,
0xf7537e82U, 0xbd3af235U, 0x2ad7d2bbU, 0xeb86d391U,
)
override fun hash(
value: UByteArray,
): UByteArray {
val h = initial.copyOf()
val l = value.size.toULong() * 8UL
// padding
val paddedValue = buildList {
addAll(value)
add(0x80U)
while (size % 64 != 56) {
add(0x00U)
}
addAll(l.toUByteArray(LITTLE_ENDIAN))
override fun reset() {
super.reset()
initial.copyInto(h)
}
// process
val blocks = paddedValue
.chunked(64) { it.toUByteArray() }
for (block in blocks) {
val w = block.toUIntArray(LITTLE_ENDIAN)
process(h, w)
override fun process() = process(buffer.value)
private fun finalize() {
buffer.append(0x80.toByte())
if (buffer.free < 8) {
process()
buffer.reset()
}
buffer.jumpTo(56)
buffer.append(length * 8, LITTLE_ENDIAN)
process()
}
return h.toUByteArray(LITTLE_ENDIAN)
override fun digestInto(destination: ByteArray, destinationOffset: Int) {
finalize()
h.copyInto(destination, destinationOffset, order = LITTLE_ENDIAN)
reset()
}
private fun process(
h: UIntArray,
w: UIntArray,
) {
val v = h.copyOf()
private fun process(block: ByteArray) {
block.copyInto(w, order = LITTLE_ENDIAN)
h.copyInto(v)
for (i in 0..<64) {
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]
@@ -100,8 +60,53 @@ object MD5 : HashFunction() {
v[1] += f.rotateLeft(shifts[i])
}
for (i in 0..3) {
for (i in 0..<4) {
h[i] += v[i]
}
}
companion object {
private val initial = intArrayOf(
+0x67452301, -0x10325477,
-0x67452302, +0x10325476,
)
private val c = intArrayOf(
-0x28955b88, -0x173848aa, +0x242070db, -0x3e423112,
-0x0a83f051, +0x4787c62a, -0x57cfb9ed, -0x02b96aff,
+0x698098d8, -0x74bb0851, -0x0000a44f, -0x76a32842,
+0x6b901122, -0x02678e6d, -0x5986bc72, +0x49b40821,
-0x09e1da9e, -0x3fbf4cc0, +0x265e5a51, -0x16493856,
-0x29d0efa3, +0x02441453, -0x275e197f, -0x182c0438,
+0x21e1cde6, -0x3cc8f82a, -0x0b2af279, +0x455a14ed,
-0x561c16fb, -0x03105c08, +0x676f02d9, -0x72d5b376,
-0x0005c6be, -0x788e097f, +0x6d9d6122, -0x021ac7f4,
-0x5b4115bc, +0x4bdecfa9, -0x0944b4a0, -0x41404390,
+0x289b7ec6, -0x155ed806, -0x2b10cf7b, +0x04881d05,
-0x262b2fc7, -0x1924661b, +0x1fa27cf8, -0x3b53a99b,
-0x0bd6ddbc, +0x432aff97, -0x546bdc59, -0x036c5fc7,
+0x655b59c3, -0x70f3336e, -0x00100b83, -0x7a7ba22f,
+0x6fa87e4f, -0x01d31920, -0x5cfebcec, +0x4e0811a1,
-0x08ac817e, -0x42c50dcb, +0x2ad7d2bb, -0x14792c6f,
)
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,
)
}
}

View File

@@ -1,75 +1,55 @@
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.hash.HashFunction
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 = uintArrayOf(
0x67452301U, 0xefcdaB89U,
0x98badcfeU, 0x10325476U,
0xc3d2e1f0U,
)
override fun hash(
value: UByteArray,
): UByteArray {
val h = initial.copyOf()
val l = value.size.toULong() * 8UL
// padding
val paddedValue = buildList {
addAll(value)
add(0x80U)
while (size % 64 != 56) {
add(0x00U)
}
addAll(l.toUByteArray())
override fun reset() {
super.reset()
initial.copyInto(h)
}
// process
val blocks = paddedValue
.chunked(64) { it.toUByteArray() }
for (block in blocks) {
val w = buildList {
addAll(block.toUIntArray())
override fun process() = process(buffer.value)
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 process(block: ByteArray) {
block.copyInto(w)
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)
w[i] = (w[i - 3] xor w[i - 8] xor w[i - 14] xor w[i - 16]).rotateLeft(1)
}
h.copyInto(v)
return h.toUByteArray()
}
private fun process(
h: UIntArray,
w: UIntArray,
) {
val v = h.copyOf()
for (i in 0..<80) {
repeat(80) { i ->
val f = when (i) {
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 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)
@@ -77,8 +57,21 @@ object SHA1 : HashFunction() {
v[0] = temp
}
for (i in 0..4) {
for (i in 0..<5) {
h[i] += v[i]
}
}
companion object {
private val initial = intArrayOf(
+0x67452301, -0x10325477,
-0x67452302, +0x10325476,
-0x3c2d1e10,
)
private val k = intArrayOf(
+0x5a827999, +0x6ed9eba1,
-0x70e44324, -0x359d3e2a,
)
}
}

View File

@@ -1,79 +1,55 @@
package com.infendro.hash.sha2
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.hash.HashFunction
import com.infendro.hash.sha2.`SHA-256`.Companion.c
object `SHA-224` : HashFunction() {
override val bytes: Int
get() = 28
class `SHA-224` : HashFunction(28, 64) {
private val h = initial.copyOf()
override val block: Int
get() = 64
private val w = IntArray(64)
private val v = IntArray(8)
private val initial = uintArrayOf(
0xc1059ed8U, 0x367cd507U,
0x3070dd17U, 0xf70e5939U,
0xffc00b31U, 0x68581511U,
0x64f98fa7U, 0xbefa4fa4U,
)
private val c = uintArrayOf(
0x428a2f98U, 0x71374491U, 0xb5c0fbcfU, 0xe9b5dba5U, 0x3956c25bU, 0x59f111f1U, 0x923f82a4U, 0xab1c5ed5U,
0xd807aa98U, 0x12835b01U, 0x243185beU, 0x550c7dc3U, 0x72be5d74U, 0x80deb1feU, 0x9bdc06a7U, 0xc19bf174U,
0xe49b69c1U, 0xefbe4786U, 0x0fc19dc6U, 0x240ca1ccU, 0x2de92c6fU, 0x4a7484aaU, 0x5cb0a9dcU, 0x76f988daU,
0x983e5152U, 0xa831c66dU, 0xb00327c8U, 0xbf597fc7U, 0xc6e00bf3U, 0xd5a79147U, 0x06ca6351U, 0x14292967U,
0x27b70a85U, 0x2e1b2138U, 0x4d2c6dfcU, 0x53380d13U, 0x650a7354U, 0x766a0abbU, 0x81c2c92eU, 0x92722c85U,
0xa2bfe8a1U, 0xa81a664bU, 0xc24b8b70U, 0xc76c51a3U, 0xd192e819U, 0xd6990624U, 0xf40e3585U, 0x106aa070U,
0x19a4c116U, 0x1e376c08U, 0x2748774cU, 0x34b0bcb5U, 0x391c0cb3U, 0x4ed8aa4aU, 0x5b9cca4fU, 0x682e6ff3U,
0x748f82eeU, 0x78a5636fU, 0x84c87814U, 0x8cc70208U, 0x90befffaU, 0xa4506cebU, 0xbef9a3f7U, 0xc67178f2U,
)
override fun hash(
value: UByteArray,
): UByteArray {
val h = initial.copyOf()
val l = value.size.toULong() * 8UL
// padding
val paddedValue = buildList {
addAll(value)
add(0x80U)
while (size % 64 != 56) {
add(0x00U)
}
addAll(l.toUByteArray())
override fun reset() {
super.reset()
initial.copyInto(h)
}
// process
val blocks = paddedValue
.chunked(64) { it.toUByteArray() }
for (block in blocks) {
val w = buildList {
addAll(block.toUIntArray())
override fun process() = process(buffer.value)
private fun finalize() {
buffer.append(0x80.toByte())
if (buffer.free < 8) {
process(buffer.value)
buffer.reset()
}
buffer.jumpTo(56)
buffer.append(length * 8)
process(buffer.value)
}
override fun digestInto(destination: ByteArray, destinationOffset: Int) {
finalize()
h.copyInto(destination, destinationOffset, endIndex = 7)
reset()
}
private fun process(block: ByteArray) {
block.copyInto(w)
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)
val s0 = w[i - 15].rotateRight(7) xor w[i - 15].rotateRight(18) xor (w[i - 15] ushr 3)
val s1 = w[i - 2].rotateRight(17) xor w[i - 2].rotateRight(19) xor (w[i - 2] ushr 10)
w[i] = (w[i - 16] + s0 + w[i - 7] + s1)
}
h.copyInto(v)
return h.sliceArray(0..6).toUByteArray()
}
private fun process(
h: UIntArray,
w: UIntArray,
) {
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 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 temp1 = v[7] + s1 + ch + this.c[i] + w[i]
val temp1 = v[7] + s1 + ch + c[i] + w[i]
val maj = (v[0] and v[1]) xor (v[0] and v[2]) xor (v[1] and v[2])
val temp2 = s0 + maj
@@ -87,8 +63,17 @@ object `SHA-224` : HashFunction() {
v[0] = temp1 + temp2
}
for (i in 0..7) {
for (i in 0..<8) {
h[i] += v[i]
}
}
companion object {
private val initial = intArrayOf(
-0x3efa6128, +0x367cd507,
+0x3070dd17, -0x08f1a6c7,
-0x003ff4cf, +0x68581511,
+0x64f98fa7, -0x4105b05c,
)
}
}

View File

@@ -1,79 +1,54 @@
package com.infendro.hash.sha2
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.hash.HashFunction
object `SHA-256` : HashFunction() {
override val bytes: Int
get() = 32
class `SHA-256` : HashFunction(32, 64) {
private val h = initial.copyOf()
override val block: Int
get() = 64
private val w = IntArray(64)
private val v = IntArray(8)
private val initial = uintArrayOf(
0x6a09e667U, 0xbb67ae85U,
0x3c6ef372U, 0xa54ff53aU,
0x510e527fU, 0x9b05688cU,
0x1f83d9abU, 0x5be0cd19U,
)
private val c = uintArrayOf(
0x428a2f98U, 0x71374491U, 0xb5c0fbcfU, 0xe9b5dba5U, 0x3956c25bU, 0x59f111f1U, 0x923f82a4U, 0xab1c5ed5U,
0xd807aa98U, 0x12835b01U, 0x243185beU, 0x550c7dc3U, 0x72be5d74U, 0x80deb1feU, 0x9bdc06a7U, 0xc19bf174U,
0xe49b69c1U, 0xefbe4786U, 0x0fc19dc6U, 0x240ca1ccU, 0x2de92c6fU, 0x4a7484aaU, 0x5cb0a9dcU, 0x76f988daU,
0x983e5152U, 0xa831c66dU, 0xb00327c8U, 0xbf597fc7U, 0xc6e00bf3U, 0xd5a79147U, 0x06ca6351U, 0x14292967U,
0x27b70a85U, 0x2e1b2138U, 0x4d2c6dfcU, 0x53380d13U, 0x650a7354U, 0x766a0abbU, 0x81c2c92eU, 0x92722c85U,
0xa2bfe8a1U, 0xa81a664bU, 0xc24b8b70U, 0xc76c51a3U, 0xd192e819U, 0xd6990624U, 0xf40e3585U, 0x106aa070U,
0x19a4c116U, 0x1e376c08U, 0x2748774cU, 0x34b0bcb5U, 0x391c0cb3U, 0x4ed8aa4aU, 0x5b9cca4fU, 0x682e6ff3U,
0x748f82eeU, 0x78a5636fU, 0x84c87814U, 0x8cc70208U, 0x90befffaU, 0xa4506cebU, 0xbef9a3f7U, 0xc67178f2U,
)
override fun hash(
value: UByteArray,
): UByteArray {
val h = initial.copyOf()
val l = value.size.toULong() * 8UL
// padding
val paddedValue = buildList {
addAll(value)
add(0x80U)
while (size % 64 != 56) {
add(0x00U)
}
addAll(l.toUByteArray())
override fun reset() {
super.reset()
initial.copyInto(h)
}
// process
val chunks = paddedValue
.chunked(64) { it.toUByteArray() }
for (chunk in chunks) {
val w = buildList {
addAll(chunk.toUIntArray())
override fun process() = process(buffer.value)
private fun finalize() {
buffer.append(0x80.toByte())
if (buffer.free < 8) {
process(buffer.value)
buffer.reset()
}
buffer.jumpTo(56)
buffer.append(length * 8)
process(buffer.value)
}
override fun digestInto(destination: ByteArray, destinationOffset: Int) {
finalize()
h.copyInto(destination, destinationOffset)
reset()
}
private fun process(block: ByteArray) {
block.copyInto(w)
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)
val s0 = w[i - 15].rotateRight(7) xor w[i - 15].rotateRight(18) xor (w[i - 15] ushr 3)
val s1 = w[i - 2].rotateRight(17) xor w[i - 2].rotateRight(19) xor (w[i - 2] ushr 10)
w[i] = (w[i - 16] + s0 + w[i - 7] + s1)
}
h.copyInto(v)
return h.toUByteArray()
}
private fun process(
h: UIntArray,
w: UIntArray,
) {
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 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 temp1 = v[7] + s1 + ch + this.c[i] + w[i]
val temp1 = v[7] + s1 + ch + c[i] + w[i]
val maj = (v[0] and v[1]) xor (v[0] and v[2]) xor (v[1] and v[2])
val temp2 = s0 + maj
@@ -87,8 +62,28 @@ object `SHA-256` : HashFunction() {
v[0] = temp1 + temp2
}
for (i in 0..7) {
for (i in 0..<8) {
h[i] += v[i]
}
}
companion object {
private val initial = intArrayOf(
+0x6a09e667, -0x4498517b,
+0x3c6ef372, -0x5ab00ac6,
+0x510e527f, -0x64fa9774,
+0x1f83d9ab, +0x5be0cd19,
)
internal val c = intArrayOf(
+0x428a2f98, +0x71374491, -0x4a3f0431, -0x164a245b, +0x3956c25b, +0x59f111f1, -0x6dc07d5c, -0x54e3a12b,
-0x27f85568, +0x12835b01, +0x243185be, +0x550c7dc3, +0x72be5d74, -0x7f214e02, -0x6423f959, -0x3e640e8c,
-0x1b64963f, -0x1041b87a, +0x0fc19dc6, +0x240ca1cc, +0x2de92c6f, +0x4a7484aa, +0x5cb0a9dc, +0x76f988da,
-0x67c1aeae, -0x57ce3993, -0x4ffcd838, -0x40a68039, -0x391ff40d, -0x2a586eb9, +0x06ca6351, +0x14292967,
+0x27b70a85, +0x2e1b2138, +0x4d2c6dfc, +0x53380d13, +0x650a7354, +0x766a0abb, -0x7e3d36d2, -0x6d8dd37b,
-0x5d40175f, -0x57e599b5, -0x3db47490, -0x3893ae5d, -0x2e6d17e7, -0x2966f9dc, -0x0bf1ca7b, +0x106aa070,
+0x19a4c116, +0x1e376c08, +0x2748774c, +0x34b0bcb5, +0x391c0cb3, +0x4ed8aa4a, +0x5b9cca4f, +0x682e6ff3,
+0x748f82ee, +0x78a5636f, -0x7b3787ec, -0x7338fdf8, -0x6f410006, -0x5baf9315, -0x41065c09, -0x398e870e,
)
}
}

View File

@@ -1,91 +1,55 @@
package com.infendro.hash.sha2
import com.infendro.bytearray.toUByteArray
import com.infendro.bytearray.toULongArray
import com.infendro.bytes.bytearray.copyInto
import com.infendro.bytes.longarray.copyInto
import com.infendro.hash.HashFunction
import com.infendro.hash.sha2.`SHA-512`.Companion.c
object `SHA-384` : HashFunction() {
override val bytes: Int
get() = 48
class `SHA-384` : HashFunction(48, 128) {
private val h = initial.copyOf()
override val block: Int
get() = 128
private val w = LongArray(80)
private val v = LongArray(8)
private val initial = ulongArrayOf(
0xcbbb9d5dc1059ed8UL, 0x629a292a367cd507UL,
0x9159015a3070dd17UL, 0x152fecd8f70e5939UL,
0x67332667ffc00b31UL, 0x8eb44a8768581511UL,
0xdb0c2e0d64f98fa7UL, 0x47b5481dbefa4fa4UL,
)
private val c = ulongArrayOf(
0x428a2f98d728ae22UL, 0x7137449123ef65cdUL, 0xb5c0fbcfec4d3b2fUL, 0xe9b5dba58189dbbcUL,
0x3956c25bf348b538UL, 0x59f111f1b605d019UL, 0x923f82a4af194f9bUL, 0xab1c5ed5da6d8118UL,
0xd807aa98a3030242UL, 0x12835b0145706fbeUL, 0x243185be4ee4b28cUL, 0x550c7dc3d5ffb4e2UL,
0x72be5d74f27b896fUL, 0x80deb1fe3b1696b1UL, 0x9bdc06a725c71235UL, 0xc19bf174cf692694UL,
0xe49b69c19ef14ad2UL, 0xefbe4786384f25e3UL, 0x0fc19dc68b8cd5b5UL, 0x240ca1cc77ac9c65UL,
0x2de92c6f592b0275UL, 0x4a7484aa6ea6e483UL, 0x5cb0a9dcbd41fbd4UL, 0x76f988da831153b5UL,
0x983e5152ee66dfabUL, 0xa831c66d2db43210UL, 0xb00327c898fb213fUL, 0xbf597fc7beef0ee4UL,
0xc6e00bf33da88fc2UL, 0xd5a79147930aa725UL, 0x06ca6351e003826fUL, 0x142929670a0e6e70UL,
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(
value: UByteArray,
): UByteArray {
val h = initial.copyOf()
val l = value.size.toULong() * 8UL
// padding
val paddedValue = buildList {
addAll(value)
add(0x80U)
while (size % 128 != 120) {
add(0x00U)
}
addAll(l.toUByteArray())
override fun reset() {
super.reset()
initial.copyInto(h)
}
// process
val blocks = paddedValue
.chunked(128) { it.toUByteArray() }
for (block in blocks) {
val w = buildList {
addAll(block.toULongArray())
override fun process() = process(buffer.value)
private fun finalize() {
buffer.append(0x80.toByte())
if (buffer.free < 16) {
process(buffer.value)
buffer.reset()
}
buffer.jumpTo(112)
buffer.append(length * 8)
process(buffer.value)
}
override fun digestInto(destination: ByteArray, destinationOffset: Int) {
finalize()
h.copyInto(destination, destinationOffset, endIndex = 6)
reset()
}
private fun process(block: ByteArray) {
block.copyInto(w)
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)
val s0 = w[i - 15].rotateRight(1) xor w[i - 15].rotateRight(8) xor (w[i - 15] ushr 7)
val s1 = w[i - 2].rotateRight(19) xor w[i - 2].rotateRight(61) xor (w[i - 2] ushr 6)
w[i] = (w[i - 16] + s0 + w[i - 7] + s1)
}
h.copyInto(v)
return h.sliceArray(0..5).toUByteArray()
}
private fun process(
h: ULongArray,
w: ULongArray,
) {
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 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 temp1 = v[7] + s1 + ch + this.c[i] + w[i]
val temp1 = v[7] + s1 + ch + c[i] + w[i]
val maj = (v[0] and v[1]) xor (v[0] and v[2]) xor (v[1] and v[2])
val temp2 = s0 + maj
@@ -99,8 +63,17 @@ object `SHA-384` : HashFunction() {
v[0] = temp1 + temp2
}
for (i in 0..7) {
for (i in 0..<8) {
h[i] += v[i]
}
}
companion object {
private val initial = longArrayOf(
-0x344462a23efa6128, +0x629a292a367cd507,
-0x6ea6fea5cf8f22e9, +0x152fecd8f70e5939,
+0x67332667ffc00b31, -0x714bb57897a7eaef,
-0x24f3d1f29b067059, +0x47b5481dbefa4fa4,
)
}
}

View File

@@ -1,91 +1,54 @@
package com.infendro.hash.sha2
import com.infendro.bytearray.toUByteArray
import com.infendro.bytearray.toULongArray
import com.infendro.bytes.bytearray.copyInto
import com.infendro.bytes.longarray.copyInto
import com.infendro.hash.HashFunction
object `SHA-512` : HashFunction() {
override val bytes: Int
get() = 64
class `SHA-512` : HashFunction(64, 128) {
private val h = initial.copyOf()
override val block: Int
get() = 128
private val w = LongArray(80)
private val v = LongArray(8)
private val initial = ulongArrayOf(
0x6a09e667f3bcc908UL, 0xbb67ae8584caa73bUL,
0x3c6ef372fe94f82bUL, 0xa54ff53a5f1d36f1UL,
0x510e527fade682d1UL, 0x9b05688c2b3e6c1fUL,
0x1f83d9abfb41bd6bUL, 0x5be0cd19137e2179UL,
)
private val c = ulongArrayOf(
0x428a2f98d728ae22UL, 0x7137449123ef65cdUL, 0xb5c0fbcfec4d3b2fUL, 0xe9b5dba58189dbbcUL,
0x3956c25bf348b538UL, 0x59f111f1b605d019UL, 0x923f82a4af194f9bUL, 0xab1c5ed5da6d8118UL,
0xd807aa98a3030242UL, 0x12835b0145706fbeUL, 0x243185be4ee4b28cUL, 0x550c7dc3d5ffb4e2UL,
0x72be5d74f27b896fUL, 0x80deb1fe3b1696b1UL, 0x9bdc06a725c71235UL, 0xc19bf174cf692694UL,
0xe49b69c19ef14ad2UL, 0xefbe4786384f25e3UL, 0x0fc19dc68b8cd5b5UL, 0x240ca1cc77ac9c65UL,
0x2de92c6f592b0275UL, 0x4a7484aa6ea6e483UL, 0x5cb0a9dcbd41fbd4UL, 0x76f988da831153b5UL,
0x983e5152ee66dfabUL, 0xa831c66d2db43210UL, 0xb00327c898fb213fUL, 0xbf597fc7beef0ee4UL,
0xc6e00bf33da88fc2UL, 0xd5a79147930aa725UL, 0x06ca6351e003826fUL, 0x142929670a0e6e70UL,
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(
value: UByteArray,
): UByteArray {
val h = initial.copyOf()
val l = value.size.toULong() * 8UL
// padding
val paddedValue = buildList {
addAll(value)
add(0x80U)
while (size % 128 != 120) {
add(0x00U)
}
addAll(l.toUByteArray())
override fun reset() {
super.reset()
initial.copyInto(h)
}
// process
val blocks = paddedValue
.chunked(128) { it.toUByteArray() }
for (block in blocks) {
val w = buildList {
addAll(block.toULongArray())
override fun process() = process(buffer.value)
private fun finalize() {
buffer.append(0x80.toByte())
if (buffer.free < 16) {
process(buffer.value)
buffer.reset()
}
buffer.jumpTo(112)
buffer.append(length * 8)
process(buffer.value)
}
override fun digestInto(destination: ByteArray, destinationOffset: Int) {
finalize()
h.copyInto(destination, destinationOffset)
reset()
}
private fun process(block: ByteArray) {
block.copyInto(w)
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)
val s0 = w[i - 15].rotateRight(1) xor w[i - 15].rotateRight(8) xor (w[i - 15] ushr 7)
val s1 = w[i - 2].rotateRight(19) xor w[i - 2].rotateRight(61) xor (w[i - 2] ushr 6)
w[i] = (w[i - 16] + s0 + w[i - 7] + s1)
}
h.copyInto(v)
return h.toUByteArray()
}
private fun process(
h: ULongArray,
w: ULongArray,
) {
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 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 temp1 = v[7] + s1 + ch + this.c[i] + w[i]
val temp1 = v[7] + s1 + ch + c[i] + w[i]
val maj = (v[0] and v[1]) xor (v[0] and v[2]) xor (v[1] and v[2])
val temp2 = s0 + maj
@@ -99,8 +62,40 @@ object `SHA-512` : HashFunction() {
v[0] = temp1 + temp2
}
for (i in 0..7) {
for (i in 0..<8) {
h[i] += v[i]
}
}
companion object {
private val initial = longArrayOf(
+0x6a09e667f3bcc908, -0x4498517a7b3558c5,
+0x3c6ef372fe94f82b, -0x5ab00ac5a0e2c90f,
+0x510e527fade682d1, -0x64fa9773d4c193e1,
+0x1f83d9abfb41bd6b, +0x5be0cd19137e2179,
)
internal val c = longArrayOf(
+0x428a2f98d728ae22, +0x7137449123ef65cd, -0x4a3f043013b2c4d1, -0x164a245a7e762444,
+0x3956c25bf348b538, +0x59f111f1b605d019, -0x6dc07d5b50e6b065, -0x54e3a12a25927ee8,
-0x27f855675cfcfdbe, +0x12835b0145706fbe, +0x243185be4ee4b28c, +0x550c7dc3d5ffb4e2,
+0x72be5d74f27b896f, -0x7f214e01c4e9694f, -0x6423f958da38edcb, -0x3e640e8b3096d96c,
-0x1b64963e610eb52e, -0x1041b879c7b0da1d, +0x0fc19dc68b8cd5b5, +0x240ca1cc77ac9c65,
+0x2de92c6f592b0275, +0x4a7484aa6ea6e483, +0x5cb0a9dcbd41fbd4, +0x76f988da831153b5,
-0x67c1aead11992055, -0x57ce3992d24bcdf0, -0x4ffcd8376704dec1, -0x40a680384110f11c,
-0x391ff40cc257703e, -0x2a586eb86cf558db, +0x06ca6351e003826f, +0x142929670a0e6e70,
+0x27b70a8546d22ffc, +0x2e1b21385c26c926, +0x4d2c6dfc5ac42aed, +0x53380d139d95b3df,
+0x650a73548baf63de, +0x766a0abb3c77b2a8, -0x7e3d36d1b812511a, -0x6d8dd37aeb7dcac5,
-0x5d40175eb30efc9c, -0x57e599b443bdcfff, -0x3db4748f2f07686f, -0x3893ae5cf9ab41d0,
-0x2e6d17e62910ade8, -0x2966f9dbaa9a56f0, -0x0bf1ca7aa88edfd6, +0x106aa07032bbd1b8,
+0x19a4c116b8d2d0c8, +0x1e376c085141ab53, +0x2748774cdf8eeb99, +0x34b0bcb5e19b48a8,
+0x391c0cb3c5c95a63, +0x4ed8aa4ae3418acb, +0x5b9cca4f7763e373, +0x682e6ff3d6b2b8a3,
+0x748f82ee5defb2fc, +0x78a5636f43172f60, -0x7b3787eb5e0f548e, -0x7338fdf7e59bc614,
-0x6f410005dc9ce1d8, -0x5baf9314217d4217, -0x41065c084d3986eb, -0x398e870d1c8dacd5,
-0x35d8c13115d99e64, -0x2e794738de3f3df9, -0x15258229321f14e2, -0x0a82b08011912e88,
+0x06f067aa72176fba, +0x0a637dc5a2c898a6, +0x113f9804bef90dae, +0x1b710b35131c471b,
+0x28db77f523047d84, +0x32caab7b40c72493, +0x3c9ebe0a15c9bebc, +0x431d67c49c100d4c,
+0x4cc5d4becb3e42b6, +0x597f299cfc657e2a, +0x5fcb6fab3ad6faec, +0x6c44198c4a475817,
)
}
}

View File

@@ -4,8 +4,8 @@ import kotlin.test.Test
import kotlin.test.assertContentEquals
import kotlin.test.assertEquals
class `Blake-224 Test` {
val function = `Blake-224`
class `Blake-224_Test` {
val function = `Blake-224`()
@Test
fun `bytes and block`() {
@@ -16,52 +16,37 @@ class `Blake-224 Test` {
@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)
val expected = byteArrayOf(
+0x7d, -0x3b, +0x31, +0x3b, +0x1c, +0x04, +0x51, +0x2a,
+0x17, +0x4b, -0x2a, +0x50, +0x3b, -0x77, +0x60, +0x7a,
-0x14, -0x42, -0x20, -0x70, +0x3d, +0x40, -0x58, -0x5b,
+0x69, -0x37, +0x4e, -0x13,
)
val actual = function.hash(ByteArray(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)
val expected = byteArrayOf(
+0x45, +0x04, -0x35, +0x03, +0x14, -0x05, +0x2a, +0x4f,
+0x7a, +0x69, +0x2e, +0x69, +0x6e, +0x48, +0x79, +0x12,
-0x02, +0x3f, +0x24, +0x68, -0x02, +0x31, +0x2c, +0x73,
-0x5b, +0x27, -0x72, -0x3b,
)
val actual = function.hash(ByteArray(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)
val expected = byteArrayOf(
-0x0b, -0x56, +0x00, -0x23, +0x1c, -0x48, +0x47, -0x1d,
+0x14, +0x03, +0x72, -0x51, +0x7b, +0x5c, +0x46, -0x4c,
-0x78, -0x73, -0x7e, -0x38, -0x40, -0x57, +0x17, -0x6f,
+0x3c, -0x05, +0x5d, +0x04,
)
val actual = function.hash(ByteArray(72))
assertContentEquals(expected, actual)
}
}

View File

@@ -4,8 +4,8 @@ import kotlin.test.Test
import kotlin.test.assertContentEquals
import kotlin.test.assertEquals
class `Blake-256 Test` {
val function = `Blake-256`
class `Blake-256_Test` {
val function = `Blake-256`()
@Test
fun `bytes and block`() {
@@ -16,55 +16,37 @@ class `Blake-256 Test` {
@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)
val expected = byteArrayOf(
+0x71, +0x6f, +0x6e, -0x7a, +0x3f, +0x74, +0x4b, -0x66,
-0x3e, +0x2c, -0x69, -0x14, +0x7b, +0x76, -0x16, +0x5f,
+0x59, +0x08, -0x44, +0x5b, +0x2f, +0x67, -0x3a, +0x15,
+0x10, -0x41, -0x3c, +0x75, +0x13, -0x7c, -0x16, +0x7a,
)
val actual = function.hash(ByteArray(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)
val expected = byteArrayOf(
+0x0c, -0x18, -0x2c, -0x11, +0x4d, -0x29, -0x33, -0x73,
+0x62, -0x21, -0x22, -0x27, -0x2c, -0x13, -0x50, -0x59,
+0x74, -0x52, +0x6a, +0x41, -0x6e, -0x66, +0x74, -0x26,
+0x23, +0x10, -0x62, -0x71, +0x11, +0x13, -0x64, -0x79,
)
val actual = function.hash(ByteArray(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)
val expected = byteArrayOf(
-0x2c, +0x19, -0x46, -0x2d, +0x2d, +0x50, +0x4f, -0x49,
-0x2c, +0x4d, +0x46, +0x0c, +0x42, -0x3b, +0x59, +0x3f,
-0x1b, +0x44, -0x06, +0x4c, +0x13, +0x5d, -0x14, +0x31,
-0x1e, +0x1b, -0x27, -0x55, -0x24, -0x3e, +0x2d, +0x41,
)
val actual = function.hash(ByteArray(72))
assertContentEquals(expected, actual)
}
}

View File

@@ -4,8 +4,8 @@ import kotlin.test.Test
import kotlin.test.assertContentEquals
import kotlin.test.assertEquals
class `Blake-384 Test` {
val function = `Blake-384`
class `Blake-384_Test` {
val function = `Blake-384`()
@Test
fun `bytes and block`() {
@@ -16,67 +16,43 @@ class `Blake-384 Test` {
@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)
val expected = byteArrayOf(
-0x3a, -0x35, -0x28, -0x64, -0x6e, +0x6a, -0x4b, +0x25,
-0x3e, +0x42, -0x1a, +0x62, +0x1f, +0x2f, +0x5f, -0x59,
+0x3a, -0x5c, -0x51, -0x1d, -0x27, -0x1e, +0x4a, -0x13,
+0x72, +0x7f, -0x56, -0x53, -0x2a, -0x51, +0x38, -0x4a,
+0x20, -0x43, -0x4a, +0x23, -0x23, +0x2b, +0x47, -0x78,
-0x4f, -0x38, +0x08, +0x69, -0x7c, -0x51, -0x79, +0x06,
)
val actual = function.hash(ByteArray(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)
val expected = byteArrayOf(
+0x10, +0x28, +0x1f, +0x67, -0x1f, +0x35, -0x17, +0x0a,
-0x18, -0x18, -0x7e, +0x25, +0x1a, +0x35, +0x55, +0x10,
-0x59, +0x19, +0x36, +0x7a, -0x29, +0x02, +0x27, -0x4f,
+0x37, +0x34, +0x3e, +0x1b, -0x3f, +0x22, +0x01, +0x5c,
+0x29, +0x39, +0x1e, -0x7b, +0x45, -0x4b, +0x27, +0x2d,
+0x13, -0x59, -0x3e, -0x79, -0x63, -0x5d, -0x28, +0x07,
)
val actual = function.hash(ByteArray(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)
val expected = byteArrayOf(
+0x0b, -0x68, +0x45, -0x23, +0x42, -0x6b, +0x66, -0x33,
-0x55, +0x77, +0x2b, -0x5f, -0x6b, -0x2e, +0x71, -0x11,
-0x02, +0x2d, +0x02, +0x11, -0x0f, +0x69, -0x6f, -0x29,
+0x66, -0x46, +0x74, -0x6c, +0x47, -0x3b, -0x33, -0x1b,
+0x69, +0x78, +0x0b, +0x2d, -0x56, +0x66, -0x3c, -0x4e,
+0x24, -0x5e, -0x14, +0x2e, +0x5d, +0x09, +0x17, +0x4c,
)
val actual = function.hash(ByteArray(144))
assertContentEquals(expected, actual)
}
}

View File

@@ -4,8 +4,8 @@ import kotlin.test.Test
import kotlin.test.assertContentEquals
import kotlin.test.assertEquals
class `Blake-512 Test` {
val function = `Blake-512`
class `Blake-512_Test` {
val function = `Blake-512`()
@Test
fun `bytes and block`() {
@@ -16,79 +16,49 @@ class `Blake-512 Test` {
@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)
val expected = byteArrayOf(
-0x58, -0x31, -0x45, -0x29, +0x37, +0x26, +0x06, +0x2d,
-0x10, -0x3a, -0x7a, +0x4d, -0x26, +0x65, -0x22, -0x02,
+0x58, -0x11, +0x0c, -0x3b, +0x2a, +0x56, +0x25, +0x09,
+0x0f, -0x5f, +0x76, +0x01, -0x1f, -0x12, -0x33, +0x1b,
+0x62, -0x72, -0x6c, -0x0d, -0x6a, -0x52, +0x40, +0x2a,
+0x00, -0x54, -0x37, -0x16, -0x49, +0x7b, +0x4d, +0x4c,
+0x2e, -0x7b, +0x2a, -0x56, -0x5e, +0x5a, +0x63, +0x6d,
-0x80, -0x51, +0x3f, -0x39, -0x6f, +0x3e, -0x0b, -0x48,
)
val actual = function.hash(ByteArray(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)
val expected = byteArrayOf(
-0x69, -0x6a, +0x15, -0x79, -0x0a, -0x27, +0x70, -0x06,
-0x46, +0x6d, +0x24, +0x78, +0x04, +0x5d, -0x1a, -0x2f,
-0x06, -0x43, +0x09, -0x4a, +0x1a, -0x1b, +0x09, +0x32,
+0x05, +0x4d, +0x52, -0x44, +0x29, -0x2d, +0x1b, -0x1c,
-0x01, -0x6f, +0x02, -0x47, -0x0a, -0x62, +0x2b, -0x43,
-0x48, +0x3b, -0x1f, +0x3d, +0x4b, -0x64, +0x06, +0x09,
+0x1e, +0x5f, -0x60, -0x4c, -0x75, -0x30, -0x7f, -0x4a,
+0x34, +0x05, -0x75, -0x20, -0x14, +0x49, -0x42, -0x4d,
)
val actual = function.hash(ByteArray(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)
val expected = byteArrayOf(
+0x31, +0x37, +0x17, -0x2a, +0x08, -0x17, -0x31, +0x75,
-0x73, -0x35, +0x1e, -0x50, -0x10, -0x3d, -0x31, -0x61,
-0x3f, +0x50, -0x4e, -0x2b, +0x00, -0x05, +0x33, -0x0b,
+0x1c, +0x52, -0x51, -0x37, -0x63, +0x35, -0x76, +0x2f,
+0x13, +0x74, -0x48, -0x5d, -0x75, -0x46, +0x79, +0x74,
-0x19, -0x0a, -0x11, +0x79, -0x36, -0x4f, +0x6f, +0x22,
-0x32, +0x1e, +0x64, -0x63, +0x6e, +0x01, -0x53, -0x6b,
-0x77, -0x3e, +0x13, +0x04, +0x5d, +0x54, +0x5d, -0x22,
)
val actual = function.hash(ByteArray(144))
assertContentEquals(expected, actual)
}
}

View File

@@ -4,7 +4,7 @@ import kotlin.test.Test
import kotlin.test.assertContentEquals
import kotlin.test.assertEquals
class `Blake2b-384 Test` {
class `Blake2b-384_Test` {
val function = Blake2b(48)
@Test
@@ -16,23 +16,15 @@ class `Blake2b-384 Test` {
@Test
fun `empty bytearray`() {
val expected = ubyteArrayOf(
0xb3U, 0x28U, 0x11U, 0x42U,
0x33U, 0x77U, 0xf5U, 0x2dU,
0x78U, 0x62U, 0x28U, 0x6eU,
0xe1U, 0xa7U, 0x2eU, 0xe5U,
0x40U, 0x52U, 0x43U, 0x80U,
0xfdU, 0xa1U, 0x72U, 0x4aU,
0x6fU, 0x25U, 0xd7U, 0x97U,
0x8cU, 0x6fU, 0xd3U, 0x24U,
0x4aU, 0x6cU, 0xafU, 0x04U,
0x98U, 0x81U, 0x26U, 0x73U,
0xc5U, 0xe0U, 0x5eU, 0xf5U,
0x83U, 0x82U, 0x51U, 0x00U,
)
val actual = function.hash(
UByteArray(0)
val expected = byteArrayOf(
-0x4d, +0x28, +0x11, +0x42, +0x33, +0x77, -0x0b, +0x2d,
+0x78, +0x62, +0x28, +0x6e, -0x1f, -0x59, +0x2e, -0x1b,
+0x40, +0x52, +0x43, -0x80, -0x03, -0x5f, +0x72, +0x4a,
+0x6f, +0x25, -0x29, -0x69, -0x74, +0x6f, -0x2d, +0x24,
+0x4a, +0x6c, -0x51, +0x04, -0x68, -0x7f, +0x26, +0x73,
-0x3b, -0x20, +0x5e, -0x0b, -0x7d, -0x7e, +0x51, +0x00,
)
val actual = function.hash(ByteArray(0))
assertContentEquals(expected, actual)
}
}

View File

@@ -4,7 +4,7 @@ import kotlin.test.Test
import kotlin.test.assertContentEquals
import kotlin.test.assertEquals
class `Blake2b-512 Test` {
class `Blake2b-512_Test` {
val function = Blake2b(64)
@Test
@@ -16,27 +16,17 @@ class `Blake2b-512 Test` {
@Test
fun `empty bytearray`() {
val expected = ubyteArrayOf(
0x78U, 0x6aU, 0x02U, 0xf7U,
0x42U, 0x01U, 0x59U, 0x03U,
0xc6U, 0xc6U, 0xfdU, 0x85U,
0x25U, 0x52U, 0xd2U, 0x72U,
0x91U, 0x2fU, 0x47U, 0x40U,
0xe1U, 0x58U, 0x47U, 0x61U,
0x8aU, 0x86U, 0xe2U, 0x17U,
0xf7U, 0x1fU, 0x54U, 0x19U,
0xd2U, 0x5eU, 0x10U, 0x31U,
0xafU, 0xeeU, 0x58U, 0x53U,
0x13U, 0x89U, 0x64U, 0x44U,
0x93U, 0x4eU, 0xb0U, 0x4bU,
0x90U, 0x3aU, 0x68U, 0x5bU,
0x14U, 0x48U, 0xb7U, 0x55U,
0xd5U, 0x6fU, 0x70U, 0x1aU,
0xfeU, 0x9bU, 0xe2U, 0xceU,
)
val actual = function.hash(
UByteArray(0)
val expected = byteArrayOf(
+0x78, +0x6a, +0x02, -0x09, +0x42, +0x01, +0x59, +0x03,
-0x3a, -0x3a, -0x03, -0x7b, +0x25, +0x52, -0x2e, +0x72,
-0x6f, +0x2f, +0x47, +0x40, -0x1f, +0x58, +0x47, +0x61,
-0x76, -0x7a, -0x1e, +0x17, -0x09, +0x1f, +0x54, +0x19,
-0x2e, +0x5e, +0x10, +0x31, -0x51, -0x12, +0x58, +0x53,
+0x13, -0x77, +0x64, +0x44, -0x6d, +0x4e, -0x50, +0x4b,
-0x70, +0x3a, +0x68, +0x5b, +0x14, +0x48, -0x49, +0x55,
-0x2b, +0x6f, +0x70, +0x1a, -0x02, -0x65, -0x1e, -0x32,
)
val actual = function.hash(ByteArray(0))
assertContentEquals(expected, actual)
}
}

View File

@@ -4,7 +4,7 @@ import kotlin.test.Test
import kotlin.test.assertContentEquals
import kotlin.test.assertEquals
class `Blake2s-224 Test` {
class `Blake2s-224_Test` {
val function = Blake2s(28)
@Test
@@ -16,18 +16,13 @@ class `Blake2s-224 Test` {
@Test
fun `empty bytearray`() {
val expected = ubyteArrayOf(
0x1fU, 0xa1U, 0x29U, 0x1eU,
0x65U, 0x24U, 0x8bU, 0x37U,
0xb3U, 0x43U, 0x34U, 0x75U,
0xb2U, 0xa0U, 0xddU, 0x63U,
0xd5U, 0x4aU, 0x11U, 0xecU,
0xc4U, 0xe3U, 0xe0U, 0x34U,
0xe7U, 0xbcU, 0x1eU, 0xf4U,
)
val actual = function.hash(
UByteArray(0)
val expected = byteArrayOf(
+0x1f, -0x5f, +0x29, +0x1e, +0x65, +0x24, -0x75, +0x37,
-0x4d, +0x43, +0x34, +0x75, -0x4e, -0x60, -0x23, +0x63,
-0x2b, +0x4a, +0x11, -0x14, -0x3c, -0x1d, -0x20, +0x34,
-0x19, -0x44, +0x1e, -0x0c,
)
val actual = function.hash(ByteArray(0))
assertContentEquals(expected, actual)
}
}

View File

@@ -4,7 +4,7 @@ import kotlin.test.Test
import kotlin.test.assertContentEquals
import kotlin.test.assertEquals
class `Blake2s-256 Test` {
class `Blake2s-256_Test` {
val function = Blake2s(32)
@Test
@@ -16,19 +16,13 @@ class `Blake2s-256 Test` {
@Test
fun `empty bytearray`() {
val expected = ubyteArrayOf(
0x69U, 0x21U, 0x7aU, 0x30U,
0x79U, 0x90U, 0x80U, 0x94U,
0xe1U, 0x11U, 0x21U, 0xd0U,
0x42U, 0x35U, 0x4aU, 0x7cU,
0x1fU, 0x55U, 0xb6U, 0x48U,
0x2cU, 0xa1U, 0xa5U, 0x1eU,
0x1bU, 0x25U, 0x0dU, 0xfdU,
0x1eU, 0xd0U, 0xeeU, 0xf9U,
)
val actual = function.hash(
UByteArray(0)
val expected = byteArrayOf(
+0x69, +0x21, +0x7a, +0x30, +0x79, -0x70, -0x80, -0x6c,
-0x1f, +0x11, +0x21, -0x30, +0x42, +0x35, +0x4a, +0x7c,
+0x1f, +0x55, -0x4a, +0x48, +0x2c, -0x5f, -0x5b, +0x1e,
+0x1b, +0x25, +0x0d, -0x03, +0x1e, -0x30, -0x12, -0x07,
)
val actual = function.hash(ByteArray(0))
assertContentEquals(expected, actual)
}
}

View File

@@ -4,8 +4,8 @@ import kotlin.test.Test
import kotlin.test.assertContentEquals
import kotlin.test.assertEquals
class `SHA3-224 Test` {
val function = `SHA3-224`
class `SHA3-224_Test` {
val function = `SHA3-224`()
@Test
fun `bytes and block`() {
@@ -16,18 +16,13 @@ class `SHA3-224 Test` {
@Test
fun `empty bytearray`() {
val expected = ubyteArrayOf(
0x6bU, 0x4eU, 0x03U, 0x42U,
0x36U, 0x67U, 0xdbU, 0xb7U,
0x3bU, 0x6eU, 0x15U, 0x45U,
0x4fU, 0x0eU, 0xb1U, 0xabU,
0xd4U, 0x59U, 0x7fU, 0x9aU,
0x1bU, 0x07U, 0x8eU, 0x3fU,
0x5bU, 0x5aU, 0x6bU, 0xc7U,
)
val actual = function.hash(
ubyteArrayOf()
val expected = byteArrayOf(
+0x6b, +0x4e, +0x03, +0x42, +0x36, +0x67, -0x25, -0x49,
+0x3b, +0x6e, +0x15, +0x45, +0x4f, +0x0e, -0x4f, -0x55,
-0x2c, +0x59, +0x7f, -0x66, +0x1b, +0x07, -0x72, +0x3f,
+0x5b, +0x5a, +0x6b, -0x39,
)
val actual = function.hash(ByteArray(0))
assertContentEquals(expected, actual)
}
}

View File

@@ -4,8 +4,8 @@ import kotlin.test.Test
import kotlin.test.assertContentEquals
import kotlin.test.assertEquals
class `SHA3-256 Test` {
val function = `SHA3-256`
class `SHA3-256_Test` {
val function = `SHA3-256`()
@Test
fun `bytes and block`() {
@@ -16,19 +16,13 @@ class `SHA3-256 Test` {
@Test
fun `empty bytearray`() {
val expected = ubyteArrayOf(
0xa7U, 0xffU, 0xc6U, 0xf8U,
0xbfU, 0x1eU, 0xd7U, 0x66U,
0x51U, 0xc1U, 0x47U, 0x56U,
0xa0U, 0x61U, 0xd6U, 0x62U,
0xf5U, 0x80U, 0xffU, 0x4dU,
0xe4U, 0x3bU, 0x49U, 0xfaU,
0x82U, 0xd8U, 0x0aU, 0x4bU,
0x80U, 0xf8U, 0x43U, 0x4aU,
)
val actual = function.hash(
ubyteArrayOf()
val expected = byteArrayOf(
-0x59, -0x01, -0x3a, -0x08, -0x41, +0x1e, -0x29, +0x66,
+0x51, -0x3f, +0x47, +0x56, -0x60, +0x61, -0x2a, +0x62,
-0x0b, -0x80, -0x01, +0x4d, -0x1c, +0x3b, +0x49, -0x06,
-0x7e, -0x28, +0x0a, +0x4b, -0x80, -0x08, +0x43, +0x4a,
)
val actual = function.hash(ByteArray(0))
assertContentEquals(expected, actual)
}
}

View File

@@ -4,8 +4,8 @@ import kotlin.test.Test
import kotlin.test.assertContentEquals
import kotlin.test.assertEquals
class `SHA3-384 Test` {
val function = `SHA3-384`
class `SHA3-384_Test` {
val function = `SHA3-384`()
@Test
fun `bytes and block`() {
@@ -16,23 +16,15 @@ class `SHA3-384 Test` {
@Test
fun `empty bytearray`() {
val expected = ubyteArrayOf(
0x0cU, 0x63U, 0xa7U, 0x5bU,
0x84U, 0x5eU, 0x4fU, 0x7dU,
0x01U, 0x10U, 0x7dU, 0x85U,
0x2eU, 0x4cU, 0x24U, 0x85U,
0xc5U, 0x1aU, 0x50U, 0xaaU,
0xaaU, 0x94U, 0xfcU, 0x61U,
0x99U, 0x5eU, 0x71U, 0xbbU,
0xeeU, 0x98U, 0x3aU, 0x2aU,
0xc3U, 0x71U, 0x38U, 0x31U,
0x26U, 0x4aU, 0xdbU, 0x47U,
0xfbU, 0x6bU, 0xd1U, 0xe0U,
0x58U, 0xd5U, 0xf0U, 0x04U,
)
val actual = function.hash(
ubyteArrayOf()
val expected = byteArrayOf(
+0x0c, +0x63, -0x59, +0x5b, -0x7c, +0x5e, +0x4f, +0x7d,
+0x01, +0x10, +0x7d, -0x7b, +0x2e, +0x4c, +0x24, -0x7b,
-0x3b, +0x1a, +0x50, -0x56, -0x56, -0x6c, -0x04, +0x61,
-0x67, +0x5e, +0x71, -0x45, -0x12, -0x68, +0x3a, +0x2a,
-0x3d, +0x71, +0x38, +0x31, +0x26, +0x4a, -0x25, +0x47,
-0x05, +0x6b, -0x2f, -0x20, +0x58, -0x2b, -0x10, +0x04,
)
val actual = function.hash(ByteArray(0))
assertContentEquals(expected, actual)
}
}

View File

@@ -4,8 +4,8 @@ import kotlin.test.Test
import kotlin.test.assertContentEquals
import kotlin.test.assertEquals
class `SHA3-512 Test` {
val function = `SHA3-512`
class `SHA3-512_Test` {
val function = `SHA3-512`()
@Test
fun `bytes and block`() {
@@ -16,27 +16,17 @@ class `SHA3-512 Test` {
@Test
fun `empty bytearray`() {
val expected = ubyteArrayOf(
0xa6U, 0x9fU, 0x73U, 0xccU,
0xa2U, 0x3aU, 0x9aU, 0xc5U,
0xc8U, 0xb5U, 0x67U, 0xdcU,
0x18U, 0x5aU, 0x75U, 0x6eU,
0x97U, 0xc9U, 0x82U, 0x16U,
0x4fU, 0xe2U, 0x58U, 0x59U,
0xe0U, 0xd1U, 0xdcU, 0xc1U,
0x47U, 0x5cU, 0x80U, 0xa6U,
0x15U, 0xb2U, 0x12U, 0x3aU,
0xf1U, 0xf5U, 0xf9U, 0x4cU,
0x11U, 0xe3U, 0xe9U, 0x40U,
0x2cU, 0x3aU, 0xc5U, 0x58U,
0xf5U, 0x00U, 0x19U, 0x9dU,
0x95U, 0xb6U, 0xd3U, 0xe3U,
0x01U, 0x75U, 0x85U, 0x86U,
0x28U, 0x1dU, 0xcdU, 0x26U,
)
val actual = function.hash(
ubyteArrayOf()
val expected = byteArrayOf(
-0x5a, -0x61, +0x73, -0x34, -0x5e, +0x3a, -0x66, -0x3b,
-0x38, -0x4b, +0x67, -0x24, +0x18, +0x5a, +0x75, +0x6e,
-0x69, -0x37, -0x7e, +0x16, +0x4f, -0x1e, +0x58, +0x59,
-0x20, -0x2f, -0x24, -0x3f, +0x47, +0x5c, -0x80, -0x5a,
+0x15, -0x4e, +0x12, +0x3a, -0x0f, -0x0b, -0x07, +0x4c,
+0x11, -0x1d, -0x17, +0x40, +0x2c, +0x3a, -0x3b, +0x58,
-0x0b, +0x00, +0x19, -0x63, -0x6b, -0x4a, -0x2d, -0x1d,
+0x01, +0x75, -0x7b, -0x7a, +0x28, +0x1d, -0x33, +0x26,
)
val actual = function.hash(ByteArray(0))
assertContentEquals(expected, actual)
}
}

View File

@@ -4,7 +4,7 @@ import kotlin.test.Test
import kotlin.test.assertContentEquals
import kotlin.test.assertEquals
class `SHAKE128 Test` {
class SHAKE128_Test {
val function = SHAKE128(32)
@Test
@@ -16,19 +16,13 @@ class `SHAKE128 Test` {
@Test
fun `empty bytearray`() {
val expected = ubyteArrayOf(
0x7fU, 0x9cU, 0x2bU, 0xa4U,
0xe8U, 0x8fU, 0x82U, 0x7dU,
0x61U, 0x60U, 0x45U, 0x50U,
0x76U, 0x05U, 0x85U, 0x3eU,
0xd7U, 0x3bU, 0x80U, 0x93U,
0xf6U, 0xefU, 0xbcU, 0x88U,
0xebU, 0x1aU, 0x6eU, 0xacU,
0xfaU, 0x66U, 0xefU, 0x26U,
)
val actual = function.hash(
ubyteArrayOf()
val expected = byteArrayOf(
+0x7f, -0x64, +0x2b, -0x5c, -0x18, -0x71, -0x7e, +0x7d,
+0x61, +0x60, +0x45, +0x50, +0x76, +0x05, -0x7b, +0x3e,
-0x29, +0x3b, -0x80, -0x6d, -0x0a, -0x11, -0x44, -0x78,
-0x15, +0x1a, +0x6e, -0x54, -0x06, +0x66, -0x11, +0x26,
)
val actual = function.hash(ByteArray(0))
assertContentEquals(expected, actual)
}
}

View File

@@ -4,7 +4,7 @@ import kotlin.test.Test
import kotlin.test.assertContentEquals
import kotlin.test.assertEquals
class `SHAKE256 Test` {
class SHAKE256_Test {
val function = SHAKE256(64)
@Test
@@ -16,27 +16,17 @@ class `SHAKE256 Test` {
@Test
fun `empty bytearray`() {
val expected = ubyteArrayOf(
0x46U, 0xb9U, 0xddU, 0x2bU,
0x0bU, 0xa8U, 0x8dU, 0x13U,
0x23U, 0x3bU, 0x3fU, 0xebU,
0x74U, 0x3eU, 0xebU, 0x24U,
0x3fU, 0xcdU, 0x52U, 0xeaU,
0x62U, 0xb8U, 0x1bU, 0x82U,
0xb5U, 0x0cU, 0x27U, 0x64U,
0x6eU, 0xd5U, 0x76U, 0x2fU,
0xd7U, 0x5dU, 0xc4U, 0xddU,
0xd8U, 0xc0U, 0xf2U, 0x00U,
0xcbU, 0x05U, 0x01U, 0x9dU,
0x67U, 0xb5U, 0x92U, 0xf6U,
0xfcU, 0x82U, 0x1cU, 0x49U,
0x47U, 0x9aU, 0xb4U, 0x86U,
0x40U, 0x29U, 0x2eU, 0xacU,
0xb3U, 0xb7U, 0xc4U, 0xbeU,
)
val actual = function.hash(
ubyteArrayOf()
val expected = byteArrayOf(
+0x46, -0x47, -0x23, +0x2b, +0x0b, -0x58, -0x73, +0x13,
+0x23, +0x3b, +0x3f, -0x15, +0x74, +0x3e, -0x15, +0x24,
+0x3f, -0x33, +0x52, -0x16, +0x62, -0x48, +0x1b, -0x7e,
-0x4b, +0x0c, +0x27, +0x64, +0x6e, -0x2b, +0x76, +0x2f,
-0x29, +0x5d, -0x3c, -0x23, -0x28, -0x40, -0x0e, +0x00,
-0x35, +0x05, +0x01, -0x63, +0x67, -0x4b, -0x6e, -0x0a,
-0x04, -0x7e, +0x1c, +0x49, +0x47, -0x66, -0x4c, -0x7a,
+0x40, +0x29, +0x2e, -0x54, -0x4d, -0x49, -0x3c, -0x42,
)
val actual = function.hash(ByteArray(0))
assertContentEquals(expected, actual)
}
}

View File

@@ -4,8 +4,8 @@ import kotlin.test.Test
import kotlin.test.assertContentEquals
import kotlin.test.assertEquals
class `MD5 Test` {
val function = MD5
class MD5_Test {
val function = MD5()
@Test
fun `bytes and block`() {
@@ -16,15 +16,11 @@ class `MD5 Test` {
@Test
fun `empty bytearray`() {
val expected = ubyteArrayOf(
0xd4U, 0x1dU, 0x8cU, 0xd9U,
0x8fU, 0x00U, 0xb2U, 0x04U,
0xe9U, 0x80U, 0x09U, 0x98U,
0xecU, 0xf8U, 0x42U, 0x7eU,
)
val actual = function.hash(
ubyteArrayOf()
val expected = byteArrayOf(
-0x2c, +0x1d, -0x74, -0x27, -0x71, +0x00, -0x4e, +0x04,
-0x17, -0x80, +0x09, -0x68, -0x14, -0x08, +0x42, +0x7e,
)
val actual = function.hash(ByteArray(0))
assertContentEquals(expected, actual)
}
}

View File

@@ -4,8 +4,8 @@ import kotlin.test.Test
import kotlin.test.assertContentEquals
import kotlin.test.assertEquals
class `SHA1 Test` {
val function = SHA1
class SHA1_Test {
val function = SHA1()
@Test
fun `bytes and block`() {
@@ -16,16 +16,12 @@ class `SHA1 Test` {
@Test
fun `empty bytearray`() {
val expected = ubyteArrayOf(
0xdaU, 0x39U, 0xa3U, 0xeeU,
0x5eU, 0x6bU, 0x4bU, 0x0dU,
0x32U, 0x55U, 0xbfU, 0xefU,
0x95U, 0x60U, 0x18U, 0x90U,
0xafU, 0xd8U, 0x07U, 0x09U,
)
val actual = function.hash(
ubyteArrayOf()
val expected = byteArrayOf(
-0x26, +0x39, -0x5d, -0x12, +0x5e, +0x6b, +0x4b, +0x0d,
+0x32, +0x55, -0x41, -0x11, -0x6b, +0x60, +0x18, -0x70,
-0x51, -0x28, +0x07, +0x09,
)
val actual = function.hash(ByteArray(0))
assertContentEquals(expected, actual)
}
}

View File

@@ -4,8 +4,8 @@ import kotlin.test.Test
import kotlin.test.assertContentEquals
import kotlin.test.assertEquals
class `SHA-224 Test` {
val function = `SHA-224`
class `SHA-224_Test` {
val function = `SHA-224`()
@Test
fun `bytes and block`() {
@@ -16,18 +16,13 @@ class `SHA-224 Test` {
@Test
fun `empty bytearray`() {
val expected = ubyteArrayOf(
0xd1U, 0x4aU, 0x02U, 0x8cU,
0x2aU, 0x3aU, 0x2bU, 0xc9U,
0x47U, 0x61U, 0x02U, 0xbbU,
0x28U, 0x82U, 0x34U, 0xc4U,
0x15U, 0xa2U, 0xb0U, 0x1fU,
0x82U, 0x8eU, 0xa6U, 0x2aU,
0xc5U, 0xb3U, 0xe4U, 0x2fU,
)
val actual = function.hash(
ubyteArrayOf()
val expected = byteArrayOf(
-0x2f, +0x4a, +0x02, -0x74, +0x2a, +0x3a, +0x2b, -0x37,
+0x47, +0x61, +0x02, -0x45, +0x28, -0x7e, +0x34, -0x3c,
+0x15, -0x5e, -0x50, +0x1f, -0x7e, -0x72, -0x5a, +0x2a,
-0x3b, -0x4d, -0x1c, +0x2f,
)
val actual = function.hash(ByteArray(0))
assertContentEquals(expected, actual)
}
}

View File

@@ -4,8 +4,8 @@ import kotlin.test.Test
import kotlin.test.assertContentEquals
import kotlin.test.assertEquals
class `SHA-256 Test` {
val function = `SHA-256`
class `SHA-256_Test` {
val function = `SHA-256`()
@Test
fun `bytes and block`() {
@@ -16,19 +16,13 @@ class `SHA-256 Test` {
@Test
fun `empty bytearray`() {
val expected = ubyteArrayOf(
0xe3U, 0xb0U, 0xc4U, 0x42U,
0x98U, 0xfcU, 0x1cU, 0x14U,
0x9aU, 0xfbU, 0xf4U, 0xc8U,
0x99U, 0x6fU, 0xb9U, 0x24U,
0x27U, 0xaeU, 0x41U, 0xe4U,
0x64U, 0x9bU, 0x93U, 0x4cU,
0xa4U, 0x95U, 0x99U, 0x1bU,
0x78U, 0x52U, 0xb8U, 0x55U,
)
val actual = function.hash(
ubyteArrayOf()
val expected = byteArrayOf(
-0x1d, -0x50, -0x3c, +0x42, -0x68, -0x04, +0x1c, +0x14,
-0x66, -0x05, -0x0c, -0x38, -0x67, +0x6f, -0x47, +0x24,
+0x27, -0x52, +0x41, -0x1c, +0x64, -0x65, -0x6d, +0x4c,
-0x5c, -0x6b, -0x67, +0x1b, +0x78, +0x52, -0x48, +0x55,
)
val actual = function.hash(ByteArray(0))
assertContentEquals(expected, actual)
}
}

View File

@@ -4,8 +4,8 @@ import kotlin.test.Test
import kotlin.test.assertContentEquals
import kotlin.test.assertEquals
class `SHA-384 Test` {
val function = `SHA-384`
class `SHA-384_Test` {
val function = `SHA-384`()
@Test
fun `bytes and block`() {
@@ -16,23 +16,15 @@ class `SHA-384 Test` {
@Test
fun `empty bytearray`() {
val expected = ubyteArrayOf(
0x38U, 0xb0U, 0x60U, 0xa7U,
0x51U, 0xacU, 0x96U, 0x38U,
0x4cU, 0xd9U, 0x32U, 0x7eU,
0xb1U, 0xb1U, 0xe3U, 0x6aU,
0x21U, 0xfdU, 0xb7U, 0x11U,
0x14U, 0xbeU, 0x07U, 0x43U,
0x4cU, 0x0cU, 0xc7U, 0xbfU,
0x63U, 0xf6U, 0xe1U, 0xdaU,
0x27U, 0x4eU, 0xdeU, 0xbfU,
0xe7U, 0x6fU, 0x65U, 0xfbU,
0xd5U, 0x1aU, 0xd2U, 0xf1U,
0x48U, 0x98U, 0xb9U, 0x5bU,
)
val actual = function.hash(
ubyteArrayOf()
val expected = byteArrayOf(
+0x38, -0x50, +0x60, -0x59, +0x51, -0x54, -0x6a, +0x38,
+0x4c, -0x27, +0x32, +0x7e, -0x4f, -0x4f, -0x1d, +0x6a,
+0x21, -0x03, -0x49, +0x11, +0x14, -0x42, +0x07, +0x43,
+0x4c, +0x0c, -0x39, -0x41, +0x63, -0x0a, -0x1f, -0x26,
+0x27, +0x4e, -0x22, -0x41, -0x19, +0x6f, +0x65, -0x05,
-0x2b, +0x1a, -0x2e, -0x0f, +0x48, -0x68, -0x47, +0x5b,
)
val actual = function.hash(ByteArray(0))
assertContentEquals(expected, actual)
}
}

View File

@@ -4,8 +4,8 @@ import kotlin.test.Test
import kotlin.test.assertContentEquals
import kotlin.test.assertEquals
class `SHA-512 Test` {
val function = `SHA-512`
class `SHA-512_Test` {
val function = `SHA-512`()
@Test
fun `bytes and block`() {
@@ -16,27 +16,17 @@ class `SHA-512 Test` {
@Test
fun `empty bytearray`() {
val expected = ubyteArrayOf(
0xcfU, 0x83U, 0xe1U, 0x35U,
0x7eU, 0xefU, 0xb8U, 0xbdU,
0xf1U, 0x54U, 0x28U, 0x50U,
0xd6U, 0x6dU, 0x80U, 0x07U,
0xd6U, 0x20U, 0xe4U, 0x05U,
0x0bU, 0x57U, 0x15U, 0xdcU,
0x83U, 0xf4U, 0xa9U, 0x21U,
0xd3U, 0x6cU, 0xe9U, 0xceU,
0x47U, 0xd0U, 0xd1U, 0x3cU,
0x5dU, 0x85U, 0xf2U, 0xb0U,
0xffU, 0x83U, 0x18U, 0xd2U,
0x87U, 0x7eU, 0xecU, 0x2fU,
0x63U, 0xb9U, 0x31U, 0xbdU,
0x47U, 0x41U, 0x7aU, 0x81U,
0xa5U, 0x38U, 0x32U, 0x7aU,
0xf9U, 0x27U, 0xdaU, 0x3eU,
)
val actual = function.hash(
ubyteArrayOf()
val expected = byteArrayOf(
-0x31, -0x7d, -0x1f, +0x35, +0x7e, -0x11, -0x48, -0x43,
-0x0f, +0x54, +0x28, +0x50, -0x2a, +0x6d, -0x80, +0x07,
-0x2a, +0x20, -0x1c, +0x05, +0x0b, +0x57, +0x15, -0x24,
-0x7d, -0x0c, -0x57, +0x21, -0x2d, +0x6c, -0x17, -0x32,
+0x47, -0x30, -0x2f, +0x3c, +0x5d, -0x7b, -0x0e, -0x50,
-0x01, -0x7d, +0x18, -0x2e, -0x79, +0x7e, -0x14, +0x2f,
+0x63, -0x47, +0x31, -0x43, +0x47, +0x41, +0x7a, -0x7f,
-0x5b, +0x38, +0x32, +0x7a, -0x07, +0x27, -0x26, +0x3e,
)
val actual = function.hash(ByteArray(0))
assertContentEquals(expected, actual)
}
}