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

116 lines
3.8 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.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)
}
}