upgrade
Some checks failed
/ test (push) Has been cancelled
/ publish (push) Has been cancelled

too tired to write a detailed commit message or split into self-explanatory commits
This commit is contained in:
2026-01-29 18:11:17 +01:00
parent f85e22311d
commit d2b901a6ff
7 changed files with 50 additions and 108 deletions

View File

@@ -1,55 +1,32 @@
package com.infendro.otp
import com.infendro.bytearray.toInt
import com.infendro.bytearray.toUByteArray
import com.infendro.bytes.bytearray.toInt
import com.infendro.bytes.long.toByteArray
import com.infendro.hash.HashFunction
import com.infendro.hash.sha1.SHA1
import com.infendro.mac.HMAC
import kotlin.math.pow
import com.infendro.otp.util.pow
import kotlin.experimental.and
class HOTP(
function: HashFunction = SHA1,
private val length: Int = 6,
val function: HashFunction = SHA1,
val length: Int = 6,
) {
private val hmac = HMAC(function)
fun verify(
secret: UByteArray,
counter: Long,
otp: String,
): Boolean {
fun verify(secret: ByteArray, counter: Long, otp: String): Boolean {
return generate(secret, counter) == otp
}
fun generate(
secret: UByteArray,
counter: Long,
): String {
fun generate(secret: ByteArray, counter: Long): String {
require(counter >= 0)
val hash = generateHash(secret, counter.toUByteArray())
return otp(hash)
return otp(secret, counter)
}
private fun generateHash(
secret: UByteArray,
value: UByteArray,
): UByteArray {
return hmac.hash(secret, value)
}
private fun otp(
hash: UByteArray,
): String {
val offset = (hash.last() and 0xFU).toInt()
var truncatedHash = hash
.drop(offset).take(4)
.toUByteArray()
.toInt() and 0x7FFFFFFF
truncatedHash %= 10.0.pow(length).toInt()
return truncatedHash.toString()
.padStart(length, '0')
private fun otp(secret: ByteArray, counter: Long): String {
val hash = hmac.hash(secret, counter.toByteArray())
val offset = (hash.last() and 0xF).toInt()
val otp = (hash.toInt(offset) and 0x7FFFFFFF) % 10.pow(length)
return "$otp".padStart(length, '0')
}
}