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) } } }