Merge pull request '1.3.1 Release' (#3) from develop into main
All checks were successful
/ publish (push) Successful in 3m6s

Reviewed-on: Infendro/otp-kt#3
This commit was merged in pull request #3.
This commit is contained in:
2026-03-12 10:34:21 +00:00
committed by Gitea
5 changed files with 16 additions and 16 deletions

View File

@@ -16,7 +16,7 @@ repositories {
} }
dependencies { dependencies {
implementation("com.infendro:otp:1.3.0") implementation("com.infendro:otp:1.3.1")
} }
``` ```
@@ -26,7 +26,7 @@ dependencies {
fun main() { fun main() {
// create TOTP instance // create TOTP instance
val totp = TOTP( val totp = TOTP(
function = SHA1, function = SHA1(),
length = 6, length = 6,
period = 30.seconds, period = 30.seconds,
) )

View File

@@ -5,7 +5,7 @@ import com.infendro.plugin.token
import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
group = "com.infendro" group = "com.infendro"
version = "1.3.0" version = "1.3.1"
plugins { plugins {
alias(libs.plugins.infendro) alias(libs.plugins.infendro)

View File

@@ -1,9 +1,9 @@
[versions] [versions]
infendro = "1.1.0" infendro = "1.1.0"
kotlin = "2.3.0" kotlin = "2.3.0"
bytes = "1.4.0" bytes = "1.4.2"
hash = "1.6.0" hash = "1.7.0"
mac = "1.4.0" mac = "1.5.0"
[plugins] [plugins]
infendro = { id = "com.infendro.plugin", version.ref = "infendro" } infendro = { id = "com.infendro.plugin", version.ref = "infendro" }

View File

@@ -9,7 +9,7 @@ import com.infendro.otp.util.pow
import kotlin.experimental.and import kotlin.experimental.and
class HOTP( class HOTP(
val function: HashFunction = SHA1, val function: HashFunction = SHA1(),
val length: Int = 6, val length: Int = 6,
) { ) {
private val hmac = HMAC(function) private val hmac = HMAC(function)
@@ -19,14 +19,14 @@ class HOTP(
return otp(secret, counter) return otp(secret, counter)
} }
fun verify(secret: ByteArray, counter: Long, otp: String): Boolean {
return generate(secret, counter) == otp
}
private fun otp(secret: ByteArray, counter: Long): String { private fun otp(secret: ByteArray, counter: Long): String {
val hash = hmac.hash(secret, counter.toByteArray()) val hash = hmac.hash(secret, counter.toByteArray())
val offset = (hash.last() and 0xF).toInt() val offset = (hash.last() and 0xF).toInt()
val otp = (hash.toInt(offset) and 0x7FFFFFFF) % 10.pow(length) val otp = (hash.toInt(offset) and 0x7FFFFFFF) % 10.pow(length)
return "$otp".padStart(length, '0') return "$otp".padStart(length, '0')
} }
fun verify(secret: ByteArray, counter: Long, otp: String): Boolean {
return generate(secret, counter) == otp
}
} }

View File

@@ -7,7 +7,7 @@ import kotlin.time.Duration.Companion.seconds
import kotlin.time.Instant import kotlin.time.Instant
class TOTP( class TOTP(
val function: HashFunction = SHA1, val function: HashFunction = SHA1(),
val length: Int = 6, val length: Int = 6,
val period: Duration = 30.seconds, val period: Duration = 30.seconds,
) { ) {
@@ -17,13 +17,13 @@ class TOTP(
return hotp.generate(secret, counter(instant)) return hotp.generate(secret, counter(instant))
} }
fun verify(secret: ByteArray, instant: Instant, otp: String): Boolean {
return generate(secret, instant) == otp
}
private fun counter(instant: Instant): Long { private fun counter(instant: Instant): Long {
val ms = instant.toEpochMilliseconds() val ms = instant.toEpochMilliseconds()
val d = period.inWholeMilliseconds val d = period.inWholeMilliseconds
return ms / d return ms / d
} }
fun verify(secret: ByteArray, instant: Instant, otp: String): Boolean {
return generate(secret, instant) == otp
}
} }