package top.tangyh.lamp.filing.utils import io.github.oshai.kotlinlogging.KotlinLogging import org.springframework.beans.factory.annotation.Value import org.springframework.stereotype.Component import java.nio.charset.StandardCharsets import java.security.KeyFactory import java.security.PublicKey import java.security.spec.PKCS8EncodedKeySpec import java.security.spec.X509EncodedKeySpec import java.util.* import javax.crypto.Cipher private val logger = KotlinLogging.logger {} /** * RSA-OAEP 解密工具类 * 用于设备身份首次绑定时解密设备信息 * * 使用场景:设备使用平台的公钥加密数据,平台使用私钥解密 */ @Component class RsaOaepDecryptionUtil( @Value("\${device.encrypt.privateKey:}") private val privateKeyBase64: String ) { private val keyFactory = KeyFactory.getInstance("RSA") private val cipherAlgorithm = "RSA/ECB/OAEPWithSHA-256AndMGF1Padding" // 缓存私钥,避免每次解密都重新加载 private val privateKey by lazy { if (privateKeyBase64.isBlank()) { throw IllegalStateException("RSA私钥未配置,无法解密设备信息") } val privateKeyBytes = Base64.getDecoder().decode(privateKeyBase64) val keySpec = PKCS8EncodedKeySpec(privateKeyBytes) keyFactory.generatePrivate(keySpec) } init { if (privateKeyBase64.isBlank()) { logger.warn { "RSA私钥未配置,设备授权解密功能可能无法使用" } } } /** * 使用RSA-OAEP解密设备信息 * @param encryptedData Base64编码的加密数据 * @return 解密后的JSON字符串 */ fun decrypt(encryptedData: String): String { if (privateKeyBase64.isBlank()) { throw IllegalStateException("RSA私钥未配置,无法解密设备信息") } return try { // 创建新的Cipher实例(Cipher不是线程安全的) val cipher = Cipher.getInstance(cipherAlgorithm) // 初始化解密器 cipher.init(Cipher.DECRYPT_MODE, privateKey) // Base64解码加密数据 val encryptedBytes = Base64.getDecoder().decode(encryptedData) // 解密数据 val decryptedBytes = cipher.doFinal(encryptedBytes) // 返回解密后的字符串 String(decryptedBytes, StandardCharsets.UTF_8) } catch (e: Exception) { logger.error(e) { "RSA-OAEP解密设备信息失败" } throw RuntimeException("RSA-OAEP解密设备信息失败: ${e.message}", e) } } /** * 使用平台公钥加密数据 * * @param plainText 原始JSON字符串(设备信息) * @param publicKeyBase64 平台公钥(Base64) * @return Base64编码的密文 */ fun encrypt1( plainText: String, publicKeyBase64: String ): String { try { val publicKey = loadPublicKey(publicKeyBase64) val cipher = Cipher.getInstance(cipherAlgorithm) cipher.init(Cipher.ENCRYPT_MODE, publicKey) val encryptedBytes = cipher.doFinal( plainText.toByteArray(StandardCharsets.UTF_8) ) return Base64.getEncoder().encodeToString(encryptedBytes) } catch (e: Exception) { logger.error(e) { "RSA-OAEP 加密失败" } throw RuntimeException("RSA-OAEP 加密失败: ${e.message}", e) } } private fun loadPublicKey(base64Key: String): PublicKey { val keyBytes = Base64.getDecoder().decode(base64Key) val keySpec = X509EncodedKeySpec(keyBytes) return keyFactory.generatePublic(keySpec) } }