174 lines
4.8 KiB
Swift
174 lines
4.8 KiB
Swift
//
|
||
// SPCryptService.swift
|
||
// MoviaBox
|
||
//
|
||
// Created by 曾觉新 on 2025/4/10.
|
||
//
|
||
|
||
import UIKit
|
||
|
||
class SPCryptService: NSObject {
|
||
|
||
static let BF_SIZE = 2048
|
||
static let EN_STR_TAG = "$"
|
||
|
||
// 生成随机盐
|
||
static func randSalt() -> Data {
|
||
let size = Int.random(in: 16...64) // 随机盐的长度
|
||
var salt = Data(capacity: size)
|
||
|
||
for _ in 0..<size {
|
||
salt.append(UInt8.random(in: 0...255))
|
||
}
|
||
|
||
return salt
|
||
}
|
||
|
||
// 加密数据
|
||
static func encrypt(_ data: String) -> String? {
|
||
guard !data.isEmpty else {
|
||
return data
|
||
}
|
||
|
||
// 确保数据是UTF-8编码
|
||
guard let utf8Data = data.data(using: .utf8) else {
|
||
return nil
|
||
}
|
||
|
||
// 随机盐
|
||
let salt = randSalt()
|
||
let saltLen = UInt8(salt.count)
|
||
|
||
// 加密数据
|
||
guard let encryptedData = encryptWithSalt(utf8Data, salt: salt) else {
|
||
return nil
|
||
}
|
||
|
||
// 构建完整加密数据: [盐长度(1字节)][盐][加密数据]
|
||
var fullEncryptedData = Data()
|
||
fullEncryptedData.append(saltLen)
|
||
fullEncryptedData.append(salt)
|
||
fullEncryptedData.append(encryptedData)
|
||
|
||
// 返回加密后的数据(16进制表示)
|
||
return EN_STR_TAG + fullEncryptedData.hexEncodedString()
|
||
}
|
||
|
||
// 使用盐加密数据
|
||
static func encryptWithSalt(_ data: Data, salt: Data) -> Data? {
|
||
var result = Data(capacity: data.count)
|
||
let saltLen = salt.count
|
||
|
||
for (i, byte) in data.enumerated() {
|
||
let saltByte = salt[i % saltLen]
|
||
result.append(calSalt(v: byte, s: saltByte))
|
||
}
|
||
|
||
return result
|
||
}
|
||
|
||
// 解密数据
|
||
static func decrypt(_ data: String) -> String? {
|
||
guard !data.isEmpty else {
|
||
return data
|
||
}
|
||
|
||
// 检查是否是加密字符串 如果不是加密串,返回原始字符串
|
||
guard data.hasPrefix(EN_STR_TAG) else {
|
||
print("Invalid encoded string.")
|
||
return data
|
||
}
|
||
|
||
// 提取16进制数据并解码
|
||
let hexString = String(data.dropFirst(EN_STR_TAG.count))
|
||
|
||
guard let encodedData = NSData(hexString: hexString) as? Data else {
|
||
// guard let encodedData = Data(hexString: hexString) else {
|
||
print("Invalid hex string.")
|
||
return nil
|
||
}
|
||
|
||
guard encodedData.count > 0 else {
|
||
print("Empty encoded data.")
|
||
return nil
|
||
}
|
||
|
||
// 解析盐长度和盐
|
||
let saltLen = Int(encodedData[0])
|
||
guard encodedData.count > saltLen + 1 else {
|
||
print("Invalid encoded data format.")
|
||
return nil
|
||
}
|
||
|
||
let salt = encodedData.subdata(in: 1..<(1+saltLen))
|
||
let encryptedData = encodedData.subdata(in: (1+saltLen)..<encodedData.count)
|
||
|
||
// 解密
|
||
guard let decryptedData = decryptWithSalt(encryptedData, salt: salt) else {
|
||
return nil
|
||
}
|
||
|
||
// 将解密数据转换为字符串
|
||
return String(data: decryptedData, encoding: .utf8)
|
||
}
|
||
|
||
// 使用盐解密数据
|
||
static func decryptWithSalt(_ data: Data, salt: Data) -> Data? {
|
||
var result = Data(capacity: data.count)
|
||
let saltLen = salt.count
|
||
for (i, byte) in data.enumerated() {
|
||
let saltByte = salt[i % saltLen]
|
||
result.append(calRemoveSalt(v: byte, s: saltByte))
|
||
}
|
||
|
||
return result
|
||
}
|
||
|
||
// 计算加盐值
|
||
private static func calSalt(v: UInt8, s: UInt8) -> UInt8 {
|
||
let r = 255 - v
|
||
if s > r {
|
||
return s - r - 1
|
||
}
|
||
return v + s
|
||
}
|
||
|
||
// 计算去盐值
|
||
private static func calRemoveSalt(v: UInt8, s: UInt8) -> UInt8 {
|
||
if v >= s {
|
||
return v - s
|
||
}
|
||
return 255 - (s - v) + 1
|
||
}
|
||
}
|
||
|
||
// Data 扩展,用于16进制编码/解码
|
||
extension Data {
|
||
// 16进制字符串转换为Data
|
||
// init?(hexString: String) {
|
||
// let len = hexString.count / 2
|
||
// var data = Data(capacity: len)
|
||
//
|
||
// var index = hexString.startIndex
|
||
// for _ in 0..<len {
|
||
// let nextIndex = hexString.index(index, offsetBy: 2)
|
||
// let byteString = hexString[index..<nextIndex]
|
||
//
|
||
// guard let num = UInt8(byteString, radix: 16) else {
|
||
// return nil
|
||
// }
|
||
//
|
||
// data.append(num)
|
||
// index = nextIndex
|
||
// }
|
||
//
|
||
// self = data
|
||
// }
|
||
|
||
// Data转换为16进制字符串
|
||
func hexEncodedString() -> String {
|
||
return map { String(format: "%02hhx", $0) }.joined()
|
||
}
|
||
|
||
}
|