在 Swift 5 實作 AES 加解密 是簡單的
Swift5
Swift
AES
Cryptography
import library
import CommonCrypto
define struct AESCrypt
private
struct AESCrypt {
private let key: Data
private let ivSize: Int = kCCBlockSizeAES128
private let options: CCOptions = CCOptions(kCCOptionPKCS7Padding)
init(key: Data) throws {
guard key.count == kCCKeySizeAES256 else {
throw Error.invalidKeySize
}
self.key = key
}
}
define AESCrypt error
private
extension AESCrypt {
enum Error: Swift.Error {
case invalidKeySize
case generateRandomIVFailed
case encryptionFailed
case decryptionFailed
case dataToStringFailed
}
}
implement AESCrypt randomIV
private
extension AESCrypt {
func generateRandomIV(for data: inout Data) throws {
try data.withUnsafeMutableBytes { dataBytes in
guard let dataBytesBaseAddress = dataBytes.baseAddress else {
throw Error.generateRandomIVFailed
}
let status: Int32 = SecRandomCopyBytes(
kSecRandomDefault,
kCCBlockSizeAES128,
dataBytesBaseAddress
)
guard status == 0 else {
throw Error.generateRandomIVFailed
}
}
}
}
implement AESCrypt encrypt
private
extension AESCrypt {
func encrypt(_ string: String) throws -> Data {
let data = Data(string.utf8)
return try encrypt(data)
}
func encrypt(_ data: Data) throws -> Data {
let bufferSize: Int = ivSize + data.count + kCCBlockSizeAES128
var buffer = Data(count: bufferSize)
try generateRandomIV(for: &buffer)
var numberBytesEncrypted: Int = 0
do {
try key.withUnsafeBytes { keyBytes in
try data.withUnsafeBytes { dataToEncryptBytes in
try buffer.withUnsafeMutableBytes { bufferBytes in
guard let keyBytesBaseAddress = keyBytes.baseAddress,
let dataToEncryptBytesBaseAddress = dataToEncryptBytes.baseAddress,
let bufferBytesBaseAddress = bufferBytes.baseAddress else {
throw Error.encryptionFailed
}
let cryptStatus: CCCryptorStatus = CCCrypt(
CCOperation(kCCEncrypt),
CCAlgorithm(kCCAlgorithmAES),
options,
keyBytesBaseAddress,
key.count,
bufferBytesBaseAddress,
dataToEncryptBytesBaseAddress,
dataToEncryptBytes.count,
bufferBytesBaseAddress + ivSize,
bufferSize,
&numberBytesEncrypted
)
guard cryptStatus == CCCryptorStatus(kCCSuccess) else {
throw Error.encryptionFailed
}
}
}
}
} catch {
throw Error.encryptionFailed
}
let encryptedData: Data = buffer[..<(numberBytesEncrypted + ivSize)]
return encryptedData
}
}
implement AESCrypt decrypt
private
extension AESCrypt {
func decrypt(_ data: Data) throws -> String {
let bufferSize: Int = data.count - ivSize
var buffer = Data(count: bufferSize)
var numberBytesDecrypted: Int = 0
do {
try key.withUnsafeBytes { keyBytes in
try data.withUnsafeBytes { dataToDecryptBytes in
try buffer.withUnsafeMutableBytes { bufferBytes in
guard let keyBytesBaseAddress = keyBytes.baseAddress,
let dataToDecryptBytesBaseAddress = dataToDecryptBytes.baseAddress,
let bufferBytesBaseAddress = bufferBytes.baseAddress else {
throw Error.encryptionFailed
}
let cryptStatus: CCCryptorStatus = CCCrypt(
CCOperation(kCCDecrypt),
CCAlgorithm(kCCAlgorithmAES128),
options,
keyBytesBaseAddress,
key.count,
dataToDecryptBytesBaseAddress,
dataToDecryptBytesBaseAddress + ivSize,
bufferSize,
bufferBytesBaseAddress,
bufferSize,
&numberBytesDecrypted
)
guard cryptStatus == CCCryptorStatus(kCCSuccess) else {
throw Error.decryptionFailed
}
}
}
}
} catch {
throw Error.encryptionFailed
}
let decryptedData: Data = buffer[..<numberBytesDecrypted]
guard let decryptedString = String(data: decryptedData, encoding: .utf8) else {
throw Error.dataToStringFailed
}
return decryptedString
}
}
Extension String
extension String {
var aesEncrypted: Data? {
let aes = try? AESCrypt(key: "your aes key")
return try? aes?.encrypt(self)
}
}
Extension Data
extension Data {
var aesEncrypted: Data? {
let aes = try? AESCrypt(key: "your aes key")
return try? aes?.encrypt(self)
}
var aesDecrypted: String? {
let aes = try? AESCrypt(key: "your aes key")
return try? aes?.decrypt(self)
}
}
Quickly Use
"明文".aesEncrypted
"密文".aesDecrypted