docs: 添加管理平台标准加密算法 Kotlin 参考实现

This commit is contained in:
2026-03-06 15:34:04 +08:00
parent 2651ec0835
commit 4d64cfb93d
12 changed files with 935 additions and 0 deletions

View File

@@ -0,0 +1,120 @@
package top.tangyh.lamp.filing.utils
import io.github.oshai.kotlinlogging.KotlinLogging
import java.nio.charset.StandardCharsets
import java.security.MessageDigest
import java.security.SecureRandom
import java.util.*
import javax.crypto.Cipher
import javax.crypto.spec.GCMParameterSpec
import javax.crypto.spec.SecretKeySpec
private val logger = KotlinLogging.logger {}
/**
* 任务加密工具类
* 使用 licence + fingerprint 作为密钥对任务数据进行 AES-256-GCM 对称加密
*
* GCM 模式提供认证加密,比 ECB 模式更安全
* 加密数据格式IV(12字节) + 加密数据 + 认证标签(16字节)
*/
object TaskEncryptionUtil {
private const val ALGORITHM = "AES"
private const val TRANSFORMATION = "AES/GCM/NoPadding"
private const val GCM_IV_LENGTH = 12 // GCM 推荐使用 12 字节 IV
private const val GCM_TAG_LENGTH = 16 // GCM 认证标签长度128位
private const val KEY_LENGTH = 32 // AES-256 密钥长度256位 = 32字节
private val secureRandom = SecureRandom()
/**
* 使用 licence + fingerprint 加密任务数据AES-256-GCM
* @param data 待加密的数据JSON字符串
* @param licence 授权码
* @param fingerprint 硬件指纹
* @return Base64编码的加密数据包含IV + 加密数据 + 认证标签)
*/
fun encrypt(data: String, licence: String, fingerprint: String): String {
return try {
// 使用 licence + fingerprint 生成密钥
val key = generateKey(licence, fingerprint)
// 生成随机 IV12字节
val iv = ByteArray(GCM_IV_LENGTH)
secureRandom.nextBytes(iv)
// 创建加密器
val cipher = Cipher.getInstance(TRANSFORMATION)
val parameterSpec = GCMParameterSpec(GCM_TAG_LENGTH * 8, iv) // 标签长度以位为单位
cipher.init(Cipher.ENCRYPT_MODE, key, parameterSpec)
// 加密数据
val encryptedBytes = cipher.doFinal(data.toByteArray(StandardCharsets.UTF_8))
// 组合IV + 加密数据(包含认证标签)
val combined = ByteArray(iv.size + encryptedBytes.size)
System.arraycopy(iv, 0, combined, 0, iv.size)
System.arraycopy(encryptedBytes, 0, combined, iv.size, encryptedBytes.size)
// 返回 Base64 编码的加密数据
Base64.getEncoder().encodeToString(combined)
} catch (e: Exception) {
logger.error(e) { "AES-256-GCM加密任务数据失败" }
throw RuntimeException("加密任务数据失败: ${e.message}", e)
}
}
/**
* 使用 licence + fingerprint 解密任务数据AES-256-GCM
* @param encryptedData Base64编码的加密数据包含IV + 加密数据 + 认证标签)
* @param licence 授权码
* @param fingerprint 硬件指纹
* @return 解密后的数据JSON字符串
*/
fun decrypt(encryptedData: String, licence: String, fingerprint: String): String {
return try {
// 使用 licence + fingerprint 生成密钥
val key = generateKey(licence, fingerprint)
// Base64 解码
val combined = Base64.getDecoder().decode(encryptedData)
// 分离 IV 和加密数据
if (combined.size < GCM_IV_LENGTH) {
throw IllegalArgumentException("加密数据格式错误:数据长度不足")
}
val iv = combined.sliceArray(0 until GCM_IV_LENGTH)
val cipherText = combined.sliceArray(GCM_IV_LENGTH until combined.size)
// 创建解密器
val cipher = Cipher.getInstance(TRANSFORMATION)
val parameterSpec = GCMParameterSpec(GCM_TAG_LENGTH * 8, iv)
cipher.init(Cipher.DECRYPT_MODE, key, parameterSpec)
// 解密数据GCM 会自动验证认证标签)
val decryptedBytes = cipher.doFinal(cipherText)
// 返回解密后的字符串
String(decryptedBytes, StandardCharsets.UTF_8)
} catch (e: Exception) {
logger.error(e) { "AES-256-GCM解密任务数据失败" }
throw RuntimeException("解密任务数据失败: ${e.message}", e)
}
}
/**
* 使用 licence + fingerprint 生成 AES-256 密钥256位 = 32字节
* 使用 SHA-256 哈希的全部32字节作为密钥
*/
private fun generateKey(licence: String, fingerprint: String): SecretKeySpec {
val combined = "$licence$fingerprint"
val digest = MessageDigest.getInstance("SHA-256")
val hash = digest.digest(combined.toByteArray(StandardCharsets.UTF_8))
// 使用全部32字节作为 AES-256 密钥
return SecretKeySpec(hash, ALGORITHM)
}
}