diff --git a/benchmarks/build.gradle.kts b/benchmarks/build.gradle.kts index 3702060..acfc163 100644 --- a/benchmarks/build.gradle.kts +++ b/benchmarks/build.gradle.kts @@ -56,11 +56,13 @@ kmpConfiguration { implementation(libs.benchmark.runtime) implementation(libs.kotlincrypto.bitops.bits) implementation(libs.kotlincrypto.bitops.endian) + implementation(libs.kotlincrypto.hash.blake2) implementation(libs.kotlincrypto.hash.md) implementation(libs.kotlincrypto.hash.sha1) implementation(libs.kotlincrypto.hash.sha2) implementation(libs.kotlincrypto.hash.sha3) implementation(libs.kotlincrypto.sponges.keccak) + implementation(project(":library:blake2")) implementation(project(":library:hmac:hmac-md")) implementation(project(":library:hmac:hmac-sha1")) implementation(project(":library:hmac:hmac-sha2")) diff --git a/benchmarks/src/commonMain/kotlin/org/kotlincrypto/macs/benchmarks/BLAKE2Ops.kt b/benchmarks/src/commonMain/kotlin/org/kotlincrypto/macs/benchmarks/BLAKE2Ops.kt new file mode 100644 index 0000000..0888cb3 --- /dev/null +++ b/benchmarks/src/commonMain/kotlin/org/kotlincrypto/macs/benchmarks/BLAKE2Ops.kt @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2024 Matthew Nelson + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +@file:Suppress("SpellCheckingInspection", "unused", "ClassName") + +package org.kotlincrypto.macs.benchmarks + +import kotlinx.benchmark.* +import org.kotlincrypto.core.mac.Mac +import org.kotlincrypto.macs.blake2.BLAKE2b +import org.kotlincrypto.macs.blake2.BLAKE2s + +@State(Scope.Benchmark) +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(BenchmarkTimeUnit.NANOSECONDS) +@Warmup(iterations = ITERATIONS, time = TIME_WARMUP) +@Measurement(iterations = ITERATIONS, time = TIME_MEASURE) +open class BLAKE2b_512Benchmark: MacBenchmarkBase() { + override val m: Mac = BLAKE2b(key, 512) +} + +@State(Scope.Benchmark) +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(BenchmarkTimeUnit.NANOSECONDS) +@Warmup(iterations = ITERATIONS, time = TIME_WARMUP) +@Measurement(iterations = ITERATIONS, time = TIME_MEASURE) +open class BLAKE2s_256Benchmark: MacBenchmarkBase(keyLength = 30) { + override val m: Mac = BLAKE2s(key, 256) +} diff --git a/benchmarks/src/commonMain/kotlin/org/kotlincrypto/macs/benchmarks/BenchmarkBase.kt b/benchmarks/src/commonMain/kotlin/org/kotlincrypto/macs/benchmarks/BenchmarkBase.kt index 265b488..6b19919 100644 --- a/benchmarks/src/commonMain/kotlin/org/kotlincrypto/macs/benchmarks/BenchmarkBase.kt +++ b/benchmarks/src/commonMain/kotlin/org/kotlincrypto/macs/benchmarks/BenchmarkBase.kt @@ -26,9 +26,9 @@ const val ITERATIONS = 5 const val TIME_WARMUP = 2 const val TIME_MEASURE = 4 -abstract class MacBenchmarkBase { +abstract class MacBenchmarkBase(keyLength: Int = 50) { - protected val key = Random.Default.nextBytes(50) + protected val key = Random.Default.nextBytes(keyLength) protected abstract val m: Mac private val bytes by lazy { Random.Default.nextBytes((m.macLength() * 2) + 10) } diff --git a/benchmarks/src/commonMain/kotlin/org/kotlincrypto/macs/benchmarks/HmacSHA2Opts.kt b/benchmarks/src/commonMain/kotlin/org/kotlincrypto/macs/benchmarks/HmacSHA2Ops.kt similarity index 100% rename from benchmarks/src/commonMain/kotlin/org/kotlincrypto/macs/benchmarks/HmacSHA2Opts.kt rename to benchmarks/src/commonMain/kotlin/org/kotlincrypto/macs/benchmarks/HmacSHA2Ops.kt diff --git a/benchmarks/src/commonMain/kotlin/org/kotlincrypto/macs/benchmarks/HmacSHA3Opts.kt b/benchmarks/src/commonMain/kotlin/org/kotlincrypto/macs/benchmarks/HmacSHA3Ops.kt similarity index 100% rename from benchmarks/src/commonMain/kotlin/org/kotlincrypto/macs/benchmarks/HmacSHA3Opts.kt rename to benchmarks/src/commonMain/kotlin/org/kotlincrypto/macs/benchmarks/HmacSHA3Ops.kt diff --git a/benchmarks/src/commonMain/kotlin/org/kotlincrypto/macs/benchmarks/KmacOpts.kt b/benchmarks/src/commonMain/kotlin/org/kotlincrypto/macs/benchmarks/KmacOps.kt similarity index 100% rename from benchmarks/src/commonMain/kotlin/org/kotlincrypto/macs/benchmarks/KmacOpts.kt rename to benchmarks/src/commonMain/kotlin/org/kotlincrypto/macs/benchmarks/KmacOps.kt diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 6c349e1..a5040b8 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -25,6 +25,7 @@ gradle-publish-maven = { module = "com.vanniktech:gradle-maven-publish-plugin", kotlincrypto-core-digest = { module = "org.kotlincrypto.core:digest", version.ref = "kotlincrypto-core" } kotlincrypto-core-mac = { module = "org.kotlincrypto.core:mac", version.ref = "kotlincrypto-core" } kotlincrypto-core-xof = { module = "org.kotlincrypto.core:xof", version.ref = "kotlincrypto-core" } +kotlincrypto-hash-blake2 = { module = "org.kotlincrypto.hash:blake2", version.ref = "kotlincrypto-hash" } kotlincrypto-hash-md = { module = "org.kotlincrypto.hash:md", version.ref = "kotlincrypto-hash" } kotlincrypto-hash-sha1 = { module = "org.kotlincrypto.hash:sha1", version.ref = "kotlincrypto-hash" } kotlincrypto-hash-sha2 = { module = "org.kotlincrypto.hash:sha2", version.ref = "kotlincrypto-hash" } diff --git a/library/blake2/.gitignore b/library/blake2/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/library/blake2/.gitignore @@ -0,0 +1 @@ +/build diff --git a/library/blake2/api/blake2.api b/library/blake2/api/blake2.api new file mode 100644 index 0000000..f1dd422 --- /dev/null +++ b/library/blake2/api/blake2.api @@ -0,0 +1,23 @@ +public abstract class org/kotlincrypto/macs/blake2/BLAKE2Mac : org/kotlincrypto/core/mac/Mac { + public synthetic fun (Lorg/kotlincrypto/macs/blake2/BLAKE2Mac$Engine;Lkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (Lorg/kotlincrypto/macs/blake2/BLAKE2Mac;Lkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun ([BI[BLorg/kotlincrypto/hash/blake2/BLAKE2Digest$KeyedHashFactory;Lkotlin/jvm/internal/DefaultConstructorMarker;)V + public abstract fun copy ()Lorg/kotlincrypto/macs/blake2/BLAKE2Mac; +} + +public final class org/kotlincrypto/macs/blake2/BLAKE2b : org/kotlincrypto/macs/blake2/BLAKE2Mac { + public fun ([BI)V + public fun ([BI[B)V + public synthetic fun copy ()Ljava/lang/Object; + public synthetic fun copy ()Lorg/kotlincrypto/macs/blake2/BLAKE2Mac; + public fun copy ()Lorg/kotlincrypto/macs/blake2/BLAKE2b; +} + +public final class org/kotlincrypto/macs/blake2/BLAKE2s : org/kotlincrypto/macs/blake2/BLAKE2Mac { + public fun ([BI)V + public fun ([BI[B)V + public synthetic fun copy ()Ljava/lang/Object; + public synthetic fun copy ()Lorg/kotlincrypto/macs/blake2/BLAKE2Mac; + public fun copy ()Lorg/kotlincrypto/macs/blake2/BLAKE2s; +} + diff --git a/library/blake2/api/blake2.klib.api b/library/blake2/api/blake2.klib.api new file mode 100644 index 0000000..d519ecf --- /dev/null +++ b/library/blake2/api/blake2.klib.api @@ -0,0 +1,28 @@ +// Klib ABI Dump +// Targets: [androidNativeArm32, androidNativeArm64, androidNativeX64, androidNativeX86, iosArm64, iosSimulatorArm64, iosX64, js, linuxArm64, linuxX64, macosArm64, macosX64, mingwX64, tvosArm64, tvosSimulatorArm64, tvosX64, wasmJs, wasmWasi, watchosArm32, watchosArm64, watchosDeviceArm64, watchosSimulatorArm64, watchosX64] +// Rendering settings: +// - Signature version: 2 +// - Show manifest properties: true +// - Show declarations: true + +// Library unique name: +final class org.kotlincrypto.macs.blake2/BLAKE2b : org.kotlincrypto.macs.blake2/BLAKE2Mac { // org.kotlincrypto.macs.blake2/BLAKE2b|null[0] + constructor (kotlin/ByteArray, kotlin/Int) // org.kotlincrypto.macs.blake2/BLAKE2b.|(kotlin.ByteArray;kotlin.Int){}[0] + constructor (kotlin/ByteArray, kotlin/Int, kotlin/ByteArray?) // org.kotlincrypto.macs.blake2/BLAKE2b.|(kotlin.ByteArray;kotlin.Int;kotlin.ByteArray?){}[0] + + final fun copy(): org.kotlincrypto.macs.blake2/BLAKE2b // org.kotlincrypto.macs.blake2/BLAKE2b.copy|copy(){}[0] +} + +final class org.kotlincrypto.macs.blake2/BLAKE2s : org.kotlincrypto.macs.blake2/BLAKE2Mac { // org.kotlincrypto.macs.blake2/BLAKE2s|null[0] + constructor (kotlin/ByteArray, kotlin/Int) // org.kotlincrypto.macs.blake2/BLAKE2s.|(kotlin.ByteArray;kotlin.Int){}[0] + constructor (kotlin/ByteArray, kotlin/Int, kotlin/ByteArray?) // org.kotlincrypto.macs.blake2/BLAKE2s.|(kotlin.ByteArray;kotlin.Int;kotlin.ByteArray?){}[0] + + final fun copy(): org.kotlincrypto.macs.blake2/BLAKE2s // org.kotlincrypto.macs.blake2/BLAKE2s.copy|copy(){}[0] +} + +sealed class org.kotlincrypto.macs.blake2/BLAKE2Mac : org.kotlincrypto.core.mac/Mac { // org.kotlincrypto.macs.blake2/BLAKE2Mac|null[0] + constructor (kotlin/ByteArray, kotlin/Int, kotlin/ByteArray?, org.kotlincrypto.hash.blake2/BLAKE2Digest.KeyedHashFactory<*>) // org.kotlincrypto.macs.blake2/BLAKE2Mac.|(kotlin.ByteArray;kotlin.Int;kotlin.ByteArray?;org.kotlincrypto.hash.blake2.BLAKE2Digest.KeyedHashFactory<*>){}[0] + constructor (org.kotlincrypto.macs.blake2/BLAKE2Mac) // org.kotlincrypto.macs.blake2/BLAKE2Mac.|(org.kotlincrypto.macs.blake2.BLAKE2Mac){}[0] + + abstract fun copy(): org.kotlincrypto.macs.blake2/BLAKE2Mac // org.kotlincrypto.macs.blake2/BLAKE2Mac.copy|copy(){}[0] +} diff --git a/library/blake2/build.gradle.kts b/library/blake2/build.gradle.kts new file mode 100644 index 0000000..a751cf1 --- /dev/null +++ b/library/blake2/build.gradle.kts @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025 Matthew Nelson + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +plugins { + id("configuration") + id("bom-include") +} + +kmpConfiguration { + configureShared(java9ModuleName = "org.kotlincrypto.macs.blake2", publish = true) { + common { + sourceSetMain { + dependencies { + implementation(libs.kotlincrypto.hash.blake2) + api(libs.kotlincrypto.core.mac) + } + } + sourceSetTest { + dependencies { + implementation(project(":tools:testing")) + } + } + } + } +} diff --git a/library/blake2/gradle.properties b/library/blake2/gradle.properties new file mode 100644 index 0000000..9864488 --- /dev/null +++ b/library/blake2/gradle.properties @@ -0,0 +1,16 @@ +# Copyright (c) 2025 Matthew Nelson +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +POM_ARTIFACT_ID=blake2 +POM_NAME=KotlinCrypto MACs BLAKE2b, BLAKE2s +POM_DESCRIPTION=MACs for BLAKE2b, BLAKE2s diff --git a/library/blake2/src/commonMain/kotlin/org/kotlincrypto/macs/blake2/BLAKE2Mac.kt b/library/blake2/src/commonMain/kotlin/org/kotlincrypto/macs/blake2/BLAKE2Mac.kt new file mode 100644 index 0000000..6e9568f --- /dev/null +++ b/library/blake2/src/commonMain/kotlin/org/kotlincrypto/macs/blake2/BLAKE2Mac.kt @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2025 Matthew Nelson + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +package org.kotlincrypto.macs.blake2 + +import org.kotlincrypto.core.Algorithm +import org.kotlincrypto.core.InternalKotlinCryptoApi +import org.kotlincrypto.core.mac.Mac +import org.kotlincrypto.hash.blake2.BLAKE2Digest + +/** + * Core abstraction for BLAKE2 Keyed Hashing in the form of Message Authentication + * + * Code implementations: + * - [BLAKE2b] + * - [BLAKE2s] + * */ +public sealed class BLAKE2Mac: Mac { + + @Throws(IllegalArgumentException::class) + protected constructor( + key: ByteArray, + bitStrength: Int, + personalization: ByteArray?, + factory: BLAKE2Digest.KeyedHashFactory<*>, + ): this(Engine(key, bitStrength, personalization, factory)) + + protected constructor(other: BLAKE2Mac): super(other) + + private constructor(engine: Engine): super(engine.algorithm(), engine) + + public abstract override fun copy(): BLAKE2Mac + + @OptIn(InternalKotlinCryptoApi::class) + private class Engine: Mac.Engine, Algorithm { + + private val bitStrength: Int + private val keyBlock: ByteArray + private val personalization: ByteArray? + private val factory: BLAKE2Digest.KeyedHashFactory<*> + private var digest: BLAKE2Digest + + @Throws(IllegalArgumentException::class) + constructor( + key: ByteArray, + bitStrength: Int, + personalization: ByteArray?, + factory: BLAKE2Digest.KeyedHashFactory<*>, + ): super(key) { + this.bitStrength = bitStrength + this.personalization = personalization?.copyOf() + this.digest = factory.keyedHashInstance( + bitStrength = bitStrength, + keyLength = key.size, + salt = null, + personalization = this.personalization, + ) + this.factory = factory + this.keyBlock = key.copyOf(this.digest.blockSize()) + this.digest.update(this.keyBlock) + } + + private constructor(other: Engine): super(other) { + this.bitStrength = other.bitStrength + this.keyBlock = other.keyBlock.copyOf() + this.personalization = other.personalization + this.factory = other.factory + this.digest = other.digest.copy() + } + + override fun copy(): Engine = Engine(this) + + override fun update(input: Byte) { digest.update(input) } + + override fun update(input: ByteArray, offset: Int, len: Int) { digest.update(input, offset, len) } + + override fun doFinal(): ByteArray = digest.digest() + + override fun reset() { + digest.reset() + digest.update(keyBlock) + } + + override fun reset(newKey: ByteArray) { + val oldDigest = digest + this.digest = factory.keyedHashInstance( + bitStrength = bitStrength, + keyLength = newKey.size, + salt = null, + personalization = personalization, + ) + + newKey.copyInto(keyBlock) + keyBlock.fill(0, newKey.size) + digest.update(keyBlock) + oldDigest.reset() + } + + override fun algorithm(): String = digest.algorithm() + + override fun macLength(): Int = digest.digestLength() + } +} diff --git a/library/blake2/src/commonMain/kotlin/org/kotlincrypto/macs/blake2/BLAKE2b.kt b/library/blake2/src/commonMain/kotlin/org/kotlincrypto/macs/blake2/BLAKE2b.kt new file mode 100644 index 0000000..4b0fe43 --- /dev/null +++ b/library/blake2/src/commonMain/kotlin/org/kotlincrypto/macs/blake2/BLAKE2b.kt @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2025 Matthew Nelson + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +package org.kotlincrypto.macs.blake2 + +/** + * BLAKE2b Keyed Hashing implementation + * + * https://datatracker.ietf.org/doc/rfc7693/ + * */ +public class BLAKE2b: BLAKE2Mac { + + /** + * Creates a new instance of [BLAKE2b]. + * + * @param [key] The secret to use for authenticating data. + * @param [bitStrength] The number of bits returned when [doFinal] is invoked. + * + * @throws [IllegalArgumentException] when: + * - [key] size is less than 1 + * - [key] size is greater than 64 + * - [bitStrength] is less than 8 + * - [bitStrength] is greater than 512 + * - [bitStrength] is not a factor of 8 + * */ + public constructor( + key: ByteArray, + bitStrength: Int, + ): this(key, bitStrength, null) + + /** + * Creates a new instance of [BLAKE2b]. + * + * @param [key] The secret to use for authenticating data. + * @param [bitStrength] The number of bits returned when [doFinal] is invoked. + * @param [personalization] A user selected customization bit string to define a variant + * of the function. When no customization is desired, [personalization] must be set to a + * null value. Must be 16 bytes in length, or null. + * + * @throws [IllegalArgumentException] when: + * - [key] size is less than 1 + * - [key] size is greater than 64 + * - [bitStrength] is less than 8 + * - [bitStrength] is greater than 512 + * - [bitStrength] is not a factor of 8 + * - [personalization] is non-null and not exactly 16 bytes in length + * */ + public constructor( + key: ByteArray, + bitStrength: Int, + personalization: ByteArray?, + ): super( + key = key, + bitStrength = bitStrength, + personalization = personalization, + factory = org.kotlincrypto.hash.blake2.BLAKE2b, + ) + + private constructor(other: BLAKE2b): super(other) + + public override fun copy(): BLAKE2b = BLAKE2b(this) +} diff --git a/library/blake2/src/commonMain/kotlin/org/kotlincrypto/macs/blake2/BLAKE2s.kt b/library/blake2/src/commonMain/kotlin/org/kotlincrypto/macs/blake2/BLAKE2s.kt new file mode 100644 index 0000000..f93de19 --- /dev/null +++ b/library/blake2/src/commonMain/kotlin/org/kotlincrypto/macs/blake2/BLAKE2s.kt @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2025 Matthew Nelson + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +package org.kotlincrypto.macs.blake2 + +/** + * BLAKE2s Keyed Hashing implementation + * + * https://datatracker.ietf.org/doc/rfc7693/ + * */ +public class BLAKE2s: BLAKE2Mac { + + /** + * Creates a new instance of [BLAKE2s]. + * + * @param [key] The secret to use for authenticating data. + * @param [bitStrength] The number of bits returned when [doFinal] is invoked. + * + * @throws [IllegalArgumentException] when: + * - [key] size is less than 1 + * - [key] size is greater than 32 + * - [bitStrength] is less than 8 + * - [bitStrength] is greater than 256 + * - [bitStrength] is not a factor of 8 + * */ + public constructor( + key: ByteArray, + bitStrength: Int, + ): this(key, bitStrength, null) + + /** + * Creates a new instance of [BLAKE2s]. + * + * @param [key] The secret to use for authenticating data. + * @param [bitStrength] The number of bits returned when [doFinal] is invoked. + * @param [personalization] A user selected customization bit string to define a variant + * of the function. When no customization is desired, [personalization] must be set to a + * null value. Must be 8 bytes in length, or null. + * + * @throws [IllegalArgumentException] when: + * - [key] size is less than 1 + * - [key] size is greater than 32 + * - [bitStrength] is less than 8 + * - [bitStrength] is greater than 256 + * - [bitStrength] is not a factor of 8 + * - [personalization] is non-null and not exactly 8 bytes in length + * */ + public constructor( + key: ByteArray, + bitStrength: Int, + personalization: ByteArray?, + ): super( + key = key, + bitStrength = bitStrength, + personalization = personalization, + factory = org.kotlincrypto.hash.blake2.BLAKE2s, + ) + + private constructor(other: BLAKE2s): super(other) + + public override fun copy(): BLAKE2s = BLAKE2s(this) +} diff --git a/library/blake2/src/commonTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2b_160UnitTest.kt b/library/blake2/src/commonTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2b_160UnitTest.kt new file mode 100644 index 0000000..5c7e463 --- /dev/null +++ b/library/blake2/src/commonTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2b_160UnitTest.kt @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2025 Matthew Nelson + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +@file:Suppress("ClassName") + +package org.kotlincrypto.macs.blake2 + +import org.kotlincrypto.core.mac.Mac +import org.kotlincrypto.macs.MacUnitTest +import kotlin.test.Test + +open class BLAKE2b_160UnitTest: MacUnitTest() { + override fun mac(key: ByteArray): Mac = BLAKE2b(key, 160) + + final override val maxKeyLength: Int = 64 + + final override val expectedResetSmallHash: String = "f3c8bd6284ba4a7e8a880c203764ef088bf2f0fa" + final override val expectedResetMediumHash: String = "8496817e3404b9c0c7eb7a789ba2badf511d64fb" + final override val expectedResetLargeHash: String = "7f740ad88459a185214222ea81c0a7811ee336d5" + final override val expectedUpdateSmallHash: String = "f63aba3d2255958ac1960aa4341306b6a4948560" + final override val expectedUpdateMediumHash: String = "40c254c2b5d7a59af73568d3c6c313de49063443" + + @Test + final override fun givenMac_whenResetSmallKey_thenDoFinalReturnsExpected() { + super.givenMac_whenResetSmallKey_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenResetMediumKey_thenDoFinalReturnsExpected() { + super.givenMac_whenResetMediumKey_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenResetLargeKey_thenDoFinalReturnsExpected() { + super.givenMac_whenResetLargeKey_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenUpdatedSmall_thenDoFinalReturnsExpected() { + super.givenMac_whenUpdatedSmall_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenUpdatedMedium_thenDoFinalReturnsExpected() { + super.givenMac_whenUpdatedMedium_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenCopied_thenIsDifferentInstance() { + super.givenMac_whenCopied_thenIsDifferentInstance() + } + + @Test + final override fun givenMac_whenDoFinal_thenLengthMatchesOutput() { + super.givenMac_whenDoFinal_thenLengthMatchesOutput() + } + + @Test + final override fun givenMac_whenInstanceResetWithNewKey_thenDoFinalReturnsExpected() { + super.givenMac_whenInstanceResetWithNewKey_thenDoFinalReturnsExpected() + } +} diff --git a/library/blake2/src/commonTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2b_184UnitTest.kt b/library/blake2/src/commonTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2b_184UnitTest.kt new file mode 100644 index 0000000..4d155ae --- /dev/null +++ b/library/blake2/src/commonTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2b_184UnitTest.kt @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2025 Matthew Nelson + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +@file:Suppress("ClassName") + +package org.kotlincrypto.macs.blake2 + +import org.kotlincrypto.core.mac.Mac +import org.kotlincrypto.macs.MacUnitTest +import kotlin.test.Test + +open class BLAKE2b_184UnitTest: MacUnitTest() { + override fun mac(key: ByteArray): Mac = BLAKE2b(key, 184) + + final override val maxKeyLength: Int = 64 + + final override val expectedResetSmallHash: String = "7442775b9d7da4ef412dddac995501f97e9f7b7698c1f3" + final override val expectedResetMediumHash: String = "218f2251d0030be947d882a535017ee25864d2a875f1f3" + final override val expectedResetLargeHash: String = "5e88d6624a0cd9d7fd94700d457c9e882f0bef8849cea6" + final override val expectedUpdateSmallHash: String = "dbdf12a154c58c90a82c1083f56dfbb4124bf336894501" + final override val expectedUpdateMediumHash: String = "55195a358fb623ce8cf077cbca2f615813c956bbc84fbc" + + @Test + final override fun givenMac_whenResetSmallKey_thenDoFinalReturnsExpected() { + super.givenMac_whenResetSmallKey_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenResetMediumKey_thenDoFinalReturnsExpected() { + super.givenMac_whenResetMediumKey_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenResetLargeKey_thenDoFinalReturnsExpected() { + super.givenMac_whenResetLargeKey_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenUpdatedSmall_thenDoFinalReturnsExpected() { + super.givenMac_whenUpdatedSmall_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenUpdatedMedium_thenDoFinalReturnsExpected() { + super.givenMac_whenUpdatedMedium_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenCopied_thenIsDifferentInstance() { + super.givenMac_whenCopied_thenIsDifferentInstance() + } + + @Test + final override fun givenMac_whenDoFinal_thenLengthMatchesOutput() { + super.givenMac_whenDoFinal_thenLengthMatchesOutput() + } + + @Test + final override fun givenMac_whenInstanceResetWithNewKey_thenDoFinalReturnsExpected() { + super.givenMac_whenInstanceResetWithNewKey_thenDoFinalReturnsExpected() + } +} diff --git a/library/blake2/src/commonTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2b_256UnitTest.kt b/library/blake2/src/commonTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2b_256UnitTest.kt new file mode 100644 index 0000000..aa92522 --- /dev/null +++ b/library/blake2/src/commonTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2b_256UnitTest.kt @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2025 Matthew Nelson + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +@file:Suppress("ClassName") + +package org.kotlincrypto.macs.blake2 + +import org.kotlincrypto.core.mac.Mac +import org.kotlincrypto.macs.MacUnitTest +import kotlin.test.Test + +open class BLAKE2b_256UnitTest: MacUnitTest() { + override fun mac(key: ByteArray): Mac = BLAKE2b(key, 256) + + final override val maxKeyLength: Int = 64 + + final override val expectedResetSmallHash: String = "24cab8b45b4640cef99619ab7d10e8c82d8bddbb3b4f8d82e13621ab784ceefe" + final override val expectedResetMediumHash: String = "acc695576fd09ad0c029ae77b9d66e102536605bcbb14d8780f08733f8932f05" + final override val expectedResetLargeHash: String = "6773c6f0abcc63674ea42af897c0e1c7e9750554f3f2ef2237cba691eab4d6cd" + final override val expectedUpdateSmallHash: String = "f9b6f68d728759002b7b64600bc1cd04ea40316cab5404ccea94f1fdf889f288" + final override val expectedUpdateMediumHash: String = "f845488dabbbf2e4380a52eec58b22ff44e40273d4b0ec65e54730037475bfaf" + + @Test + final override fun givenMac_whenResetSmallKey_thenDoFinalReturnsExpected() { + super.givenMac_whenResetSmallKey_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenResetMediumKey_thenDoFinalReturnsExpected() { + super.givenMac_whenResetMediumKey_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenResetLargeKey_thenDoFinalReturnsExpected() { + super.givenMac_whenResetLargeKey_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenUpdatedSmall_thenDoFinalReturnsExpected() { + super.givenMac_whenUpdatedSmall_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenUpdatedMedium_thenDoFinalReturnsExpected() { + super.givenMac_whenUpdatedMedium_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenCopied_thenIsDifferentInstance() { + super.givenMac_whenCopied_thenIsDifferentInstance() + } + + @Test + final override fun givenMac_whenDoFinal_thenLengthMatchesOutput() { + super.givenMac_whenDoFinal_thenLengthMatchesOutput() + } + + @Test + final override fun givenMac_whenInstanceResetWithNewKey_thenDoFinalReturnsExpected() { + super.givenMac_whenInstanceResetWithNewKey_thenDoFinalReturnsExpected() + } +} diff --git a/library/blake2/src/commonTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2b_384UnitTest.kt b/library/blake2/src/commonTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2b_384UnitTest.kt new file mode 100644 index 0000000..2f1c051 --- /dev/null +++ b/library/blake2/src/commonTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2b_384UnitTest.kt @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2025 Matthew Nelson + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +@file:Suppress("ClassName") + +package org.kotlincrypto.macs.blake2 + +import org.kotlincrypto.core.mac.Mac +import org.kotlincrypto.macs.MacUnitTest +import kotlin.test.Test + +open class BLAKE2b_384UnitTest: MacUnitTest() { + override fun mac(key: ByteArray): Mac = BLAKE2b(key, 384) + + final override val maxKeyLength: Int = 64 + + final override val expectedResetSmallHash: String = "a285da0d50d9664e847fd5f070e70c96ae7a5545032fd893dd87756803763e1654e488ff8d857986b39753e43faa864f" + final override val expectedResetMediumHash: String = "612c0ad0a3b60257da991d969fdbcc45327bfcd074c00027659d1fc728b2de58f792b6d75ae2696f62da2c050df9a868" + final override val expectedResetLargeHash: String = "7204d7c3d08f5698c81d95fcc54c58e79a50b9f68b8b911cfee91b916c5dd881f1d723f165d655fc595ab68199a610b5" + final override val expectedUpdateSmallHash: String = "92545bfd677f6fed7da70bad2dae4f7f1f9fef7a0648e649e1ba30eaa1d2fa8077d94780b95863d25b032da29be71957" + final override val expectedUpdateMediumHash: String = "eb6cc1e601b18c5139364d2349a3d7d1bfb71d6ac4b48c38e677751c928a774e2107767046e44d6b3f2cc1ef8211496a" + + @Test + final override fun givenMac_whenResetSmallKey_thenDoFinalReturnsExpected() { + super.givenMac_whenResetSmallKey_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenResetMediumKey_thenDoFinalReturnsExpected() { + super.givenMac_whenResetMediumKey_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenResetLargeKey_thenDoFinalReturnsExpected() { + super.givenMac_whenResetLargeKey_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenUpdatedSmall_thenDoFinalReturnsExpected() { + super.givenMac_whenUpdatedSmall_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenUpdatedMedium_thenDoFinalReturnsExpected() { + super.givenMac_whenUpdatedMedium_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenCopied_thenIsDifferentInstance() { + super.givenMac_whenCopied_thenIsDifferentInstance() + } + + @Test + final override fun givenMac_whenDoFinal_thenLengthMatchesOutput() { + super.givenMac_whenDoFinal_thenLengthMatchesOutput() + } + + @Test + final override fun givenMac_whenInstanceResetWithNewKey_thenDoFinalReturnsExpected() { + super.givenMac_whenInstanceResetWithNewKey_thenDoFinalReturnsExpected() + } +} diff --git a/library/blake2/src/commonTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2b_512UnitTest.kt b/library/blake2/src/commonTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2b_512UnitTest.kt new file mode 100644 index 0000000..3e1c0a2 --- /dev/null +++ b/library/blake2/src/commonTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2b_512UnitTest.kt @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2025 Matthew Nelson + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +@file:Suppress("ClassName") + +package org.kotlincrypto.macs.blake2 + +import org.kotlincrypto.core.mac.Mac +import org.kotlincrypto.macs.MacUnitTest +import kotlin.test.Test + +open class BLAKE2b_512UnitTest: MacUnitTest() { + override fun mac(key: ByteArray): Mac = BLAKE2b(key, 512) + + final override val maxKeyLength: Int = 64 + + final override val expectedResetSmallHash: String = "3ee218a026889e1d9b93e6f1216415a6566344cd3634b0be5b529329bf95c519b6f1b5c663e390253b0815cd9cfe486a40bf6283d9e0de4420bcc72a54e34275" + final override val expectedResetMediumHash: String = "185f29f5342ca4fce69eb3216852b1a87c9648879db85a89d251460f2234d6547f6758c4ad2c3fe21f1d23066dcbff46dd14b508dade008e69942f6fae68c328" + final override val expectedResetLargeHash: String = "4c0ec45c0e365cf91c6839022a163deb8c4195f68bef616dd56039673f4e1b8589ce7d36738102ee057b907012e212c1c3c96149834a44d5e321756a9dc0bc60" + final override val expectedUpdateSmallHash: String = "c293a90d4064c6e671e7ec6124b70952d25e1f2515abe498aa33c99fe131e35ce80049e6f2715eb4200a882b3b04892a57f0302d66f8df840f243588e3e96d99" + final override val expectedUpdateMediumHash: String = "c153bb41a104b980d3346de6a7fe0ef9d11914b8a1dd023a95e3263bb4f2f546ed6ab83f0e8b2b8a434b53663cfbe40bfd04e9dbe119d0e81c9a793b08a10025" + + @Test + final override fun givenMac_whenResetSmallKey_thenDoFinalReturnsExpected() { + super.givenMac_whenResetSmallKey_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenResetMediumKey_thenDoFinalReturnsExpected() { + super.givenMac_whenResetMediumKey_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenResetLargeKey_thenDoFinalReturnsExpected() { + super.givenMac_whenResetLargeKey_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenUpdatedSmall_thenDoFinalReturnsExpected() { + super.givenMac_whenUpdatedSmall_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenUpdatedMedium_thenDoFinalReturnsExpected() { + super.givenMac_whenUpdatedMedium_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenCopied_thenIsDifferentInstance() { + super.givenMac_whenCopied_thenIsDifferentInstance() + } + + @Test + final override fun givenMac_whenDoFinal_thenLengthMatchesOutput() { + super.givenMac_whenDoFinal_thenLengthMatchesOutput() + } + + @Test + final override fun givenMac_whenInstanceResetWithNewKey_thenDoFinalReturnsExpected() { + super.givenMac_whenInstanceResetWithNewKey_thenDoFinalReturnsExpected() + } +} diff --git a/library/blake2/src/commonTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2s_128UnitTest.kt b/library/blake2/src/commonTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2s_128UnitTest.kt new file mode 100644 index 0000000..0b16e82 --- /dev/null +++ b/library/blake2/src/commonTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2s_128UnitTest.kt @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2025 Matthew Nelson + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +@file:Suppress("ClassName") + +package org.kotlincrypto.macs.blake2 + +import org.kotlincrypto.core.mac.Mac +import org.kotlincrypto.macs.MacUnitTest +import kotlin.test.Test + +open class BLAKE2s_128UnitTest: MacUnitTest() { + override fun mac(key: ByteArray): Mac = BLAKE2s(key, 128) + + final override val maxKeyLength: Int = 32 + + final override val expectedResetSmallHash: String = "59ae88d9382f9a8d6280cbb096d0b256" + final override val expectedResetMediumHash: String = "fb2a18e9c663992b2f10b9f71ea9afe6" + final override val expectedResetLargeHash: String = "34b2929d7a24b1dfa087f92573ba8efe" + final override val expectedUpdateSmallHash: String = "9f2e6c1d4b4cc0fdc9684c0ae330993c" + final override val expectedUpdateMediumHash: String = "36ae31e6dd7872f79e9afcf379ea7c90" + + @Test + final override fun givenMac_whenResetSmallKey_thenDoFinalReturnsExpected() { + super.givenMac_whenResetSmallKey_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenResetMediumKey_thenDoFinalReturnsExpected() { + super.givenMac_whenResetMediumKey_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenResetLargeKey_thenDoFinalReturnsExpected() { + super.givenMac_whenResetLargeKey_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenUpdatedSmall_thenDoFinalReturnsExpected() { + super.givenMac_whenUpdatedSmall_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenUpdatedMedium_thenDoFinalReturnsExpected() { + super.givenMac_whenUpdatedMedium_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenCopied_thenIsDifferentInstance() { + super.givenMac_whenCopied_thenIsDifferentInstance() + } + + @Test + final override fun givenMac_whenDoFinal_thenLengthMatchesOutput() { + super.givenMac_whenDoFinal_thenLengthMatchesOutput() + } + + @Test + final override fun givenMac_whenInstanceResetWithNewKey_thenDoFinalReturnsExpected() { + super.givenMac_whenInstanceResetWithNewKey_thenDoFinalReturnsExpected() + } +} diff --git a/library/blake2/src/commonTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2s_160UnitTest.kt b/library/blake2/src/commonTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2s_160UnitTest.kt new file mode 100644 index 0000000..90d25e1 --- /dev/null +++ b/library/blake2/src/commonTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2s_160UnitTest.kt @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2025 Matthew Nelson + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +@file:Suppress("ClassName") + +package org.kotlincrypto.macs.blake2 + +import org.kotlincrypto.core.mac.Mac +import org.kotlincrypto.macs.MacUnitTest +import kotlin.test.Test + +open class BLAKE2s_160UnitTest: MacUnitTest() { + override fun mac(key: ByteArray): Mac = BLAKE2s(key, 160) + + final override val maxKeyLength: Int = 32 + + final override val expectedResetSmallHash: String = "dc8d7fdb3700ff7562d90f23264e815951bbc9e5" + final override val expectedResetMediumHash: String = "9289bcc3f5062178974df5e0b5df9e8bc583f0fb" + final override val expectedResetLargeHash: String = "318be51c0bb12bf0c2abecacc5d5e9457c4d627d" + final override val expectedUpdateSmallHash: String = "a7f88fafe1b8160ee0cc68c91a4f3e5630e3554d" + final override val expectedUpdateMediumHash: String = "7ab1e051e2989912ef20ee559dcc6f61753da529" + + @Test + final override fun givenMac_whenResetSmallKey_thenDoFinalReturnsExpected() { + super.givenMac_whenResetSmallKey_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenResetMediumKey_thenDoFinalReturnsExpected() { + super.givenMac_whenResetMediumKey_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenResetLargeKey_thenDoFinalReturnsExpected() { + super.givenMac_whenResetLargeKey_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenUpdatedSmall_thenDoFinalReturnsExpected() { + super.givenMac_whenUpdatedSmall_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenUpdatedMedium_thenDoFinalReturnsExpected() { + super.givenMac_whenUpdatedMedium_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenCopied_thenIsDifferentInstance() { + super.givenMac_whenCopied_thenIsDifferentInstance() + } + + @Test + final override fun givenMac_whenDoFinal_thenLengthMatchesOutput() { + super.givenMac_whenDoFinal_thenLengthMatchesOutput() + } + + @Test + final override fun givenMac_whenInstanceResetWithNewKey_thenDoFinalReturnsExpected() { + super.givenMac_whenInstanceResetWithNewKey_thenDoFinalReturnsExpected() + } +} diff --git a/library/blake2/src/commonTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2s_184UnitTest.kt b/library/blake2/src/commonTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2s_184UnitTest.kt new file mode 100644 index 0000000..ab8b884 --- /dev/null +++ b/library/blake2/src/commonTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2s_184UnitTest.kt @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2025 Matthew Nelson + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +@file:Suppress("ClassName") + +package org.kotlincrypto.macs.blake2 + +import org.kotlincrypto.core.mac.Mac +import org.kotlincrypto.macs.MacUnitTest +import kotlin.test.Test + +open class BLAKE2s_184UnitTest: MacUnitTest() { + override fun mac(key: ByteArray): Mac = BLAKE2s(key, 184) + + final override val maxKeyLength: Int = 32 + + final override val expectedResetSmallHash: String = "45d41259a15f621be3f292a78c1a35b1fe0b6e3d544e48" + final override val expectedResetMediumHash: String = "30eb87b29a7633666c66bb8db10cdab09c9791d5c7402b" + final override val expectedResetLargeHash: String = "59cb035526cf35cbc0b96e2788696763d371cc0f1eadcf" + final override val expectedUpdateSmallHash: String = "4e4d5011985d950b14464dc86106b7625a1caf8648c82c" + final override val expectedUpdateMediumHash: String = "30d7b080d3d632ccfe4b56b859ddbceb3c7388aa0f82a7" + + @Test + final override fun givenMac_whenResetSmallKey_thenDoFinalReturnsExpected() { + super.givenMac_whenResetSmallKey_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenResetMediumKey_thenDoFinalReturnsExpected() { + super.givenMac_whenResetMediumKey_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenResetLargeKey_thenDoFinalReturnsExpected() { + super.givenMac_whenResetLargeKey_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenUpdatedSmall_thenDoFinalReturnsExpected() { + super.givenMac_whenUpdatedSmall_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenUpdatedMedium_thenDoFinalReturnsExpected() { + super.givenMac_whenUpdatedMedium_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenCopied_thenIsDifferentInstance() { + super.givenMac_whenCopied_thenIsDifferentInstance() + } + + @Test + final override fun givenMac_whenDoFinal_thenLengthMatchesOutput() { + super.givenMac_whenDoFinal_thenLengthMatchesOutput() + } + + @Test + final override fun givenMac_whenInstanceResetWithNewKey_thenDoFinalReturnsExpected() { + super.givenMac_whenInstanceResetWithNewKey_thenDoFinalReturnsExpected() + } +} diff --git a/library/blake2/src/commonTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2s_224UnitTest.kt b/library/blake2/src/commonTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2s_224UnitTest.kt new file mode 100644 index 0000000..57f4217 --- /dev/null +++ b/library/blake2/src/commonTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2s_224UnitTest.kt @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2025 Matthew Nelson + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +@file:Suppress("ClassName") + +package org.kotlincrypto.macs.blake2 + +import org.kotlincrypto.core.mac.Mac +import org.kotlincrypto.macs.MacUnitTest +import kotlin.test.Test + +open class BLAKE2s_224UnitTest: MacUnitTest() { + override fun mac(key: ByteArray): Mac = BLAKE2s(key, 224) + + final override val maxKeyLength: Int = 32 + + final override val expectedResetSmallHash: String = "f2fe453e8789811db168c64f1912b015ed509a4e97382a022af07dce" + final override val expectedResetMediumHash: String = "0b2cc5683e3adcbf0a88412d56ec62b63d7962016bfb4935ac6ab635" + final override val expectedResetLargeHash: String = "664d9e93306b099574504d1e16b01ba82f05b0df681009bcf06c59d5" + final override val expectedUpdateSmallHash: String = "4e0eae25c7409a0f19e01dadd58e9f1ef57f728c9fa029a1a2d3336f" + final override val expectedUpdateMediumHash: String = "2f6e2d07dfae2463c2cac72a988965c1c217d4ad41836e9d6cd4317c" + + @Test + final override fun givenMac_whenResetSmallKey_thenDoFinalReturnsExpected() { + super.givenMac_whenResetSmallKey_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenResetMediumKey_thenDoFinalReturnsExpected() { + super.givenMac_whenResetMediumKey_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenResetLargeKey_thenDoFinalReturnsExpected() { + super.givenMac_whenResetLargeKey_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenUpdatedSmall_thenDoFinalReturnsExpected() { + super.givenMac_whenUpdatedSmall_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenUpdatedMedium_thenDoFinalReturnsExpected() { + super.givenMac_whenUpdatedMedium_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenCopied_thenIsDifferentInstance() { + super.givenMac_whenCopied_thenIsDifferentInstance() + } + + @Test + final override fun givenMac_whenDoFinal_thenLengthMatchesOutput() { + super.givenMac_whenDoFinal_thenLengthMatchesOutput() + } + + @Test + final override fun givenMac_whenInstanceResetWithNewKey_thenDoFinalReturnsExpected() { + super.givenMac_whenInstanceResetWithNewKey_thenDoFinalReturnsExpected() + } +} diff --git a/library/blake2/src/commonTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2s_256UnitTest.kt b/library/blake2/src/commonTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2s_256UnitTest.kt new file mode 100644 index 0000000..30bc12f --- /dev/null +++ b/library/blake2/src/commonTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2s_256UnitTest.kt @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2025 Matthew Nelson + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +@file:Suppress("ClassName") + +package org.kotlincrypto.macs.blake2 + +import org.kotlincrypto.core.mac.Mac +import org.kotlincrypto.macs.MacUnitTest +import kotlin.test.Test + +open class BLAKE2s_256UnitTest: MacUnitTest() { + override fun mac(key: ByteArray): Mac = BLAKE2s(key, 256) + + final override val maxKeyLength: Int = 32 + + final override val expectedResetSmallHash: String = "24a80aed26a17c9210503918bf9b4c0aeb9e2e03f2ee9b3cf636f0325a27b745" + final override val expectedResetMediumHash: String = "7a50d2c8aff303387f706576ee03a1815bcaa3f69287a0b208b34a2995b0cea7" + final override val expectedResetLargeHash: String = "1042e44eb3451dd8a57ee87499dd14b3865e9a7e6825cdc664856742a2792264" + final override val expectedUpdateSmallHash: String = "d41121edf9fe5910bffcdab5e48004468ef4f121a52204fbf97052b1b0241ef7" + final override val expectedUpdateMediumHash: String = "863ad2cab99016e2bfdf7e680887fc468f81eb6838848d06c45bfd779f817358" + + @Test + final override fun givenMac_whenResetSmallKey_thenDoFinalReturnsExpected() { + super.givenMac_whenResetSmallKey_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenResetMediumKey_thenDoFinalReturnsExpected() { + super.givenMac_whenResetMediumKey_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenResetLargeKey_thenDoFinalReturnsExpected() { + super.givenMac_whenResetLargeKey_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenUpdatedSmall_thenDoFinalReturnsExpected() { + super.givenMac_whenUpdatedSmall_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenUpdatedMedium_thenDoFinalReturnsExpected() { + super.givenMac_whenUpdatedMedium_thenDoFinalReturnsExpected() + } + + @Test + final override fun givenMac_whenCopied_thenIsDifferentInstance() { + super.givenMac_whenCopied_thenIsDifferentInstance() + } + + @Test + final override fun givenMac_whenDoFinal_thenLengthMatchesOutput() { + super.givenMac_whenDoFinal_thenLengthMatchesOutput() + } + + @Test + final override fun givenMac_whenInstanceResetWithNewKey_thenDoFinalReturnsExpected() { + super.givenMac_whenInstanceResetWithNewKey_thenDoFinalReturnsExpected() + } +} diff --git a/library/blake2/src/jvmMain/java9/module-info.java b/library/blake2/src/jvmMain/java9/module-info.java new file mode 100644 index 0000000..972f869 --- /dev/null +++ b/library/blake2/src/jvmMain/java9/module-info.java @@ -0,0 +1,8 @@ +@SuppressWarnings("module") +module org.kotlincrypto.macs.blake2 { + requires kotlin.stdlib; + requires org.kotlincrypto.hash.blake2; + requires transitive org.kotlincrypto.core.mac; + + exports org.kotlincrypto.macs.blake2; +} diff --git a/library/blake2/src/jvmTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2JvmMac.kt b/library/blake2/src/jvmTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2JvmMac.kt new file mode 100644 index 0000000..b5171cd --- /dev/null +++ b/library/blake2/src/jvmTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2JvmMac.kt @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2023 Matthew Nelson + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +package org.kotlincrypto.macs.blake2 + +import org.bouncycastle.crypto.ExtendedDigest +import org.bouncycastle.crypto.digests.Blake2bDigest +import org.bouncycastle.crypto.digests.Blake2sDigest +import org.kotlincrypto.core.mac.Mac + +/** + * Simple test class that Bouncy Castle Blake2bDigest and Blake2sDigest + * */ +class BLAKE2JvmMac: Mac { + + constructor(algorithm: String, key: ByteArray): super(algorithm, Engine(algorithm, key)) + + private constructor(other: BLAKE2JvmMac): super(other) + override fun copy(): BLAKE2JvmMac = BLAKE2JvmMac(this) + + private class Engine: Mac.Engine { + + private val digestLength: Int + private var delegate: ExtendedDigest + + constructor(algorithm: String, key: ByteArray): super(key) { + val (name, digestLength) = algorithm.split('-').let { + it.first() to (it.last().toInt() / Byte.SIZE_BITS) + } + this.digestLength = digestLength + + this.delegate = when (name) { + "BLAKE2b" -> { + Blake2bDigest(key, digestLength, null, null) + } + "BLAKE2s" -> { + Blake2sDigest(key, digestLength, null, null) + } + else -> error("Unsupported $algorithm") + } + } + + private constructor(other: Engine): super(other) { + this.digestLength = other.digestLength + val otherDelegate = other.delegate + this.delegate = when (otherDelegate) { + is Blake2bDigest -> Blake2bDigest(otherDelegate) + is Blake2sDigest -> Blake2sDigest(otherDelegate) + else -> error("") + } + } + + override fun copy(): Engine = Engine(this) + + override fun macLength(): Int = delegate.digestSize + + override fun update(input: Byte) { delegate.update(input) } + override fun update(input: ByteArray, offset: Int, len: Int) { delegate.update(input, offset, len) } + + override fun doFinal(): ByteArray { + val out = ByteArray(macLength()) + delegate.doFinal(out, 0) + return out + } + + override fun reset() { delegate.reset() } + override fun reset(newKey: ByteArray) { + delegate = when (delegate) { + is Blake2bDigest -> Blake2bDigest(newKey, digestLength, null, null) + is Blake2sDigest -> Blake2sDigest(newKey, digestLength, null, null) + else -> error("") + } + } + } +} diff --git a/library/blake2/src/jvmTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2b_160JvmUnitTest.kt b/library/blake2/src/jvmTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2b_160JvmUnitTest.kt new file mode 100644 index 0000000..af8d59f --- /dev/null +++ b/library/blake2/src/jvmTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2b_160JvmUnitTest.kt @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Matthew Nelson + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +@file:Suppress("ClassName") + +package org.kotlincrypto.macs.blake2 + +import org.kotlincrypto.core.mac.Mac + +class BLAKE2b_160JvmUnitTest: BLAKE2b_160UnitTest() { + override fun mac(key: ByteArray): Mac = BLAKE2JvmMac(super.mac(key).algorithm(), key) +} diff --git a/library/blake2/src/jvmTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2b_184JvmUnitTest.kt b/library/blake2/src/jvmTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2b_184JvmUnitTest.kt new file mode 100644 index 0000000..153f4e6 --- /dev/null +++ b/library/blake2/src/jvmTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2b_184JvmUnitTest.kt @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Matthew Nelson + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +@file:Suppress("ClassName") + +package org.kotlincrypto.macs.blake2 + +import org.kotlincrypto.core.mac.Mac + +class BLAKE2b_184JvmUnitTest: BLAKE2b_184UnitTest() { + override fun mac(key: ByteArray): Mac = BLAKE2JvmMac(super.mac(key).algorithm(), key) +} diff --git a/library/blake2/src/jvmTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2b_256JvmUnitTest.kt b/library/blake2/src/jvmTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2b_256JvmUnitTest.kt new file mode 100644 index 0000000..c48250e --- /dev/null +++ b/library/blake2/src/jvmTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2b_256JvmUnitTest.kt @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Matthew Nelson + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +@file:Suppress("ClassName") + +package org.kotlincrypto.macs.blake2 + +import org.kotlincrypto.core.mac.Mac + +class BLAKE2b_256JvmUnitTest: BLAKE2b_256UnitTest() { + override fun mac(key: ByteArray): Mac = BLAKE2JvmMac(super.mac(key).algorithm(), key) +} diff --git a/library/blake2/src/jvmTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2b_384JvmUnitTest.kt b/library/blake2/src/jvmTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2b_384JvmUnitTest.kt new file mode 100644 index 0000000..743662c --- /dev/null +++ b/library/blake2/src/jvmTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2b_384JvmUnitTest.kt @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Matthew Nelson + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +@file:Suppress("ClassName") + +package org.kotlincrypto.macs.blake2 + +import org.kotlincrypto.core.mac.Mac + +class BLAKE2b_384JvmUnitTest: BLAKE2b_384UnitTest() { + override fun mac(key: ByteArray): Mac = BLAKE2JvmMac(super.mac(key).algorithm(), key) +} diff --git a/library/blake2/src/jvmTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2b_512JvmUnitTest.kt b/library/blake2/src/jvmTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2b_512JvmUnitTest.kt new file mode 100644 index 0000000..f3e6b5f --- /dev/null +++ b/library/blake2/src/jvmTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2b_512JvmUnitTest.kt @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Matthew Nelson + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +@file:Suppress("ClassName") + +package org.kotlincrypto.macs.blake2 + +import org.kotlincrypto.core.mac.Mac + +class BLAKE2b_512JvmUnitTest: BLAKE2b_512UnitTest() { + override fun mac(key: ByteArray): Mac = BLAKE2JvmMac(super.mac(key).algorithm(), key) +} diff --git a/library/blake2/src/jvmTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2s_128JvmUnitTest.kt b/library/blake2/src/jvmTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2s_128JvmUnitTest.kt new file mode 100644 index 0000000..49f8cb7 --- /dev/null +++ b/library/blake2/src/jvmTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2s_128JvmUnitTest.kt @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Matthew Nelson + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +@file:Suppress("ClassName") + +package org.kotlincrypto.macs.blake2 + +import org.kotlincrypto.core.mac.Mac + +class BLAKE2s_128JvmUnitTest: BLAKE2s_128UnitTest() { + override fun mac(key: ByteArray): Mac = BLAKE2JvmMac(super.mac(key).algorithm(), key) +} diff --git a/library/blake2/src/jvmTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2s_160JvmUnitTest.kt b/library/blake2/src/jvmTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2s_160JvmUnitTest.kt new file mode 100644 index 0000000..f676ccc --- /dev/null +++ b/library/blake2/src/jvmTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2s_160JvmUnitTest.kt @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Matthew Nelson + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +@file:Suppress("ClassName") + +package org.kotlincrypto.macs.blake2 + +import org.kotlincrypto.core.mac.Mac + +class BLAKE2s_160JvmUnitTest: BLAKE2s_160UnitTest() { + override fun mac(key: ByteArray): Mac = BLAKE2JvmMac(super.mac(key).algorithm(), key) +} diff --git a/library/blake2/src/jvmTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2s_184JvmUnitTest.kt b/library/blake2/src/jvmTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2s_184JvmUnitTest.kt new file mode 100644 index 0000000..99cfc3a --- /dev/null +++ b/library/blake2/src/jvmTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2s_184JvmUnitTest.kt @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Matthew Nelson + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +@file:Suppress("ClassName") + +package org.kotlincrypto.macs.blake2 + +import org.kotlincrypto.core.mac.Mac + +class BLAKE2s_184JvmUnitTest: BLAKE2s_184UnitTest() { + override fun mac(key: ByteArray): Mac = BLAKE2JvmMac(super.mac(key).algorithm(), key) +} diff --git a/library/blake2/src/jvmTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2s_224JvmUnitTest.kt b/library/blake2/src/jvmTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2s_224JvmUnitTest.kt new file mode 100644 index 0000000..6d25d48 --- /dev/null +++ b/library/blake2/src/jvmTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2s_224JvmUnitTest.kt @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Matthew Nelson + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +@file:Suppress("ClassName") + +package org.kotlincrypto.macs.blake2 + +import org.kotlincrypto.core.mac.Mac + +class BLAKE2s_224JvmUnitTest: BLAKE2s_224UnitTest() { + override fun mac(key: ByteArray): Mac = BLAKE2JvmMac(super.mac(key).algorithm(), key) +} diff --git a/library/blake2/src/jvmTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2s_256JvmUnitTest.kt b/library/blake2/src/jvmTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2s_256JvmUnitTest.kt new file mode 100644 index 0000000..aca7c9b --- /dev/null +++ b/library/blake2/src/jvmTest/kotlin/org/kotlincrypto/macs/blake2/BLAKE2s_256JvmUnitTest.kt @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Matthew Nelson + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +@file:Suppress("ClassName") + +package org.kotlincrypto.macs.blake2 + +import org.kotlincrypto.core.mac.Mac + +class BLAKE2s_256JvmUnitTest: BLAKE2s_256UnitTest() { + override fun mac(key: ByteArray): Mac = BLAKE2JvmMac(super.mac(key).algorithm(), key) +} diff --git a/library/hmac/hmac/src/jvmMain/java9/module-info.java b/library/hmac/hmac/src/jvmMain/java9/module-info.java index 8bfb802..46db1de 100644 --- a/library/hmac/hmac/src/jvmMain/java9/module-info.java +++ b/library/hmac/hmac/src/jvmMain/java9/module-info.java @@ -1,6 +1,5 @@ module org.kotlincrypto.macs.hmac { requires kotlin.stdlib; - requires org.kotlincrypto.core; requires org.kotlincrypto.core.digest; requires transitive org.kotlincrypto.core.mac; diff --git a/library/kmac/src/commonMain/kotlin/org/kotlincrypto/macs/kmac/Kmac.kt b/library/kmac/src/commonMain/kotlin/org/kotlincrypto/macs/kmac/Kmac.kt index 3479b20..ff49351 100644 --- a/library/kmac/src/commonMain/kotlin/org/kotlincrypto/macs/kmac/Kmac.kt +++ b/library/kmac/src/commonMain/kotlin/org/kotlincrypto/macs/kmac/Kmac.kt @@ -26,6 +26,7 @@ import org.kotlincrypto.hash.sha3.CSHAKE256 /** * Core abstraction for Keccak-based Message Authentication + * * Code implementations: * - [KMAC128] * - [KMAC256] diff --git a/settings.gradle.kts b/settings.gradle.kts index 6672c2f..b021b33 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -17,6 +17,7 @@ if (CHECK_PUBLICATION != null) { include(":tools:check-publication") } else { listOf( + "blake2", "hmac:hmac", "hmac:hmac-md", "hmac:hmac-sha1", diff --git a/test-android/build.gradle.kts b/test-android/build.gradle.kts index 0128649..c017fe7 100644 --- a/test-android/build.gradle.kts +++ b/test-android/build.gradle.kts @@ -40,6 +40,7 @@ kmpConfiguration { } sourceSetTestInstrumented { + kotlin.srcDir("src/androidInstrumentedTest/blake2") kotlin.srcDir("src/androidInstrumentedTest/hmac-md") kotlin.srcDir("src/androidInstrumentedTest/hmac-sha1") kotlin.srcDir("src/androidInstrumentedTest/hmac-sha2") @@ -51,6 +52,7 @@ kmpConfiguration { implementation(libs.encoding.base16) implementation(kotlin("test")) + implementation(project(":library:blake2")) implementation(project(":library:hmac:hmac-md")) implementation(project(":library:hmac:hmac-sha1")) implementation(project(":library:hmac:hmac-sha2")) diff --git a/test-android/src/androidInstrumentedTest/blake2 b/test-android/src/androidInstrumentedTest/blake2 new file mode 120000 index 0000000..bd1e1b5 --- /dev/null +++ b/test-android/src/androidInstrumentedTest/blake2 @@ -0,0 +1 @@ +../../../library/blake2/src/commonTest/kotlin \ No newline at end of file diff --git a/tools/check-publication/build.gradle.kts b/tools/check-publication/build.gradle.kts index 690f3cc..603e8ec 100644 --- a/tools/check-publication/build.gradle.kts +++ b/tools/check-publication/build.gradle.kts @@ -42,11 +42,11 @@ kmpConfiguration { implementation("$group:hmac:$version") implementation(platform("$group:bom:$version")) + implementation("$group:blake2") implementation("$group:hmac-md") implementation("$group:hmac-sha1") implementation("$group:hmac-sha2") implementation("$group:hmac-sha3") - implementation("$group:kmac") } } diff --git a/tools/testing/src/commonMain/kotlin/org/kotlincrypto/macs/MacUnitTest.kt b/tools/testing/src/commonMain/kotlin/org/kotlincrypto/macs/MacUnitTest.kt index 9fa9879..80c4eba 100644 --- a/tools/testing/src/commonMain/kotlin/org/kotlincrypto/macs/MacUnitTest.kt +++ b/tools/testing/src/commonMain/kotlin/org/kotlincrypto/macs/MacUnitTest.kt @@ -46,6 +46,13 @@ abstract class MacUnitTest { abstract fun mac(key: ByteArray): Mac + private fun ByteArray.toMaxKeyLen(): ByteArray { + val max = maxKeyLength ?: return this + if (this.size < max) return this + return copyOf(max) + } + + open val maxKeyLength: Int? = null abstract val expectedResetSmallHash: String abstract val expectedResetMediumHash: String abstract val expectedResetLargeHash: String @@ -64,7 +71,7 @@ abstract class MacUnitTest { open fun givenMac_whenResetSmallKey_thenDoFinalReturnsExpected() { assertExpectedHashes - val mac = mac(KEY_SMALL) + val mac = mac(KEY_SMALL.toMaxKeyLen()) val empty = mac.doFinal().encodeToString(TestData.base16) updateSmall(mac) mac.reset() @@ -75,7 +82,7 @@ abstract class MacUnitTest { open fun givenMac_whenResetMediumKey_thenDoFinalReturnsExpected() { assertExpectedHashes - val mac = mac(KEY_MEDIUM) + val mac = mac(KEY_MEDIUM.toMaxKeyLen()) val empty = mac.doFinal().encodeToString(TestData.base16) updateSmall(mac) mac.reset() @@ -86,7 +93,7 @@ abstract class MacUnitTest { open fun givenMac_whenResetLargeKey_thenDoFinalReturnsExpected() { assertExpectedHashes - val mac = mac(KEY_LARGE) + val mac = mac(KEY_LARGE.toMaxKeyLen()) val empty = mac.doFinal().encodeToString(TestData.base16) updateSmall(mac) mac.reset() @@ -97,7 +104,7 @@ abstract class MacUnitTest { open fun givenMac_whenUpdatedSmall_thenDoFinalReturnsExpected() { assertExpectedHashes - val mac = mac(KEY_SMALL) + val mac = mac(KEY_SMALL.toMaxKeyLen()) mac.doFinal() updateSmall(mac) val actual = mac.doFinal().encodeToString(TestData.base16) @@ -106,7 +113,7 @@ abstract class MacUnitTest { open fun givenMac_whenUpdatedMedium_thenDoFinalReturnsExpected() { assertExpectedHashes - val mac = mac(KEY_MEDIUM) + val mac = mac(KEY_MEDIUM.toMaxKeyLen()) mac.doFinal() updateMedium(mac) @@ -116,7 +123,7 @@ abstract class MacUnitTest { open fun givenMac_whenCopied_thenIsDifferentInstance() { assertExpectedHashes - val mac = mac(KEY_SMALL) + val mac = mac(KEY_SMALL.toMaxKeyLen()) updateSmall(mac) val copy = mac.copy() @@ -131,17 +138,17 @@ abstract class MacUnitTest { open fun givenMac_whenDoFinal_thenLengthMatchesOutput() { assertExpectedHashes - assertEquals(mac(KEY_SMALL).doFinal().encodeToString(TestData.base16).length, expectedResetSmallHash.length) + assertEquals(mac(KEY_SMALL.toMaxKeyLen()).doFinal().encodeToString(TestData.base16).length, expectedResetSmallHash.length) } open fun givenMac_whenInstanceResetWithNewKey_thenDoFinalReturnsExpected() { assertExpectedHashes - val mac = mac(KEY_SMALL) + val mac = mac(KEY_SMALL.toMaxKeyLen()) updateSmall(mac) assertEquals(mac.doFinal().encodeToString(TestData.base16), expectedUpdateSmallHash) assertEquals(mac.doFinal().encodeToString(TestData.base16), expectedResetSmallHash) - mac.reset(KEY_MEDIUM) + mac.reset(KEY_MEDIUM.toMaxKeyLen()) updateMedium(mac) assertEquals(mac.doFinal().encodeToString(TestData.base16), expectedUpdateMediumHash) assertEquals(mac.doFinal().encodeToString(TestData.base16), expectedResetMediumHash)