I'm writing a helper function for an iOS Objective-C app that is supposed to encrypt a string with the provided key using the AES-128 algorithm.
I already have a working implementation of this function in Swift, but I'm struggling translating it into Objective-C. The function doesn't take into account any initialization vector, which is hard-coded as an empty string: this is intended.
Here is the Swift code that works as expected:
@objc func AES128(_ string: String, withKey: String) -> String {
let data = string.data(using: String.Encoding.utf8)!
let keyData = withKey.data(using: String.Encoding.utf8)!
let ivData = "".data(using: String.Encoding.utf8)!
let cryptLength = size_t(data.count + kCCBlockSizeAES128)
var cryptData = Data(count: cryptLength)
let keyLength = size_t(kCCKeySizeAES128)
let options = CCOptions(kCCOptionPKCS7Padding)
var numBytesEncrypted: size_t = 0
let cryptStatus = cryptData.withUnsafeMutableBytes { cryptBytes in
data.withUnsafeBytes { dataBytes in
ivData.withUnsafeBytes { ivBytes in
keyData.withUnsafeBytes { keyBytes in
CCCrypt(CCOperation(kCCEncrypt), CCAlgorithm(kCCAlgorithmAES), options, keyBytes, keyLength, ivBytes, dataBytes, data.count, cryptBytes, cryptLength, &numBytesEncrypted)
}
}
}
}
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
cryptData.removeSubrange(numBytesEncrypted..<cryptData.count)
}
return cryptData.base64EncodedString();
}
This function works like a charm and encrypting the string Hello World with the key ABCDEFGHIJKLMNOP results in a base64 encoded string of 3G4OU62dM9zXhkbXy8pmuA==.
I translated it into Objective-C:
+(NSString *)AES128:(NSString *)string withKey:(NSString *)key {
NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
NSData *keyData = [key dataUsingEncoding:NSUTF8StringEncoding];
NSData *ivData = [@"" dataUsingEncoding:NSUTF8StringEncoding];
size_t cryptLength = data.length + kCCBlockSizeAES128;
NSMutableData *cryptData = [NSMutableData dataWithLength:cryptLength];
size_t keyLength = kCCKeySizeAES128;
CCOptions options = kCCOptionPKCS7Padding;
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES, options, keyData.bytes, keyLength, ivData.bytes, data.bytes, data.length, cryptData.mutableBytes, cryptLength, &numBytesEncrypted);
if (cryptStatus == kCCSuccess) {
[cryptData replaceBytesInRange:NSMakeRange(numBytesEncrypted, cryptData.length - numBytesEncrypted) withBytes:NULL length:0];
}
return [cryptData base64EncodedStringWithOptions:0];
}
The problem is that the Objective-C version provides wrong results, I'd say random results, producing for the same combination of Hello World + ABCDEFGHIJKLMNOP different encrypted values.
7m+HH5NusyA1VAfZ78KYCw== or NY5p8XtYLoAE/4VbCCrPIg== are some of those wrong values.
If you decrypt these strings you get Hello Wold and Hello Worod respectively.
What did I do wrong while translating?
Thank you for your kind help!
CCCrypt()in both versions and compare the parameters. If they're the same, then probably the problem occurs after that. If they're different, that'd explain the problem. Also, looking at which parameters are different, if any, may point you toward the problem.