From f78b10f565ff30c15d4072654aeff13fb9ee1fb9 Mon Sep 17 00:00:00 2001 From: Infendro Date: Tue, 3 Feb 2026 23:42:46 +0100 Subject: [PATCH] upgrade --- README.md | 20 ++------ build.gradle.kts | 17 +++++-- gradle/libs.versions.toml | 12 ++--- src/commonMain/kotlin/com/infendro/kdf/KDF.kt | 20 ++++++-- .../kotlin/com/infendro/kdf/PBKDF2.kt | 47 ++++++++----------- .../kotlin/com/infendro/kdf/util/Math.kt | 4 ++ .../kotlin/com/infendro/kdf/PBKDF2.kt | 37 +++++++-------- 7 files changed, 79 insertions(+), 78 deletions(-) create mode 100644 src/commonMain/kotlin/com/infendro/kdf/util/Math.kt diff --git a/README.md b/README.md index 3eee0bb..d46eb45 100644 --- a/README.md +++ b/README.md @@ -5,15 +5,6 @@ Supported algorithms: - PBKDF2 -## Targets - -| Target | Status | -|------------------|---------------| -| JVM | Supported | -| JavaScript | Supported | -| Native (Linux) | Supported | -| Native (Windows) | Not Supported | - ## Installation Add the following to your `build.gradle.kts`. @@ -24,24 +15,21 @@ repositories { } dependencies { - implementation("com.infendro:kdf:1.1.0") + implementation("com.infendro:kdf:1.2.0") } ``` ## Usage ```kotlin -import com.infendro.hash.`SHA-256` -import com.infendro.kdf.PBKDF2 - fun main() { - // create a PBKDF2 instance using HMAC SHA256 + // create a PBKDF2 instance using HMAC SHA-256 // this example uses 32 bytes of length and 100_000 iterations val kdf = PBKDF2(32, 100_000, `SHA-256`) // securely hash value with some salt - val value = "password".encodeToByteArray().asUByteArray() - val salt = "salt".encodeToByteArray().asUByteArray() + val value = "password".encodeToByteArray() + val salt = "salt".encodeToByteArray() val hash = kdf.hash(value, salt) } ``` diff --git a/build.gradle.kts b/build.gradle.kts index 5c442e1..ee45012 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.1.0" +version = "1.2.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() @@ -26,7 +33,7 @@ kotlin { commonMain.dependencies { implementation(libs.mac) 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 06180ff..fe31bde 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,9 +1,9 @@ [versions] -infendro = "1.0.0" -kotlin = "2.2.21" -mac = "1.2.0" -hash = "1.3.2" -bytearray = "1.2.4" +infendro = "1.1.0" +kotlin = "2.3.0" +mac = "1.3.0" +hash = "1.5.1" +bytes = "1.3.4" [plugins] infendro = { id = "com.infendro.plugin", version.ref = "infendro" } @@ -12,5 +12,5 @@ multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotl [libraries] mac = { module = "com.infendro:mac", version.ref = "mac" } 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/kdf/KDF.kt b/src/commonMain/kotlin/com/infendro/kdf/KDF.kt index 50c31fe..c0c6c61 100644 --- a/src/commonMain/kotlin/com/infendro/kdf/KDF.kt +++ b/src/commonMain/kotlin/com/infendro/kdf/KDF.kt @@ -5,8 +5,20 @@ interface KDF { val bits: Int get() = bytes * 8 - fun hash( - value: UByteArray, - salt: UByteArray, - ): UByteArray + fun hashInto(value: ByteArray, salt: ByteArray, destination: ByteArray, destinationOffset: Int = 0) + + fun hashInto(value: ByteArray, salt: ByteArray, destination: UByteArray, destinationOffset: Int = 0) = + hashInto(value, salt, destination.asByteArray(), destinationOffset) + + fun hashInto(value: UByteArray, salt: UByteArray, destination: ByteArray, destinationOffset: Int = 0) = + hashInto(value.asByteArray(), salt.asByteArray(), destination, destinationOffset) + + fun hashInto(value: UByteArray, salt: UByteArray, destination: UByteArray, destinationOffset: Int = 0) = + hashInto(value.asByteArray(), salt.asByteArray(), destination.asByteArray(), destinationOffset) + + fun hash(value: ByteArray, salt: ByteArray): ByteArray = + ByteArray(bytes).also { hashInto(value, salt, it) } + + fun hash(value: UByteArray, salt: UByteArray): UByteArray = + UByteArray(bytes).also { hashInto(value, salt, it) } } diff --git a/src/commonMain/kotlin/com/infendro/kdf/PBKDF2.kt b/src/commonMain/kotlin/com/infendro/kdf/PBKDF2.kt index c09a68a..6557d20 100644 --- a/src/commonMain/kotlin/com/infendro/kdf/PBKDF2.kt +++ b/src/commonMain/kotlin/com/infendro/kdf/PBKDF2.kt @@ -1,10 +1,10 @@ package com.infendro.kdf -import com.infendro.bytearray.toUByteArray -import com.infendro.bytearray.xor +import com.infendro.bytes.bytearray.xorInto +import com.infendro.bytes.int.copyInto import com.infendro.hash.HashFunction +import com.infendro.kdf.util.ceilDiv import com.infendro.mac.HMAC -import kotlin.math.min class PBKDF2( override val bytes: Int, @@ -16,34 +16,25 @@ class PBKDF2( require(iterations > 0) } - private val mac = HMAC(function) + private val hmac = HMAC(function) - override fun hash( - value: UByteArray, - salt: UByteArray, - ): UByteArray { - return buildList { - var i = 1 - while (size < bytes) { - addAll( - f(value, salt, i) - .sliceArray(0.. acc xor bytes } + } } } diff --git a/src/commonMain/kotlin/com/infendro/kdf/util/Math.kt b/src/commonMain/kotlin/com/infendro/kdf/util/Math.kt new file mode 100644 index 0000000..3af28df --- /dev/null +++ b/src/commonMain/kotlin/com/infendro/kdf/util/Math.kt @@ -0,0 +1,4 @@ +package com.infendro.kdf.util + +internal fun Int.ceilDiv(n: Int): Int = + (this + n - 1) / n diff --git a/src/commonTest/kotlin/com/infendro/kdf/PBKDF2.kt b/src/commonTest/kotlin/com/infendro/kdf/PBKDF2.kt index 7c5681b..ea32483 100644 --- a/src/commonTest/kotlin/com/infendro/kdf/PBKDF2.kt +++ b/src/commonTest/kotlin/com/infendro/kdf/PBKDF2.kt @@ -1,6 +1,5 @@ package com.infendro.kdf -import com.infendro.bytearray.encodeToUByteArray import com.infendro.hash.sha2.`SHA-256` import kotlin.test.Test import kotlin.test.assertContentEquals @@ -15,10 +14,10 @@ class `PBKDF2 Test` { 0x43U, 0xe7U, 0x22U, 0x52U, 0x56U, 0xc4U, 0xf8U, 0x37U, 0xa8U, 0x65U, 0x48U, 0xc9U, 0x2cU, 0xccU, 0x35U, 0x48U, 0x08U, 0x05U, 0x98U, 0x7cU, 0xb7U, 0x0bU, 0xe1U, 0x7bU, - ) + ).asByteArray() val actual = function.hash( - "password".encodeToUByteArray(), - "salt".encodeToUByteArray(), + "password".encodeToByteArray(), + "salt".encodeToByteArray(), ) assertContentEquals(expected, actual) } @@ -32,10 +31,10 @@ class `PBKDF2 Test` { 0x2dU, 0x0aU, 0xdfU, 0xf9U, 0x28U, 0xf0U, 0x6dU, 0xd0U, 0x2aU, 0x30U, 0x3fU, 0x8eU, 0xf3U, 0xc2U, 0x51U, 0xdfU, 0xd6U, 0xe2U, 0xd8U, 0x5aU, 0x95U, 0x47U, 0x4cU, 0x43U, - ) + ).asByteArray() val actual = function.hash( - "password".encodeToUByteArray(), - "salt".encodeToUByteArray(), + "password".encodeToByteArray(), + "salt".encodeToByteArray(), ) assertContentEquals(expected, actual) } @@ -49,10 +48,10 @@ class `PBKDF2 Test` { 0xaaU, 0x53U, 0x0dU, 0xb6U, 0x84U, 0x5cU, 0x4cU, 0x8dU, 0x96U, 0x28U, 0x93U, 0xa0U, 0x01U, 0xceU, 0x4eU, 0x11U, 0xa4U, 0x96U, 0x38U, 0x73U, 0xaaU, 0x98U, 0x13U, 0x4aU, - ) + ).asByteArray() val actual = function.hash( - "password".encodeToUByteArray(), - "salt".encodeToUByteArray(), + "password".encodeToByteArray(), + "salt".encodeToByteArray(), ) assertContentEquals(expected, actual) } @@ -67,10 +66,10 @@ class `PBKDF2 Test` { 0x96U, 0x28U, 0x93U, 0xa0U, 0x01U, 0xceU, 0x4eU, 0x11U, 0xa4U, 0x96U, 0x38U, 0x73U, 0xaaU, 0x98U, 0x13U, 0x4aU, 0xf7U, 0xadU, 0x98U, 0xc1U, 0xb4U, 0x58U, 0xceU, 0x3fU, - ) + ).asByteArray() val actual = function.hash( - "password".encodeToUByteArray(), - "salt".encodeToUByteArray(), + "password".encodeToByteArray(), + "salt".encodeToByteArray(), ) assertContentEquals(expected, actual) } @@ -88,10 +87,10 @@ class `PBKDF2 Test` { 0x99U, 0x16U, 0x64U, 0xb3U, 0x9dU, 0x77U, 0xefU, 0x31U, 0x7cU, 0x71U, 0xb8U, 0x45U, 0xb1U, 0xe3U, 0x0bU, 0xd5U, 0x09U, 0x11U, 0x20U, 0x41U, 0xd3U, 0xa1U, 0x97U, 0x83U, - ) + ).asByteArray() val actual = function.hash( - "passwd".encodeToUByteArray(), - "salt".encodeToUByteArray(), + "passwd".encodeToByteArray(), + "salt".encodeToByteArray(), ) assertContentEquals(expected, actual) } @@ -109,10 +108,10 @@ class `PBKDF2 Test` { 0x9aU, 0xdbU, 0x84U, 0x1bU, 0x51U, 0xc9U, 0xb3U, 0x17U, 0x6aU, 0x27U, 0x2bU, 0xdeU, 0xbbU, 0xa1U, 0xd0U, 0x78U, 0x47U, 0x8fU, 0x62U, 0xb3U, 0x97U, 0xf3U, 0x3cU, 0x8dU, - ) + ).asByteArray() val actual = function.hash( - "Password".encodeToByteArray().toUByteArray(), - "NaCl".encodeToByteArray().toUByteArray() + "Password".encodeToByteArray(), + "NaCl".encodeToByteArray(), ) assertContentEquals(expected, actual) }