Skip to content

Instantly share code, notes, and snippets.

@dotkebi
Last active June 12, 2023 08:59
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dotkebi/09732ec725e91bc927e71bed6a0837c4 to your computer and use it in GitHub Desktop.
Save dotkebi/09732ec725e91bc927e71bed6a0837c4 to your computer and use it in GitHub Desktop.
Swift AES Extensions
import Foundation
extension NSData {
func encryptAES128(key: NSString, iv: NSString) -> NSData? {
return aes128(method: CCOperation(kCCEncrypt), key: key, iv: iv)
}
func decryptAES128(key: NSString, iv: NSString) -> NSData? {
return aes128(method: CCOperation(kCCDecrypt), key: key, iv: iv)
}
private func aes128(method: CCOperation, key: NSString, iv: NSString) -> NSData? {
let keyPtr = UnsafeMutablePointer<CChar>.allocate(capacity: Int(kCCKeySizeAES128) + 1)
defer {
keyPtr.deallocate()
}
let ivPtr = iv.utf8String
bzero(keyPtr, 0)
key.getCString(keyPtr, maxLength: Int(kCCKeySizeAES128) + 1, encoding: String.Encoding.utf8.rawValue)
let bufferSize = self.length + kCCBlockSizeAES128
let buffer = UnsafeMutableRawPointer.allocate(byteCount: bufferSize, alignment: MemoryLayout.alignment(ofValue: CChar.self))
var numBytesEncrypted = 0
let cryptStatus = CCCrypt(method, CCAlgorithm(kCCAlgorithmAES128), CCOptions(kCCOptionPKCS7Padding), keyPtr, kCCKeySizeAES128, ivPtr, self.bytes, self.length, buffer, bufferSize, &numBytesEncrypted)
if cryptStatus == kCCSuccess {
return NSData(bytesNoCopy: buffer, length: numBytesEncrypted, freeWhenDone: true)
}
buffer.deallocate()
return nil
}
}
import Foundation
extension String {
func encryptAES128(key: String, iv: String) -> String? {
return aes128(method: CCOperation(kCCEncrypt), key: key, iv: iv)
}
func decryptAES128(key: String, iv: String) -> String? {
return aes128(method: CCOperation(kCCDecrypt), key: key, iv: iv)
}
private func aes128(method: CCOperation, key: String, iv: String) -> String? {
if let keyData = key.data(using: String.Encoding.utf8),
let data = NSData(base64Encoded: self, options: .ignoreUnknownCharacters),
let cryptData = NSMutableData(length: Int((data.length)) + kCCBlockSizeAES128) {
let keyLength = size_t(kCCKeySizeAES128)
let algoritm: CCAlgorithm = UInt32(kCCAlgorithmAES128)
var numBytesEncrypted :size_t = 0
let cryptStatus = CCCrypt(method,
algoritm,
CCOptions(kCCOptionPKCS7Padding),
(keyData as NSData).bytes, keyLength,
iv,
data.bytes, data.length,
cryptData.mutableBytes, cryptData.length,
&numBytesEncrypted)
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
cryptData.length = Int(numBytesEncrypted)
let unencryptedMessage = String(data: cryptData as Data, encoding:String.Encoding.utf8)
return unencryptedMessage
}
}
return nil
}
}
@mezhevikin
Copy link

mezhevikin commented May 31, 2023

Swift 5 version

extension Data {

    func encryptAES128(key: String, iv: String) -> Data? {
        aes128(method: CCOperation(kCCEncrypt), key: key, iv: iv)
    }

    func decryptAES128(key: String, iv: String) -> Data? {
        aes128(method: CCOperation(kCCDecrypt), key: key, iv: iv)
    }

    private func aes128(method: CCOperation, key: String, iv: String) -> Data? {
        let keyData = key.data(using: .utf8)!
        let ivData = iv.data(using: .utf8)!

        let bufferSize = count + kCCBlockSizeAES128
        var buffer = [UInt8](repeating: 0, count: bufferSize)

        var numBytesEncrypted = 0

        let cryptStatus = keyData.withUnsafeBytes { keyBytes in
            ivData.withUnsafeBytes { ivBytes in
                withUnsafeBytes { dataBytes in
                    CCCrypt(
                        method,
                        CCAlgorithm(kCCAlgorithmAES128),
                        CCOptions(kCCOptionPKCS7Padding),
                        keyBytes.baseAddress,
                        kCCKeySizeAES128,
                        ivBytes.baseAddress,
                        dataBytes.baseAddress,
                        count,
                        &buffer,
                        bufferSize,
                        &numBytesEncrypted
                    )
                }
            }
        }

        if cryptStatus == kCCSuccess {
            return Data(bytes: buffer, count: numBytesEncrypted)
        }

        return nil
    }
    
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment