Files
hospital-rescue-app-v2/uni_modules/x-crypto-s/utssdk/app-ios/UniversalCryptoHelper.swift
T
2026-09-24 16:25:22 +08:00

1296 lines
42 KiB
Swift
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import Foundation
import CryptoSwift
import Security
import CommonCrypto
// UTS内置对象的引用
import DCloudUTSFoundation
enum OutputLength: Int {
case LENGTH_16 = 8 // 8 bytes = 16 hex chars
case LENGTH_32 = 16 // 16 bytes = 32 hex chars
case LENGTH_64 = 32 // 32 bytes = 64 hex chars
}
struct RSARandomKey {
let publicKey: String
let privateKey: String
}
enum RSAError: Error {
case keyExtractionFailed
case invalidKeyFormat
case invalidInput
case keyGenerationFailed(status: OSStatus)
case publicKeyConversionFailed
case privateKeyConversionFailed
case keyCreationFailed
case encryptionFailed
case decryptionFailed
case dataConversionFailed
case base64DecodingFailed
}
// 生成指定长度的密钥,类似于Android版本
func generateKey(key: String, keySize: Int = 16) -> [UInt8] {
let keyBytes = Array(key.utf8)
var paddedKey = [UInt8](repeating: 0, count: keySize)
if keyBytes.count < keySize {
// 不足时用0填充
paddedKey.replaceSubrange(0..<keyBytes.count, with: keyBytes)
} else {
// 过长时截断
paddedKey.replaceSubrange(0..<keySize, with: keyBytes[0..<keySize])
}
return paddedKey
}
// 生成指定长度的密钥,处理ByteArray输入,类似于Android版本的generateDesKey2
func generateKey2(key: [UInt8], keySize: Int = 16) -> [UInt8] {
var paddedKey = [UInt8](repeating: 0, count: keySize)
if key.count < keySize {
// 不足时用0填充
paddedKey.replaceSubrange(0..<key.count, with: key)
} else {
// 过长时截断
paddedKey.replaceSubrange(0..<keySize, with: key[0..<keySize])
}
return paddedKey
}
//
// MZRSA.swift
// TDSwiftTemplate
//
// Created by 曾龙 on 2021/12/1.
//
public struct MZRSA {
//MARK:- encrypt or decrypt by SecKey String
/// 使用私钥字符串加密Data
/// - Parameters:
/// - data: 需加密的Data
/// - privateKey: 私钥字符串
/// - Returns: 加密后Data
public static func encryptData(_ data: Data, privateKey: String) -> Data? {
let secKey = addPrivateKey(privateKey)
if secKey == nil {
return nil
}
return encrypt(data, with: secKey!, and: true)
}
/// 使用私钥字符串加密String
/// - Parameters:
/// - string: 需加密的String
/// - privateKey: 私钥字符串
/// - Returns: 加密后String
public static func encryptString(_ string: String, privateKey: String) -> String? {
guard let data = encryptData(string.data(using: String.Encoding.utf8)!, privateKey: privateKey) else {
return nil
}
return base64_encode_data(data)
}
/// 使用私钥字符串解密Data
/// - Parameters:
/// - data: 需解密的Data
/// - privateKey: 私钥字符串
/// - Returns: 解密后Data
public static func decryptData(_ data: Data, privateKey: String) -> Data? {
let secKey = addPrivateKey(privateKey)
if secKey == nil {
return nil
}
return decrypt(data, with: secKey!)
}
/// 使用私钥字符串解密String
/// - Parameters:
/// - string: 需解密的String
/// - privateKey: 私钥字符串
/// - Returns: 解密后String
public static func decryptString(_ string: String, privateKey: String) -> String? {
var data = base64_decode(string)
data = decryptData(data!, privateKey: privateKey)
if data == nil {
return nil
}
return String.init(data: data!, encoding: String.Encoding.utf8)
}
/// 使用公钥字符串加密Data
/// - Parameters:
/// - data: 需加密的Data
/// - publicKey: 公钥字符串
/// - Returns: 加密后Data
public static func encryptData(_ data: Data, publicKey: String) -> Data? {
let secKey = addPublicKey(publicKey)
if secKey == nil {
return nil
}
return encrypt(data, with: secKey!, and: false)
}
/// 使用公钥字符串加密String
/// - Parameters:
/// - string: 需加密的String
/// - publicKey: 公钥字符串
/// - Returns: 加密后String
public static func encryptString(_ string: String, publicKey: String) -> String? {
guard let data = encryptData(string.data(using: String.Encoding.utf8)!, publicKey: publicKey) else {
return nil
}
return base64_encode_data(data)
}
/// 使用公钥字符串解密Data
/// - Parameters:
/// - data: 需解密的Data
/// - publicKey: 公钥字符串
/// - Returns: 解密后Data
public static func decryptData(_ data: Data, publicKey: String) -> Data? {
let secKey = addPublicKey(publicKey)
if secKey == nil {
return nil
}
return decrypt(data, with: secKey!)
}
/// 使用公钥字符串解密String
/// - Parameters:
/// - string: 需解密的String
/// - publicKey: 公钥字符串
/// - Returns: 解密后String
public static func decryptString(_ string: String, publicKey: String) -> String? {
var data = base64_decode(string)
data = decryptData(data!, publicKey: publicKey)
if data == nil {
return nil
}
return String.init(data: data!, encoding: String.Encoding.utf8)
}
//MARK:- encrypt or decrypt by SecKey data
/// 使用私钥Data加密Data
/// - Parameters:
/// - data: 需加密的Data
/// - privateKeyData: 私钥Data
/// - Returns: 加密后的Data
public static func encryptData(_ data: Data, privateKeyData: Data) -> Data? {
let secKey = addPrivateKey(privateKeyData)
if secKey == nil {
return nil
}
return encrypt(data, with: secKey!, and: true)
}
/// 使用私钥Data加密String
/// - Parameters:
/// - string: 需加密的String
/// - privateKeyData: 私钥Data
/// - Returns: 加密后的String
public static func encryptString(_ string: String, privateKeyData: Data) -> String? {
guard let data = encryptData(string.data(using: String.Encoding.utf8)!, privateKeyData: privateKeyData) else {
return nil
}
return base64_encode_data(data)
}
/// 用私钥Data解密Data
/// - Parameters:
/// - data: 需解密的Data
/// - privateKeyData: 私钥Data
/// - Returns: 解密后的Data
public static func decryptData(_ data: Data, privateKeyData: Data) -> Data? {
let secKey = addPrivateKey(privateKeyData)
if secKey == nil {
return nil
}
return decrypt(data, with: secKey!)
}
/// 用私钥Data解密String
/// - Parameters:
/// - string: 需解密的String
/// - privateKeyData: 私钥Data
/// - Returns: 解密后的String
public static func decryptString(_ string: String, privateKeyData: Data) -> String? {
var data = base64_decode(string)
data = decryptData(data!, privateKeyData: privateKeyData)
if data == nil {
return nil
}
return String.init(data: data!, encoding: String.Encoding.utf8)
}
/// 使用公钥Data加密Data
/// - Parameters:
/// - data: 需加密的Data
/// - publicKeyData: 公钥Data
/// - Returns: 加密后Data
public static func encryptData(_ data: Data, publicKeyData: Data) -> Data? {
let secKey = addPublicKey(publicKeyData)
if secKey == nil {
return nil
}
return encrypt(data, with: secKey!, and: false)
}
/// 使用公钥Data加密String
/// - Parameters:
/// - string: 需加密的String
/// - publicKeyData: 公钥Data
/// - Returns: 加密后String
public static func encryptString(_ string: String, publicKeyData: Data) -> String? {
guard let data = encryptData(string.data(using: String.Encoding.utf8)!, publicKeyData: publicKeyData) else {
return nil
}
return base64_encode_data(data)
}
/// 使用公钥Data解密Data
/// - Parameters:
/// - data: 需解密的Data
/// - publicKeyData: 公钥Data
/// - Returns: 解密后Data
public static func decryptData(_ data: Data, publicKeyData: Data) -> Data? {
let secKey = addPublicKey(publicKeyData)
if secKey == nil {
return nil
}
return decrypt(data, with: secKey!)
}
/// 使用公钥Data解密String
/// - Parameters:
/// - string: 需解密的String
/// - publicKeyData: 公钥Data
/// - Returns: 解密后String
public static func decryptString(_ string: String, publicKeyData: Data) -> String? {
var data = base64_decode(string)
data = decryptData(data!, publicKeyData: publicKeyData)
if data == nil {
return nil
}
return String.init(data: data!, encoding: String.Encoding.utf8)
}
//MARK:- encrypt or decrypt by SecKey path
/// 使用私钥证书路径加密Data
/// - Parameters:
/// - data: 需加密的Data
/// - privateKeyPath: 私钥证书路径
/// - Returns: 加密后Data
public static func encryptData(_ data: Data, privateKeyPath: String) -> Data? {
let secKey = loadPrivateKey(privateKeyPath)
if secKey == nil {
return nil
}
return encrypt(data, with: secKey!, and: true)
}
/// 使用私钥证书路径加密String
/// - Parameters:
/// - string: 需加密的String
/// - privateKeyPath: 私钥证书路径
/// - Returns: 加密后String
public static func encryptString(_ string: String, privateKeyPath: String) -> String? {
guard let data = encryptData(string.data(using: String.Encoding.utf8)!, privateKeyPath: privateKeyPath) else {
return nil
}
return base64_encode_data(data)
}
/// 使用私钥证书路径解密Data
/// - Parameters:
/// - data: 需解密的Data
/// - privateKeyPath: 私钥证书路径
/// - Returns: 解密后Data
public static func decryptData(_ data: Data, privateKeyPath: String) -> Data? {
let secKey = loadPrivateKey(privateKeyPath)
if secKey == nil {
return nil
}
return decrypt(data, with: secKey!)
}
/// 使用私钥证书路径解密String
/// - Parameters:
/// - string: 需解密的String
/// - privateKeyPath: 私钥证书路径
/// - Returns: 解密后String
public static func decryptString(_ string: String, privateKeyPath: String) -> String? {
var data = base64_decode(string)
data = decryptData(data!, privateKeyPath: privateKeyPath)
if data == nil {
return nil
}
return String.init(data: data!, encoding: String.Encoding.utf8)
}
/// 使用公钥证书路径加密Data
/// - Parameters:
/// - data: 需加密的Data
/// - publicKeyPath: 公钥证书路径
/// - Returns: 加密后Data
public static func encryptData(_ data: Data, publicKeyPath: String) -> Data? {
let secKey = loadPublicKey(publicKeyPath)
if secKey == nil {
return nil
}
return encrypt(data, with: secKey!, and: false)
}
/// 使用公钥证书路径加密String
/// - Parameters:
/// - string: 需加密的String
/// - publicKeyPath: 公钥证书路径
/// - Returns: 加密后String
public static func encryptString(_ string: String, publicKeyPath: String) -> String? {
guard let data = encryptData(string.data(using: String.Encoding.utf8)!, publicKeyPath: publicKeyPath) else {
return nil
}
return base64_encode_data(data)
}
/// 使用公钥证书路径解密Data
/// - Parameters:
/// - data: 需解密的Data
/// - publicKeyPath: 公钥证书路径
/// - Returns: 解密后Data
public static func decryptData(_ data: Data, publicKeyPath: String) -> Data? {
let secKey = loadPublicKey(publicKeyPath)
if secKey == nil {
return nil
}
return decrypt(data, with: secKey!)
}
/// 使用公钥证书路径解密String
/// - Parameters:
/// - string: 需解密的String
/// - publicKeyPath: 公钥证书路径
/// - Returns: 解密后String
public static func decryptString(_ string: String, publicKeyPath: String) -> String? {
var data = base64_decode(string)
data = decryptData(data!, publicKeyPath: publicKeyPath)
if data == nil {
return nil
}
return String.init(data: data!, encoding: String.Encoding.utf8)
}
//MARK:- OTHER
private static func base64_encode_data(_ data: Data) -> String? {
let newData = data.base64EncodedData(options: Data.Base64EncodingOptions.lineLength64Characters)
return String.init(data: newData, encoding: String.Encoding.utf8)
}
private static func base64_decode(_ string: String) -> Data? {
return Data.init(base64Encoded: string, options: Data.Base64DecodingOptions.ignoreUnknownCharacters)
}
private static func stripPublicKeyHeader(_ d_key: Data?) -> Data? {
guard let dKey = d_key else {
return nil
}
let len = dKey.count
if len == 0 {
return nil
}
var cKey = dataToBytes(dKey)
var index = 0
if cKey[index] != 0x30 {
return nil
}
index += 1
if cKey[index] > 0x80 {
index += Int(cKey[index]) - 0x80 + 1
} else {
index += 1
}
let swqiod:[CUnsignedChar] = [0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
0x01, 0x05, 0x00]
if (memcmp(&cKey[index], swqiod, 15) == 1) {
return nil
}
index += 15
if cKey[index] != 0x03 {
return nil
}
index += 1
if cKey[index] > 0x80 {
index += Int(cKey[index]) - 0x80 + 1
} else {
index += 1
}
if cKey[index] != Unicode.Scalar.init("\0").value {
return nil
}
index += 1
return Data.init(cKey).advanced(by: index)
}
private static func stripPrivateKeyHeader(_ d_key: Data?) -> Data? {
guard let dKey = d_key else {
return nil
}
let len = dKey.count
if len == 0 {
return nil
}
var cKey = dataToBytes(dKey)
var index = 22
if cKey[index] != 0x04 {
return nil
}
index += 1
var cLen = Int(cKey[index])
index += 1
let det = cLen & 0x80
if det == 0 {
cLen = cLen & 0x7f
} else {
var byteCount = Int(cLen & 0x7f)
if Int(byteCount) + index > len {
return nil
}
var accum = 0
var ptr = withUnsafePointer(to: &cKey[index]) { $0 }
index += Int(byteCount)
while byteCount > 0 {
accum = (accum << 8) + Int(ptr.pointee)
ptr = ptr.advanced(by: 1)
byteCount -= 1
}
cLen = accum
}
return dKey.subdata(in: Range.init(_NSRange.init(location: index, length: Int(cLen)))!)
}
/// 公钥字符串转SecKey
/// - Parameter key: 公钥字符串
/// - Returns: SecKey
private static func addPublicKey(_ key: String) -> SecKey? {
var newKey = key
let spos = newKey.range(of: "-----BEGIN PUBLIC KEY-----")
let epos = newKey.range(of: "-----END PUBLIC KEY-----")
if spos != nil && epos != nil {
newKey = String(newKey[spos!.upperBound..<epos!.lowerBound])
}
newKey = newKey.replacingOccurrences(of: "\r", with: "")
newKey = newKey.replacingOccurrences(of: "\n", with: "")
newKey = newKey.replacingOccurrences(of: "\t", with: "")
newKey = newKey.replacingOccurrences(of: " ", with: "")
var data = base64_decode(newKey)
data = stripPublicKeyHeader(data)
if data == nil {
return nil
}
return addPublicKey(data!)
}
public static func addPublicKey(_ data: Data) -> SecKey? {
let tag = "RSAUtil_PubKey"
let d_tag = tag.data(using: String.Encoding.utf8)
var publicKey = Dictionary<String, Any>.init()
publicKey[kSecClass as String] = kSecClassKey
publicKey[kSecAttrKeyType as String] = kSecAttrKeyTypeRSA
publicKey[kSecAttrApplicationTag as String] = d_tag
SecItemDelete(publicKey as CFDictionary)
publicKey[kSecValueData as String] = data
publicKey[kSecAttrKeyClass as String] = kSecAttrKeyClassPublic
publicKey[kSecReturnPersistentRef as String] = true
var status = SecItemAdd(publicKey as CFDictionary, nil)
if status != noErr && status != errSecDuplicateItem {
return nil
}
publicKey.removeValue(forKey: kSecValueData as String)
publicKey.removeValue(forKey: kSecReturnPersistentRef as String)
publicKey[kSecReturnRef as String] = NSNumber(value: true)
publicKey[kSecAttrKeyType as String] = kSecAttrKeyTypeRSA
var keyRef: CFTypeRef?
status = SecItemCopyMatching(publicKey as CFDictionary, &keyRef)
if status != noErr {
return nil
}
return (keyRef as! SecKey)
}
/// 私钥字符串转SecKey
/// - Parameter key: 私钥字符串     /// - Returns: SecKey
private static func addPrivateKey(_ key: String) -> SecKey? {
var newKey = key
var spos: Range<String.Index>?
var epos: Range<String.Index>?
spos = newKey.range(of: "-----BEGIN RSA PRIVATE KEY-----")
if spos != nil {
epos = newKey.range(of: "-----END RSA PRIVATE KEY-----")
} else {
spos = newKey.range(of: "-----BEGIN PRIVATE KEY-----")
epos = newKey.range(of: "-----END PRIVATE KEY-----")
}
if spos != nil && epos != nil {
newKey = String(newKey[spos!.upperBound..<epos!.lowerBound])
}
newKey = newKey.replacingOccurrences(of: "\r", with: "")
newKey = newKey.replacingOccurrences(of: "\n", with: "")
newKey = newKey.replacingOccurrences(of: "\t", with: "")
newKey = newKey.replacingOccurrences(of: " ", with: "")
var data = base64_decode(newKey)
data = stripPrivateKeyHeader(data)
if data == nil {
return nil
}
return addPrivateKey(data!)
}
private static func addPrivateKey(_ data: Data) -> SecKey? {
let tag = "RSAUtil_PrivKey"
let d_tag = tag.data(using: String.Encoding.utf8)
var privateKey = Dictionary<CFString, Any>.init()
privateKey[kSecClass] = kSecClassKey
privateKey[kSecAttrKeyType] = kSecAttrKeyTypeRSA
privateKey[kSecAttrApplicationTag] = d_tag
SecItemDelete(privateKey as CFDictionary)
privateKey[kSecValueData] = data
privateKey[kSecAttrKeyClass] = kSecAttrKeyClassPrivate
privateKey[kSecReturnPersistentRef] = true
var persistKey: CFTypeRef?
var status = SecItemAdd(privateKey as CFDictionary, &persistKey)
if status != noErr && status != errSecDuplicateItem {
return nil
}
privateKey.removeValue(forKey: kSecValueData)
privateKey.removeValue(forKey: kSecReturnPersistentRef)
privateKey[kSecReturnRef] = true
privateKey[kSecAttrKeyType] = kSecAttrKeyTypeRSA
var keyRef: CFTypeRef?
status = SecItemCopyMatching(privateKey as CFDictionary, &keyRef)
if status != noErr {
return nil
}
return (keyRef as! SecKey)
}
private static func encrypt(_ data: Data, with secKey: SecKey, and isSign: Bool) -> Data? {
var srcbuf = dataToBytes(data)
let srclen = data.count
let block_size = SecKeyGetBlockSize(secKey) * MemoryLayout<UInt8>.size
var outbuf = [UInt8](repeating: 0, count: block_size)
let src_block_size = block_size - 11
var ret: Data? = Data.init()
var index = 0
while index < srclen {
var data_len = srclen - index
if data_len > src_block_size {
data_len = src_block_size
}
var outlen = block_size
var status = noErr
let ptr = withUnsafePointer(to: &srcbuf[index]) { $0 }
if isSign {
status = SecKeyRawSign(secKey, SecPadding.PKCS1, ptr, data_len, &outbuf, &outlen)
} else {
status = SecKeyEncrypt(secKey, SecPadding.PKCS1, ptr, data_len, &outbuf, &outlen)
}
if status != 0 {
ret = nil
break
} else {
ret!.append(contentsOf: outbuf[0..<outlen])
}
index += src_block_size
}
return ret
}
private static func decrypt(_ data: Data, with secKey: SecKey) -> Data? {
var srcbuf = dataToBytes(data)
let srclen = data.count
let block_size = SecKeyGetBlockSize(secKey) * MemoryLayout<UInt8>.size
var outbuf = [UInt8](repeating: 0, count: block_size)
let src_block_size = block_size
var ret: Data? = Data.init()
var index = 0
while index < srclen {
var data_len = srclen - index
if data_len > src_block_size {
data_len = src_block_size
}
var outlen = block_size
var status = noErr
let ptr = withUnsafePointer(to: &srcbuf[index]) { $0 }
status = SecKeyDecrypt(secKey, SecPadding.init(rawValue: 0), ptr, data_len, &outbuf, &outlen)
if status != 0 {
ret = nil
break
} else {
var idxFirstZero = -1
var idxNextZero = Int(outlen)
for i in 0..<outlen {
if outbuf[i] == 0 {
if idxFirstZero < 0 {
idxFirstZero = i
} else {
idxNextZero = i
break
}
}
}
ret?.append(contentsOf: outbuf[idxFirstZero+1..<idxNextZero])
}
index += src_block_size
}
return ret
}
/// 从.der证书获取公钥
/// - Parameter der: .der证书路径
/// - Returns: 公钥
private static func loadPublicKey(_ path: String) -> SecKey? {
let data: Data;
do {
data = try Data.init(contentsOf: URL.init(fileURLWithPath: path))
} catch {
return nil
}
guard let cert = SecCertificateCreateWithData(nil, data as CFData) else {
return nil
}
let key: SecKey?
var trust: SecTrust?
let policy = SecPolicyCreateBasicX509()
if SecTrustCreateWithCertificates(cert, policy, &trust) == noErr {
var result = SecTrustResultType.invalid
if trust != nil {
if SecTrustEvaluate(trust!, &result) == noErr {
key = SecTrustCopyPublicKey(trust!)
return key
}
}
}
return nil
}
/// 从.p12证书获取私钥
/// - Parameters:
/// - path: .p12证书路径
/// - password: ,p12证书密码
/// - Returns: 私钥
private static func loadPrivateKey(_ path: String, with password: String = "") -> SecKey? {
let data: Data;
do {
data = try Data.init(contentsOf: URL.init(fileURLWithPath: path))
} catch {
return nil
}
var key: SecKey?
let options = NSMutableDictionary.init()
options[kSecImportExportPassphrase as String] = password
var items: CFArray?
var securityError = SecPKCS12Import(data as CFData, options, &items)
if securityError == noErr && CFArrayGetCount(items) > 0 {
let identityDict = CFArrayGetValueAtIndex(items, 0)
let appKey = Unmanaged.passUnretained(kSecImportItemIdentity).toOpaque()
let identityApp = CFDictionaryGetValue((identityDict as! CFDictionary), appKey)
securityError = SecIdentityCopyPrivateKey(identityApp as! SecIdentity, &key)
if securityError == noErr {
return key
}
}
return nil
}
/// Data转Byte(UInt8)数组
/// - Parameter data: Data
/// - Returns: Byte(UInt8)数组
private static func dataToBytes(_ data: Data) -> [UInt8] {
let string = dataToHex(data)
var start = string.startIndex
return stride(from: 0, to: string.count, by: 2).compactMap { _ in
let end = string.index(after: start)
defer {start = string.index(after: end)}
return UInt8(string[start...end], radix: 16)
}
}
/// Data转16进制字符串
/// - Parameter data: Data
/// - Returns: 16进制字符串
private static func dataToHex(_ data: Data) -> String {
let bytes = [UInt8](data)
var hex = ""
for index in 0..<data.count {
let newHex = String(format: "%x", bytes[index]&0xff)
if newHex.count == 1 {
hex = String(format: "%@0%@", hex, newHex)
} else {
hex += newHex
}
}
return hex
}
}
// RC4 加密和解密
func rc4(data: Data, key: String) -> Data {
let keyBytes = [UInt8](key.utf8)
var s = Array(0...255) // S-box
var j = 0
// 初始化 S-box
for i in 0..<256 {
j = (j + s[i] + Int(keyBytes[i % keyBytes.count])) & 0xFF
s.swapAt(i, j)
}
var i = 0
j = 0
var output = Data()
// 加密/解密
for byte in data {
i = (i + 1) & 0xFF
j = (j + s[i]) & 0xFF
s.swapAt(i, j)
let k = s[(s[i] + s[j]) & 0xFF]
output.append(byte ^ UInt8(k))
}
return output
}
// 字符串转十六进制
func stringToHex(_ data: Data) -> String {
return data.map { String(format: "%02x", $0) }.joined()
}
// 十六进制转 Data
func hexToData(_ hex: String) -> Data? {
var data = Data()
var tempHex = hex
while tempHex.count > 0 {
let c = tempHex.prefix(2)
tempHex.removeFirst(2)
if let byte = UInt8(c, radix: 16) {
data.append(byte)
} else {
return nil
}
}
return data
}
// RC4 加密
func rc4Encrypt2(data: String, key: String) -> String {
let dataBytes = Data(data.utf8)
let encryptedData = rc4(data: dataBytes, key: key)
return stringToHex(encryptedData)
}
// RC4 解密
func rc4Decrypt2(encryptedHex: String, key: String) -> String {
guard let encryptedData = hexToData(encryptedHex) else { return "" }
let decryptedData = rc4(data: encryptedData, key: key)
return String(data: decryptedData, encoding: .utf8) ?? ""
}
class UniversalCryptoHelper {
// MD5 Encryption
static func md5(input: String) -> String {
let md5Hash = input.md5();
return md5Hash;
}
// Base64 Encoding and Decoding
static func base64Encode(input: String) -> String {
let data = input.data(using: .utf8)!;
return data.base64EncodedString();
}
static func base64Decode(input: String) -> String {
if let data = Data(base64Encoded: input) {
if let decryptedString = String(data: data, encoding: .utf8) {
return decryptedString
} else {
return "" // 或者处理解包失败的情况
}
}
return ""
}
// HMAC with SHA-256
static func hmacSha256(key: String, data: String) -> String {
let hmac = try! HMAC(key: Array(key.utf8), variant: .sha256)
let hash = try! hmac.authenticate(Array(data.utf8))
return hash.toHexString()
}
// HMAC with SHA-512
static func hmacSha512(key: String, data: String) -> String {
let hmac = try! HMAC(key: Array(key.utf8), variant: .sha512)
let hash = try! hmac.authenticate(Array(data.utf8))
return hash.toHexString()
}
// SHA-1 and SHA-256 Hashing
static func sha1(input: String) -> String {
let sha1Hash = input.sha1()
return sha1Hash
}
static func sha256(input: String) -> String {
let sha256Hash = input.sha256()
return sha256Hash
}
static func sha512(input: String) -> String {
let sha512Hash = input.sha512()
return sha512Hash
}
// AES Encryption and Decryption
static func aesEncrypt(input: String, key: String, mode: String = "ECB", iv: String? = nil,keySize:Int=16) -> String {
do {
let keyBytes = generateKey(key: key, keySize: keySize)
var aes: AES
switch mode.lowercased() {
case "ecb":
aes = try AES(key: keyBytes, blockMode: ECB(), padding: .pkcs7)
case "cbc":
guard let iv = iv else { return "" }
let ivBytes = generateKey(key: iv, keySize: 16)
aes = try AES(key: keyBytes, blockMode: CBC(iv: ivBytes), padding: .pkcs7)
default:
return "" // 如果模式不支持,返回空字符串
}
let encryptedBytes = try aes.encrypt(input.bytes)
let encryptedData = Data(encryptedBytes)
return encryptedData.base64EncodedString()
} catch {
console.log("Encryption failed: \(error)")
return "" // 如果出现错误,返回空字符串
}
}
static func aesDecrypt(input: String, key: String, mode: String = "ECB", iv: String? = nil,keySize:Int=16) -> String {
do {
let keyBytes = generateKey(key: key, keySize: keySize)
var aes: AES
switch mode.lowercased() {
case "ecb":
aes = try AES(key: keyBytes, blockMode: ECB(), padding: .pkcs7)
case "cbc":
guard let iv = iv else { return "" }
let ivBytes = generateKey(key: iv, keySize: 16)
aes = try AES(key: keyBytes, blockMode: CBC(iv: ivBytes), padding: .pkcs7)
default:
return "" // 如果模式不支持,返回空字符串
}
let encryptedData = Data(base64Encoded: input)!
let decryptedBytes = try aes.decrypt(encryptedData.bytes)
if let decryptedString = String(bytes: decryptedBytes, encoding: .utf8) {
return decryptedString
} else {
return "" // 如果解密后的数据无法转换为字符串,返回空字符串
}
} catch {
console.log("Decryption failed: \(error)")
return "" // 如果出现错误,返回空字符串
}
}
// AES Encryption for ByteArray input/output, similar to Android aesEncrypt2
static func aesEncrypt2(input: Data, key: Data, mode: String = "ECB", iv: Data? = nil, keySize: Int = 16) -> Data {
do {
let keyBytes = generateKey2(key: [UInt8](key), keySize: keySize)
var aes: AES
switch mode.lowercased() {
case "ecb":
aes = try AES(key: keyBytes, blockMode: ECB(), padding: .pkcs7)
case "cbc":
let ivBytes: [UInt8]
if let iv = iv {
ivBytes = generateKey2(key: [UInt8](iv), keySize: 16)
} else {
ivBytes = [UInt8](repeating: 0, count: 16)
}
aes = try AES(key: keyBytes, blockMode: CBC(iv: ivBytes), padding: .pkcs7)
default:
return Data() // 如果模式不支持,返回空数组
}
let encryptedBytes = try aes.encrypt([UInt8](input))
return Data(encryptedBytes)
} catch {
console.log("Encryption failed: \(error)")
return Data() // 如果出现错误,返回空数组
}
}
// AES Decryption for ByteArray input/output, similar to Android aesDecrypt2
static func aesDecrypt2(input: Data, key: Data, mode: String = "ECB", iv: Data? = nil, keySize: Int = 16) -> Data {
do {
let keyBytes = generateKey2(key: [UInt8](key), keySize: keySize)
var aes: AES
switch mode.lowercased() {
case "ecb":
aes = try AES(key: keyBytes, blockMode: ECB(), padding: .pkcs7)
case "cbc":
let ivBytes: [UInt8]
if let iv = iv {
ivBytes = generateKey2(key: [UInt8](iv), keySize: 16)
} else {
ivBytes = [UInt8](repeating: 0, count: 16)
}
aes = try AES(key: keyBytes, blockMode: CBC(iv: ivBytes), padding: .pkcs7)
default:
return Data() // 如果模式不支持,返回空数组
}
let decryptedBytes = try aes.decrypt([UInt8](input))
return Data(decryptedBytes)
} catch {
console.log("Decryption failed: \(error)")
return Data() // 如果出现错误,返回空数组
}
}
// DES Encryption and Decryption
static func desEncrypt(input: String, key: String, mode: String = "ECB", iv: String? = nil) -> String {
guard key.count == kCCKeySizeDES else {
console.log("Key length must be 8 bytes.")
return ""
}
let data = input.data(using: .utf8)!
let keyData = key.data(using: .utf8)!
let keyBytes = [UInt8](keyData)
var options: CCOptions = CCOptions(kCCOptionPKCS7Padding)
var ivBytes: [UInt8]?
console.log(mode.lowercased() ,iv,"---")
if mode.lowercased() == "ecb" {
options |= CCOptions(kCCOptionECBMode)
} else if mode.lowercased() == "cbc", let iv = iv {
ivBytes = [UInt8](iv.data(using: .utf8)!)
} else {
console.log("Invalid mode or missing IV for CBC.")
return ""
}
var buffer = [UInt8](repeating: 0, count: data.count + kCCBlockSizeDES)
var bufferLength = 0
let cryptStatus = CCCrypt(
CCOperation(kCCEncrypt),
CCAlgorithm(kCCAlgorithmDES),
options,
keyBytes, key.count,
ivBytes ?? [UInt8](repeating: 0, count: kCCBlockSizeDES),
data.bytes, data.count,
&buffer, buffer.count,
&bufferLength
)
if cryptStatus == kCCSuccess {
let encryptedData = Data(bytes: buffer, count: bufferLength)
return encryptedData.base64EncodedString()
} else {
console.log("Error: \(cryptStatus)")
return ""
}
}
static func desDecrypt(input: String, key: String, mode: String = "ECB", iv: String? = nil) -> String {
guard key.count == kCCKeySizeDES else {
console.log("Key length must be 8 bytes.")
return ""
}
guard let data = Data(base64Encoded: input) else {
console.log("Invalid base64 input.")
return ""
}
console.log(mode.lowercased() ,iv,"---")
let keyData = key.data(using: .utf8)!
let keyBytes = [UInt8](keyData)
var options: CCOptions = CCOptions(kCCOptionPKCS7Padding)
var ivBytes: [UInt8]?
if mode.lowercased() == "ecb" {
options |= CCOptions(kCCOptionECBMode)
} else if mode.lowercased() == "cbc", let iv = iv {
ivBytes = [UInt8](iv.data(using: .utf8)!)
} else {
console.log("Invalid mode or missing IV for CBC.")
return ""
}
var buffer = [UInt8](repeating: 0, count: data.count + kCCBlockSizeDES)
var bufferLength = 0
let cryptStatus = CCCrypt(
CCOperation(kCCDecrypt),
CCAlgorithm(kCCAlgorithmDES),
options,
keyBytes, key.count,
ivBytes ?? [UInt8](repeating: 0, count: kCCBlockSizeDES),
data.bytes, data.count,
&buffer, buffer.count,
&bufferLength
)
if cryptStatus == kCCSuccess {
let decryptedData = Data(bytes: buffer, count: bufferLength)
return String(data: decryptedData, encoding: .utf8) ?? ""
} else {
console.log("Error: \(cryptStatus)")
return ""
}
}
static func generateRSAKeyPair(keySize: Int) throws -> RSARandomKey {
let privateKeyAttributes: [String: Any] = [
kSecAttrIsPermanent as String: false,
kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlocked
]
let publicKeyAttributes: [String: Any] = [
kSecAttrIsPermanent as String: false,
kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlocked
]
let keyPairAttributes: [String: Any] = [
kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
kSecAttrKeySizeInBits as String: keySize,
kSecPrivateKeyAttrs as String: privateKeyAttributes,
kSecPublicKeyAttrs as String: publicKeyAttributes
]
var publicKey: SecKey?
var privateKey: SecKey?
let status = SecKeyGeneratePair(keyPairAttributes as CFDictionary, &publicKey, &privateKey)
guard status == errSecSuccess, let publicKey = publicKey, let privateKey = privateKey else {
throw RSAError.keyGenerationFailed(status: status)
}
guard let publicKeyData = SecKeyCopyExternalRepresentation(publicKey, nil) as Data? else {
throw RSAError.publicKeyConversionFailed
}
guard let privateKeyData = SecKeyCopyExternalRepresentation(privateKey, nil) as Data? else {
throw RSAError.privateKeyConversionFailed
}
let publicKeyBase64 = publicKeyData.base64EncodedString()
let privateKeyBase64 = privateKeyData.base64EncodedString()
return RSARandomKey(publicKey: publicKeyBase64, privateKey: privateKeyBase64)
}
static func rsaDecrypt(_ content: String, privateKey: String) throws -> String {
guard let data = Data(base64Encoded: content) else {
throw RSAError.base64DecodingFailed
}
// Prepare the key
guard let privateKeyData = privateKey
.replacingOccurrences(of: "-----BEGIN PRIVATE KEY-----", with: "")
.replacingOccurrences(of: "-----END PRIVATE KEY-----", with: "")
.replacingOccurrences(of: "\n", with: "")
.data(using: .utf8) else {
throw RSAError.keyCreationFailed
}
let privateKeyBase64 = Data(base64Encoded: privateKeyData)!
var attributes: [String: Any] = [
kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
kSecAttrKeyClass as String: kSecAttrKeyClassPrivate,
kSecAttrKeySizeInBits as String: 2048
]
var error: Unmanaged<CFError>?
guard let privateSecKey = SecKeyCreateWithData(privateKeyBase64 as CFData,
attributes as CFDictionary,
&error) else {
throw RSAError.keyCreationFailed
}
// Decrypt
let algorithm: SecKeyAlgorithm = .rsaEncryptionPKCS1
guard SecKeyIsAlgorithmSupported(privateSecKey, .decrypt, algorithm) else {
throw RSAError.decryptionFailed
}
var decryptError: Unmanaged<CFError>?
guard let decryptedData = SecKeyCreateDecryptedData(privateSecKey,
algorithm,
data as CFData,
&decryptError) as Data? else {
throw RSAError.decryptionFailed
}
guard let decryptedString = String(data: decryptedData, encoding: .utf8) else {
throw RSAError.dataConversionFailed
}
return decryptedString
}
// Encrypt with public key
static func rsaEncrypt(_ content: String, publicKey: String) throws -> String {
guard let data = content.data(using: .utf8) else {
throw RSAError.dataConversionFailed
}
// Prepare the key
guard let publicKeyData = publicKey
.replacingOccurrences(of: "-----BEGIN PUBLIC KEY-----", with: "")
.replacingOccurrences(of: "-----END PUBLIC KEY-----", with: "")
.replacingOccurrences(of: "\n", with: "")
.data(using: .utf8) else {
throw RSAError.keyCreationFailed
}
let publicKeyBase64 = Data(base64Encoded: publicKeyData)!
var attributes: [String: Any] = [
kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
kSecAttrKeyClass as String: kSecAttrKeyClassPublic,
kSecAttrKeySizeInBits as String: 2048
]
var error: Unmanaged<CFError>?
guard let publicSecKey = SecKeyCreateWithData(publicKeyBase64 as CFData,
attributes as CFDictionary,
&error) else {
throw RSAError.keyCreationFailed
}
// Encrypt
let algorithm: SecKeyAlgorithm = .rsaEncryptionPKCS1
guard SecKeyIsAlgorithmSupported(publicSecKey, .encrypt, algorithm) else {
throw RSAError.encryptionFailed
}
var encryptError: Unmanaged<CFError>?
guard let encryptedData = SecKeyCreateEncryptedData(publicSecKey,
algorithm,
data as CFData,
&encryptError) as Data? else {
throw RSAError.encryptionFailed
}
return encryptedData.base64EncodedString()
}
// // pkcs1 2048位
// static func rsaEncrypt(input: String, publicKey: String) -> String {
// // https://github.com/1691665955/MZRSA_Swift
// let codestr = MZRSA.encryptString(input,publicKey:publicKey)
// return codestr ?? ""
// }
// // pkcs1 2048位
// static func rsaDecrypt(input: String, privateKey: String) -> String {
// let codestr = MZRSA.decryptString(input,privateKey:privateKey)
// return codestr ?? ""
// }
static func rc4Encrypt(data : String,key:String) -> String {
return rc4Encrypt2(data:data,key:key)
}
static func rc4Decrypt(encryptedHex: String, key: String) -> String {
return rc4Decrypt2(encryptedHex:encryptedHex,key:key)
}
}