diff --git a/pom.xml b/pom.xml index cf6a8f7..70038f1 100644 --- a/pom.xml +++ b/pom.xml @@ -163,6 +163,11 @@ core 3.3.3 + + cn.hutool + hutool-http + 5.8.31 + diff --git a/src/main/kotlin/info/alinadace/sakuramiki/service/jm/util/DownloadUtil.kt b/src/main/kotlin/info/alinadace/sakuramiki/service/jm/util/DownloadUtil.kt index 1801157..5be375a 100644 --- a/src/main/kotlin/info/alinadace/sakuramiki/service/jm/util/DownloadUtil.kt +++ b/src/main/kotlin/info/alinadace/sakuramiki/service/jm/util/DownloadUtil.kt @@ -47,12 +47,6 @@ class DownloadUtil { return this.newCall(Request.Builder() .url(url) .method(method, body) -//// .addHeader("Content-Type", "application/json") -//// .addHeader("Authorization", "Bearer $APIKEY") -// .addHeader("User-Agent", "Apifox/1.0.0 (https://apifox.com)") -// .addHeader("Accept", "*/*") -// .addHeader("Host", "api.github.com") -// .addHeader("Connection", "keep-alive") .build()).execute() } } diff --git a/src/main/kotlin/info/alinadace/sakuramiki/service/mfa/MFAGenerateService.kt b/src/main/kotlin/info/alinadace/sakuramiki/service/mfa/MFAGenerateService.kt index 3bff029..3b90462 100644 --- a/src/main/kotlin/info/alinadace/sakuramiki/service/mfa/MFAGenerateService.kt +++ b/src/main/kotlin/info/alinadace/sakuramiki/service/mfa/MFAGenerateService.kt @@ -57,7 +57,7 @@ class MFAGenerateService : Service { event.send("您还没有绑定默认MFA,使用 #mfa bind default 绑定默认MFA") return } - event.send(MFAUtil.generate(mfa.secret, 30)) + event.send(MFAUtil.generate(mfa.secret)) return } if (command.size == 2){ @@ -70,7 +70,7 @@ class MFAGenerateService : Service { event.send("您还没有绑定${command[1]} MFA,使用 #mfa bind ${command[1]} 绑定${command[1]} MFA") return } - event.send(MFAUtil.generate(mfa.secret, 30)) + event.send(MFAUtil.generate(mfa.secret)) return } } diff --git a/src/main/kotlin/info/alinadace/sakuramiki/util/JsonUtil.kt b/src/main/kotlin/info/alinadace/sakuramiki/util/JsonUtil.kt index a3b3f66..9f6bffe 100644 --- a/src/main/kotlin/info/alinadace/sakuramiki/util/JsonUtil.kt +++ b/src/main/kotlin/info/alinadace/sakuramiki/util/JsonUtil.kt @@ -7,7 +7,15 @@ import com.fasterxml.jackson.databind.ObjectMapper * @author Kane * @since 2025/3/24 16:10 */ -private val OBJECT_MAPPER = ObjectMapper() +val OBJECT_MAPPER = ObjectMapper() fun parse(json: String): Dict { return OBJECT_MAPPER.readValue(json, OBJECT_MAPPER.typeFactory.constructType(Dict::class.java)) } + +inline fun T.toJson(): String { + return OBJECT_MAPPER.writeValueAsString(this) +} + +inline fun T.ofJson(json: String): T{ + return OBJECT_MAPPER.readValue(json, T::class.java) +} diff --git a/src/main/kotlin/info/alinadace/sakuramiki/util/MFAUtil.kt b/src/main/kotlin/info/alinadace/sakuramiki/util/MFAUtil.kt index 1987872..64d62fd 100644 --- a/src/main/kotlin/info/alinadace/sakuramiki/util/MFAUtil.kt +++ b/src/main/kotlin/info/alinadace/sakuramiki/util/MFAUtil.kt @@ -11,41 +11,53 @@ import kotlin.math.pow * @since 2025/3/18 16:01 */ class MFAUtil { - companion object{ + companion object { private const val ALGORITHM = "HmacSHA1" private val mac = Mac.getInstance(ALGORITHM) + private const val CODE_DIGITS = 6 + private const val CODE_MODULUS = 10.0 + /** * 生成 MFA 验证码 */ fun generate(key: String, step: Int): String { - val data = ByteArray(8) - var value = System.currentTimeMillis() / 1000 / step - run { - var i = 8 - while (i-- > 0) { + return try { + val data = ByteArray(8) + var value = System.currentTimeMillis() / 1000 / step + + for (i in 7 downTo 0) { data[i] = value.toByte() value = value ushr 8 } + + val decodedKey = Base32.decode(key) + val signKey = SecretKeySpec(decodedKey, ALGORITHM) + mac.init(signKey) + val hash = mac.doFinal(data) + val offset = hash[hash.size - 1].toInt() and 0xF + + var truncatedHash: Long = 0 + + for (i in 0..3) { + truncatedHash = truncatedHash shl 8 + truncatedHash = truncatedHash or (hash[offset + i].toInt() and 0xFF).toLong() + } + + truncatedHash = truncatedHash and 0x7FFFFFFFL + truncatedHash %= CODE_MODULUS.pow(CODE_DIGITS).toLong() + + "%0${CODE_DIGITS}d".format(truncatedHash) + } catch (e: Exception) { + throw RuntimeException("Failed to generate MFA code", e) } - - val decodedKey = Base32.decode(key) - val signKey = SecretKeySpec(decodedKey, ALGORITHM) - mac.init(signKey) - val hash = mac.doFinal(data) - println(hash.contentToString()) - val offset = hash[hash.size - 1].toInt() and 0xF - - var truncatedHash: Long = 0 - - for (i in 0..3) { - truncatedHash = truncatedHash shl 8 - truncatedHash = truncatedHash or (hash[offset + i].toInt() and 0xFF).toLong() - } - - truncatedHash = truncatedHash and 0x7FFFFFFFL - truncatedHash %= 10.0.pow(6.0).toLong() - - return String.format("%0" + 6 + "d", truncatedHash) } + + /** + * 生成默认步长(30秒)的 MFA 验证码 + * + * @param key Base32编码的密钥 + * @return 6位数字验证码 + */ + fun generate(key: String): String = generate(key, 30) } }