I recently found an Objective-C extension on NSData
that encodes and decodes data with AES-128. I made an attempt to port this code to Swift 2.2:
NSData+AES.swift
extension NSData {
struct AES {
static let privateKey = "DefaultPrivateKey"
}
func AES128EncryptedDataWithKey(key: String = AES.privateKey) -> NSData? {
return AES128Operation(CCOperation(kCCEncrypt), key: key)
}
func AES128DecryptedDataWithKey(key: String = AES.privateKey) -> NSData? {
return AES128Operation(CCOperation(kCCDecrypt), key: key)
}
private func AES128Operation(operation: CCOperation, key: String) -> NSData? {
var keyPtr = [CChar](count: kCCKeySizeAES128 + 1, repeatedValue: 0)
key.getCString(&keyPtr, maxLength: keyPtr.count, encoding: NSUTF8StringEncoding)
let dataLength = self.length
let bufferSize = dataLength + kCCBlockSizeAES128
let buffer = malloc(bufferSize)
var numBytesEncrypted = 0
let cryptStatus = CCCrypt(operation, CCAlgorithm(kCCAlgorithmAES128), CCOptions(kCCOptionPKCS7Padding), keyPtr, kCCBlockSizeAES128, nil, self.bytes, dataLength, buffer, bufferSize, &numBytesEncrypted)
if cryptStatus == CCCryptorStatus(kCCSuccess) {
// bytesNoCopy will transfer ownership to the NSData object returned, so we don't need to explicitly call free here
return NSData(bytesNoCopy: buffer, length: numBytesEncrypted)
}
// If the operation failed, we never transferred memory ownership, so free the buffer
free(buffer)
return nil
}
}
A few notes:
I keep a default key as a private struct in the extension so the operation function can be called without arguments for encoding/decoding with a default key.
No need to call
bzero
anymore since we init the buffer with arepeatedValue
of 0.In my first pass of this in Swift, I accidentally was passing in the size of the array (pointer) as the
maxLength
parameter ingetCString
(Stack Overflow question here). Is there any way I could make the code clearer so I don't do that in the future?Is it necessary to
malloc
a buffer? Can I use a Swift[Int8]
instead?According to my boss in a passive comment, AES-128 is "known to be compromised." How complex would it be to refactor this code to use AES-256 or (192) bit encryption?