我正在为iOS Objective-C应用程序编写一个辅助函数,该函数应该使用AES-128算法使用提供的密钥对字符串进行加密。
我已经在Swift中对该函数进行了有效的实现,但是我正在努力将其转换为Objective-C。该函数不考虑任何初始化向量,该向量被硬编码为空字符串:这是有意的。
这是可以正常工作的Swift代码:
@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();
}
此函数的工作原理类似于超级按钮,并使用密钥对字符串Hello World
进行加密,ABCDEFGHIJKLMNOP
结果是base64编码的字符串3G4OU62dM9zXhkbXy8pmuA==
。
我将其翻译成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];
}
问题在于,Objective-C版本提供了错误的结果,我会说是随机结果,会产生Hello World
+ABCDEFGHIJKLMNOP
加密值的相同组合。7m+HH5NusyA1VAfZ78KYCw==
还是NY5p8XtYLoAE/4VbCCrPIg==
其中一些错误的值。如果解密这些字符串Hello Wold
,则Hello Worod
分别得到和。
翻译时我做错了什么?
谢谢你的热心帮助!
这似乎与您处理初始化向量有关。如果您注意到,CCCrypt函数接受一个指向IV的字节缓冲区内容的指针,但是您没有提供length参数。这意味着缓冲区的长度是已知的。
根据Wikipedia(https://en.wikipedia.org/wiki/Initialization_vector)的规定,IV的长度通常是“密码的块大小”。
所以基本上,当你做的时候
NSData *ivData = [@"" dataUsingEncoding:NSUTF8StringEncoding];
ivData.bytes属性现在将指向某个位置,在最佳情况下,该位置的全长为0x00,但很可能没有。CCCrypt()函数将从您正在传递的内存地址(指向空数组的指针)开始,并继续使用其在其中找到的任何随机数据读取下一个[IV Length]字节。
要解决此问题,您需要确保以某种方式将指针传递给包含期望的全零内容的缓冲区。
我只是这样做
void* ivBuffer = calloc(1, kCCBlockSizeAES128);
它分配一个128位(16字节)的块,并将其初始化为全零。
您对CCCrypt()的调用将变为
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES, options, keyData.bytes, keyLength, ivBuffer, data.bytes, data.length, cryptData.mutableBytes, cryptLength, &numBytesEncrypted);
而且您只需要记住调用free(ivBuffer)以释放为此缓冲区分配的内存。
另外,当您处理成功状态时,您可以
if (cryptStatus == kCCSuccess)
{
cryptData.length = numBytesEncrypted;
}
它将数据截断为您要使用的部分。取决于您,因为结果与您已有的结果相同。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句