From 498a5b5826eac6ab7da1cd411bb211737a502128 Mon Sep 17 00:00:00 2001 From: Infendro Date: Sat, 13 Dec 2025 01:44:39 +0100 Subject: [PATCH] update dependencies, use common plugin --- build.gradle.kts | 46 ++++++------------- gradle/libs.versions.toml | 14 +++--- settings.gradle.kts | 5 ++ .../kotlin/com/infendro/otp/HOTP.kt | 35 +++++++------- .../com/infendro/otp/SecretGenerator.kt | 24 ++++------ .../kotlin/com/infendro/otp/TOTP.kt | 17 +++---- 6 files changed, 58 insertions(+), 83 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 9756c8e..3abd573 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,12 +1,11 @@ +import com.infendro.plugin.infendro +import com.infendro.plugin.token + group = "com.infendro" version = "1.1.1" -repositories { - maven("https://git.infendro.com/api/packages/Infendro/maven") - mavenCentral() -} - plugins { + alias(libs.plugins.infendro) alias(libs.plugins.multiplatform) id("maven-publish") } @@ -18,9 +17,14 @@ kotlin { } linuxX64() + repositories { + infendro() + mavenCentral() + } + sourceSets { commonMain.dependencies { - implementation(libs.random) + implementation(libs.prng) implementation(libs.mac) implementation(libs.hash) implementation(libs.bytearray) @@ -28,35 +32,11 @@ kotlin { } compilerOptions { + freeCompilerArgs.add("-opt-in=kotlin.ExperimentalUnsignedTypes") freeCompilerArgs.add("-opt-in=kotlin.time.ExperimentalTime") } } -publishing { - repositories { - maven { - url = uri("https://git.infendro.com/api/packages/Infendro/maven") - authentication.create("header", HttpHeaderAuthentication::class) - credentials(HttpHeaderCredentials::class) { - val token = secret("git.token") ?: throw GradleException() - - name = "Authorization" - value = "token $token" - } - } - } -} - -fun secret( - key: String, -): String? { - val property = key - val environment = key - .uppercase() - .replace(".", "__") - - val prop = properties[property] as String? - val env = System.getenv(environment) - - return prop ?: env +publishing.repositories { + infendro(token) } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 87727d7..1609a5c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,15 +1,17 @@ [versions] -kotlin = "2.1.20" -random = "1.0.0" -mac = "1.1.2" -hash = "1.2.2" -bytearray = "1.1.1" +infendro = "1.0.0" +kotlin = "2.2.21" +prng = "1.2.0" +mac = "1.2.0" +hash = "1.3.2" +bytearray = "1.2.4" [plugins] +infendro = { id = "com.infendro.plugin", version.ref = "infendro" } multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } [libraries] -random = { module = "com.infendro:random", version.ref = "random" } +prng = { module = "com.infendro:prng", version.ref = "prng" } mac = { module = "com.infendro:mac", version.ref = "mac" } hash = { module = "com.infendro:hash", version.ref = "hash" } bytearray = { module = "com.infendro:bytearray", version.ref = "bytearray" } diff --git a/settings.gradle.kts b/settings.gradle.kts index d4a641e..2123c21 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1 +1,6 @@ rootProject.name = "otp" + +pluginManagement.repositories { + maven("https://git.infendro.com/api/packages/Infendro/maven") + mavenCentral() +} diff --git a/src/commonMain/kotlin/com/infendro/otp/HOTP.kt b/src/commonMain/kotlin/com/infendro/otp/HOTP.kt index 28d6b37..d0113d6 100644 --- a/src/commonMain/kotlin/com/infendro/otp/HOTP.kt +++ b/src/commonMain/kotlin/com/infendro/otp/HOTP.kt @@ -1,19 +1,20 @@ package com.infendro.otp -import com.infendro.bytearray.toByteArray import com.infendro.bytearray.toInt +import com.infendro.bytearray.toUByteArray import com.infendro.hash.HashFunction -import com.infendro.hash.SHA1 +import com.infendro.hash.sha1.SHA1 import com.infendro.mac.HMAC -import kotlin.experimental.and import kotlin.math.pow class HOTP( val function: HashFunction = SHA1, val length: Int = 6, ) { + private val hmac = HMAC(function) + fun verify( - secret: ByteArray, + secret: UByteArray, counter: Long, otp: String, ): Boolean { @@ -21,33 +22,31 @@ class HOTP( } fun generate( - secret: ByteArray, + secret: UByteArray, counter: Long, ): String { - if (counter < 0) throw Exception() + if (counter < 0) + throw IllegalArgumentException() - val hash = generateHash( - secret, - counter.toByteArray() - ) + val hash = generateHash(secret, counter.toUByteArray()) return otp(hash) } private fun generateHash( - secret: ByteArray, - value: ByteArray, - ): ByteArray { - return HMAC(function).hash(secret, value) + secret: UByteArray, + value: UByteArray, + ): UByteArray { + return hmac.hash(secret, value) } private fun otp( - hash: ByteArray, + hash: UByteArray, ): String { - val offset = (hash.last() and 0xF).toInt() + val offset = (hash.last() and 0xFU).toInt() var truncatedHash = hash - .drop(offset) - .take(4) + .drop(offset).take(4) + .toUByteArray() .toInt() and 0x7FFFFFFF truncatedHash %= 10.0.pow(length).toInt() diff --git a/src/commonMain/kotlin/com/infendro/otp/SecretGenerator.kt b/src/commonMain/kotlin/com/infendro/otp/SecretGenerator.kt index 4c04f76..d394433 100644 --- a/src/commonMain/kotlin/com/infendro/otp/SecretGenerator.kt +++ b/src/commonMain/kotlin/com/infendro/otp/SecretGenerator.kt @@ -1,22 +1,14 @@ package com.infendro.otp -import com.infendro.hash.* -import com.infendro.random.PRNG +import com.infendro.hash.HashFunction +import com.infendro.random.csprng.CSPRNG -object SecretGenerator { - private val random = PRNG.HMAC +class SecretGenerator( + val function: HashFunction, +) { + private val random = CSPRNG.HMAC(function) - fun generate( - algorithm: HashFunction = SHA1, - ): ByteArray { - val bytes = when (algorithm) { - MD5 -> 16 - SHA1 -> 20 - SHA224 -> 28 - SHA256 -> 32 - SHA384 -> 48 - SHA512 -> 64 - } - return random.nextBytes(bytes) + fun generate(): ByteArray { + return random.nextBytes(function.bytes) } } diff --git a/src/commonMain/kotlin/com/infendro/otp/TOTP.kt b/src/commonMain/kotlin/com/infendro/otp/TOTP.kt index c6c2bca..5e1a6cc 100644 --- a/src/commonMain/kotlin/com/infendro/otp/TOTP.kt +++ b/src/commonMain/kotlin/com/infendro/otp/TOTP.kt @@ -1,20 +1,20 @@ package com.infendro.otp import com.infendro.hash.HashFunction -import com.infendro.hash.SHA1 +import com.infendro.hash.sha1.SHA1 import kotlin.time.Duration import kotlin.time.Duration.Companion.seconds import kotlin.time.Instant class TOTP( - function: HashFunction = SHA1, - length: Int = 6, + val function: HashFunction = SHA1, + val length: Int = 6, val period: Duration = 30.seconds, ) { - val hotp = HOTP(function, length) + private val hotp = HOTP(function, length) fun verify( - secret: ByteArray, + secret: UByteArray, instant: Instant, otp: String, ): Boolean { @@ -22,13 +22,10 @@ class TOTP( } fun generate( - secret: ByteArray, + secret: UByteArray, instant: Instant, ): String { - return hotp.generate( - secret, - counter(instant) - ) + return hotp.generate(secret, counter(instant)) } private fun counter(