67 lines
2.5 KiB
Kotlin
67 lines
2.5 KiB
Kotlin
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)
|
||
}
|
||
}
|
||
}
|
||
|