From 46647558ceb09b8a07a8031b9565b5ebb7d58a44 Mon Sep 17 00:00:00 2001 From: Infendro Date: Sun, 14 Dec 2025 14:34:00 +0100 Subject: [PATCH 1/5] update README small rewording, link wikipedia article --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 23c1d1f..905c879 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # mac-kt -`mac-kt` is a Kotlin Multiplatform library that provides common MAC implementations. +`mac-kt` is a Kotlin Multiplatform library that provides common [Message Authentication Code](https://en.wikipedia.org/wiki/Message_authentication_code) algorithms. -Supported MACs: +Supported algorithms: - HMAC ## Targets -- 2.49.1 From 3603583d949b7e5fca98db827dd54b742a9bb132 Mon Sep 17 00:00:00 2001 From: Infendro Date: Tue, 13 Jan 2026 18:04:06 +0100 Subject: [PATCH 2/5] improve ci --- .gitea/workflows/ci.yaml | 92 +++++++++++++++++++ .gitea/workflows/main.yaml | 36 -------- build.gradle.kts | 2 +- .../kotlin/com/infendro/mac/HMAC.kt | 2 +- 4 files changed, 94 insertions(+), 38 deletions(-) create mode 100644 .gitea/workflows/ci.yaml delete mode 100644 .gitea/workflows/main.yaml diff --git a/.gitea/workflows/ci.yaml b/.gitea/workflows/ci.yaml new file mode 100644 index 0000000..2f46684 --- /dev/null +++ b/.gitea/workflows/ci.yaml @@ -0,0 +1,92 @@ +on: + push: + branches: [ develop, main ] + 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: 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: Test + run: ./gradlew allTests + + publish: + if: ${{ github.event_name == 'push' && github.ref_name == 'main' }} + needs: 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: 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 }} diff --git a/.gitea/workflows/main.yaml b/.gitea/workflows/main.yaml deleted file mode 100644 index 4885477..0000000 --- a/.gitea/workflows/main.yaml +++ /dev/null @@ -1,36 +0,0 @@ -on: - push: - branches: - - main - -env: - INFENDRO__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/ diff --git a/build.gradle.kts b/build.gradle.kts index 89bb4ce..285c4cd 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,10 +12,10 @@ plugins { kotlin { jvm() + linuxX64() js { nodejs() } - linuxX64() repositories { infendro() diff --git a/src/commonTest/kotlin/com/infendro/mac/HMAC.kt b/src/commonTest/kotlin/com/infendro/mac/HMAC.kt index e47ab4b..a88670a 100644 --- a/src/commonTest/kotlin/com/infendro/mac/HMAC.kt +++ b/src/commonTest/kotlin/com/infendro/mac/HMAC.kt @@ -16,7 +16,7 @@ class `HMAC Test` { } @Test - fun `hash() - example`() { + fun `example`() { assertContentEquals( ubyteArrayOf( 0xf7U, 0xbcU, 0x83U, 0xf4U, -- 2.49.1 From d07f2658ffa25c51625e5cc48dca727640aefb6d Mon Sep 17 00:00:00 2001 From: Infendro Date: Thu, 22 Jan 2026 12:50:36 +0100 Subject: [PATCH 3/5] implement optimizations --- README.md | 20 ++-------- build.gradle.kts | 2 +- gradle/libs.versions.toml | 10 ++--- .../kotlin/com/infendro/mac/HMAC.kt | 37 +++++++++---------- src/commonMain/kotlin/com/infendro/mac/MAC.kt | 20 ++++++++-- .../kotlin/com/infendro/mac/HMAC.kt | 32 ++++++++-------- 6 files changed, 58 insertions(+), 63 deletions(-) diff --git a/README.md b/README.md index 905c879..23e2d9b 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,10 @@ # mac-kt -`mac-kt` is a Kotlin Multiplatform library that provides common [Message Authentication Code](https://en.wikipedia.org/wiki/Message_authentication_code) algorithms. +`mac-kt` is a Kotlin Multiplatform library that provides common [Message Authentication Codes](https://en.wikipedia.org/wiki/Message_authentication_code). Supported algorithms: - HMAC -## Targets - -| Target | Status | -|------------------|---------------| -| JVM | Supported | -| JavaScript | Supported | -| Native (Linux) | Supported | -| Native (Windows) | Not Supported | - ## Installation Add the following to your `build.gradle.kts`. @@ -31,18 +22,13 @@ dependencies { ## Usage ```kotlin -import com.infendro.hash.sha1.SHA1 -import com.infendro.mac.HMAC - fun main() { // create an HMAC instance using SHA1 val hmac = HMAC(SHA1) // generate MAC - val key = "secret" - .encodeToByteArray().asUByteArray() - val value = "Hello World!" - .encodeToByteArray().asUByteArray() + val key = "secret".encodeToByteArray() + val value = "Hello World!".encodeToByteArray() val mac = hmac.hash(key, value) } ``` diff --git a/build.gradle.kts b/build.gradle.kts index 285c4cd..46874c8 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -25,7 +25,7 @@ kotlin { sourceSets { commonMain.dependencies { implementation(libs.hash) - implementation(libs.bytearray) + implementation(libs.bytes) } commonTest.dependencies { implementation(libs.test) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 4b5468d..627e5eb 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,8 +1,8 @@ [versions] -infendro = "1.0.0" -kotlin = "2.2.21" -hash = "1.3.2" -bytearray = "1.2.4" +infendro = "1.1.0" +kotlin = "2.3.0" +hash = "1.5.1" +bytes = "1.3.3" [plugins] infendro = { id = "com.infendro.plugin", version.ref = "infendro" } @@ -10,5 +10,5 @@ multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotl [libraries] hash = { module = "com.infendro:hash", version.ref = "hash" } -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" } diff --git a/src/commonMain/kotlin/com/infendro/mac/HMAC.kt b/src/commonMain/kotlin/com/infendro/mac/HMAC.kt index 6d28138..922eef1 100644 --- a/src/commonMain/kotlin/com/infendro/mac/HMAC.kt +++ b/src/commonMain/kotlin/com/infendro/mac/HMAC.kt @@ -1,6 +1,6 @@ package com.infendro.mac -import com.infendro.bytearray.padEnd +import com.infendro.bytes.bytearray.xorInto import com.infendro.hash.HashFunction class HMAC( @@ -9,25 +9,24 @@ class HMAC( override val bytes: Int get() = function.bytes - override fun hash( - key: UByteArray, - value: UByteArray, - ): UByteArray { + override fun hashInto(key: ByteArray, value: ByteArray, destination: ByteArray, destinationOffset: Int) { val paddedKey = pad(key) - - val innerKey = paddedKey.map { it xor 0x36U }.toUByteArray() - val outerKey = paddedKey.map { it xor 0x5CU }.toUByteArray() - - return function.hash(outerKey + function.hash(innerKey + value)) - } - - private fun pad( - key: UByteArray, - ): UByteArray { - return when { - key.size > function.block -> function.hash(key) - key.size < function.block -> key.padEnd(function.block, 0x00U) - else -> key + val inner = ByteArray(function.block + value.size).also { + paddedKey.xorInto(0x36, it) + value.copyInto(it, function.block) } + val outer = ByteArray(function.block + function.bytes).also { + paddedKey.xorInto(0x5C, it) + function.hashInto(inner, it, function.block) + } + function.hashInto(outer, destination, destinationOffset) } + + private fun pad(key: ByteArray): ByteArray = + ByteArray(function.block).also { + when { + key.size > function.block -> function.hashInto(key, it) + else -> key.copyInto(it) + } + } } diff --git a/src/commonMain/kotlin/com/infendro/mac/MAC.kt b/src/commonMain/kotlin/com/infendro/mac/MAC.kt index 686a46b..0069681 100644 --- a/src/commonMain/kotlin/com/infendro/mac/MAC.kt +++ b/src/commonMain/kotlin/com/infendro/mac/MAC.kt @@ -5,8 +5,20 @@ interface MAC { val bits: Int get() = bytes * 8 - fun hash( - key: UByteArray, - value: UByteArray, - ): UByteArray + fun hashInto(key: ByteArray, value: ByteArray, destination: ByteArray, destinationOffset: Int = 0) + + fun hashInto(key: ByteArray, value: ByteArray, destination: UByteArray, destinationOffset: Int = 0) = + hashInto(key, value, destination.asByteArray(), destinationOffset) + + fun hashInto(key: UByteArray, value: UByteArray, destination: ByteArray, destinationOffset: Int = 0) = + hashInto(key.asByteArray(), value.asByteArray(), destination, destinationOffset) + + fun hashInto(key: UByteArray, value: UByteArray, destination: UByteArray, destinationOffset: Int = 0) = + hashInto(key.asByteArray(), value.asByteArray(), destination.asByteArray(), destinationOffset) + + fun hash(key: ByteArray, value: ByteArray): ByteArray = + ByteArray(bytes).also { hashInto(key, value, it) } + + fun hash(key: UByteArray, value: UByteArray): UByteArray = + UByteArray(bytes).also { hashInto(key, value, it) } } diff --git a/src/commonTest/kotlin/com/infendro/mac/HMAC.kt b/src/commonTest/kotlin/com/infendro/mac/HMAC.kt index a88670a..2964ec3 100644 --- a/src/commonTest/kotlin/com/infendro/mac/HMAC.kt +++ b/src/commonTest/kotlin/com/infendro/mac/HMAC.kt @@ -1,6 +1,5 @@ package com.infendro.mac -import com.infendro.bytearray.encodeToUByteArray import com.infendro.hash.sha2.`SHA-256` import kotlin.test.Test import kotlin.test.assertContentEquals @@ -16,22 +15,21 @@ class `HMAC Test` { } @Test - fun `example`() { - assertContentEquals( - ubyteArrayOf( - 0xf7U, 0xbcU, 0x83U, 0xf4U, - 0x30U, 0x53U, 0x84U, 0x24U, - 0xb1U, 0x32U, 0x98U, 0xe6U, - 0xaaU, 0x6fU, 0xb1U, 0x43U, - 0xefU, 0x4dU, 0x59U, 0xa1U, - 0x49U, 0x46U, 0x17U, 0x59U, - 0x97U, 0x47U, 0x9dU, 0xbcU, - 0x2dU, 0x1aU, 0x3cU, 0xd8U, - ), - hmac.hash( - "key".encodeToUByteArray(), - "The quick brown fox jumps over the lazy dog".encodeToUByteArray() - ) + fun example() { + val expected = ubyteArrayOf( + 0xf7U, 0xbcU, 0x83U, 0xf4U, + 0x30U, 0x53U, 0x84U, 0x24U, + 0xb1U, 0x32U, 0x98U, 0xe6U, + 0xaaU, 0x6fU, 0xb1U, 0x43U, + 0xefU, 0x4dU, 0x59U, 0xa1U, + 0x49U, 0x46U, 0x17U, 0x59U, + 0x97U, 0x47U, 0x9dU, 0xbcU, + 0x2dU, 0x1aU, 0x3cU, 0xd8U, + ).asByteArray() + val actual = hmac.hash( + "key".encodeToByteArray(), + "The quick brown fox jumps over the lazy dog".encodeToByteArray(), ) + assertContentEquals(expected, actual) } } -- 2.49.1 From c11e80d22137819c93a3f9504a805fc347ddbaa3 Mon Sep 17 00:00:00 2001 From: Infendro Date: Thu, 22 Jan 2026 12:51:45 +0100 Subject: [PATCH 4/5] bump version to 1.3.0, add targets --- README.md | 2 +- build.gradle.kts | 15 +++++++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 23e2d9b..f392dd7 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ repositories { } dependencies { - implementation("com.infendro:mac:1.2.0") + implementation("com.infendro:mac:1.3.0") } ``` diff --git a/build.gradle.kts b/build.gradle.kts index 46874c8..168c970 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,8 +1,11 @@ +@file:OptIn(ExperimentalWasmDsl::class) + import com.infendro.plugin.infendro import com.infendro.plugin.token +import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl group = "com.infendro" -version = "1.2.0" +version = "1.3.0" plugins { alias(libs.plugins.infendro) @@ -13,9 +16,13 @@ plugins { kotlin { jvm() linuxX64() - js { - nodejs() - } + linuxArm64() + mingwX64() + macosX64() + macosArm64() + js { nodejs() } + wasmJs { nodejs() } + wasmWasi { nodejs() } repositories { infendro() -- 2.49.1 From 41d37cb42eb1a07dcad2c0c8d4607b27f86a70aa Mon Sep 17 00:00:00 2001 From: Infendro Date: Thu, 22 Jan 2026 12:57:34 +0100 Subject: [PATCH 5/5] split ci --- .gitea/workflows/ci.yaml | 92 ----------------------------------- .gitea/workflows/publish.yaml | 47 ++++++++++++++++++ .gitea/workflows/test.yaml | 28 +++++++++++ 3 files changed, 75 insertions(+), 92 deletions(-) delete mode 100644 .gitea/workflows/ci.yaml create mode 100644 .gitea/workflows/publish.yaml create mode 100644 .gitea/workflows/test.yaml diff --git a/.gitea/workflows/ci.yaml b/.gitea/workflows/ci.yaml deleted file mode 100644 index 2f46684..0000000 --- a/.gitea/workflows/ci.yaml +++ /dev/null @@ -1,92 +0,0 @@ -on: - push: - branches: [ develop, main ] - 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: 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: Test - run: ./gradlew allTests - - publish: - if: ${{ github.event_name == 'push' && github.ref_name == 'main' }} - needs: 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: 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 }} diff --git a/.gitea/workflows/publish.yaml b/.gitea/workflows/publish.yaml new file mode 100644 index 0000000..dad1306 --- /dev/null +++ b/.gitea/workflows/publish.yaml @@ -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 }} diff --git a/.gitea/workflows/test.yaml b/.gitea/workflows/test.yaml new file mode 100644 index 0000000..bce9e35 --- /dev/null +++ b/.gitea/workflows/test.yaml @@ -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 -- 2.49.1