Files
fullstack-starter/docs/工具箱端-授权对接指南/utils/HkdfUtil.kt

67 lines
2.5 KiB
Kotlin
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package top.tangyh.lamp.filing.utils
import io.github.oshai.kotlinlogging.KotlinLogging
import org.bouncycastle.crypto.digests.SHA256Digest
import org.bouncycastle.crypto.generators.HKDFBytesGenerator
import org.bouncycastle.crypto.params.HKDFParameters
import java.nio.charset.StandardCharsets
private val logger = KotlinLogging.logger {}
/**
* HKDF (HMAC-based Key Derivation Function) 工具类
* 用于从 licence + fingerprint 派生设备签名密钥
*
* 安全设计说明:
* - 使用 HKDF 而非直接哈希,提供更好的密钥分离和扩展性
* - Salt 固定为 "AUTH_V3_SALT",确保同一输入产生相同密钥
* - Info 参数用于区分不同用途的密钥派生device_report_signature
* - 输出长度 32 字节256位适用于 HMAC-SHA256
*/
object HkdfUtil {
private const val SALT = "AUTH_V3_SALT"
private const val INFO = "device_report_signature"
private const val KEY_LENGTH = 32 // 32 bytes = 256 bits
/**
* 使用 HKDF 派生密钥(使用默认 salt 和 info
*
* @param input 输入密钥材料licence + fingerprint
* @return 派生出的密钥32字节
*/
fun deriveKey(input: String): ByteArray {
return deriveKey(input, SALT, INFO)
}
/**
* 使用 HKDF 派生密钥(支持自定义 salt 和 info
*
* @param input 输入密钥材料licence + fingerprint
* @param salt Salt 值(用于密钥派生)
* @param info Info 值(用于区分不同用途的密钥)
* @param keyLength 输出密钥长度默认32字节
* @return 派生出的密钥
*/
fun deriveKey(input: String, salt: String, info: String, keyLength: Int = KEY_LENGTH): ByteArray {
return try {
val inputBytes = input.toByteArray(StandardCharsets.UTF_8)
val saltBytes = salt.toByteArray(StandardCharsets.UTF_8)
val infoBytes = info.toByteArray(StandardCharsets.UTF_8)
val hkdf = HKDFBytesGenerator(SHA256Digest())
val params = HKDFParameters(inputBytes, saltBytes, infoBytes)
hkdf.init(params)
val derivedKey = ByteArray(keyLength)
hkdf.generateBytes(derivedKey, 0, keyLength)
derivedKey
} catch (e: Exception) {
logger.error(e) { "HKDF 密钥派生失败: input=$input, salt=$salt, info=$info" }
throw RuntimeException("HKDF 密钥派生失败: ${e.message}", e)
}
}
}