Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/100.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 如何将此加密函数从Swift转换为Objective-C?_Ios_Objective C_Swift_Commoncrypto - Fatal编程技术网

Ios 如何将此加密函数从Swift转换为Objective-C?

Ios 如何将此加密函数从Swift转换为Objective-C?,ios,objective-c,swift,commoncrypto,Ios,Objective C,Swift,Commoncrypto,我正在为iOS Objective-C应用程序编写一个助手函数,该应用程序应该使用AES-128算法使用提供的密钥加密字符串 我已经在Swift中实现了此功能,但我正在努力将其翻译成Objective-C。该函数不考虑任何初始化向量,初始化向量硬编码为空字符串:这是有意的 以下是按预期工作的Swift代码: @objc func AES128(_ string: String, withKey: String) -> String { let data = string.data(

我正在为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();
}
问题是Objective-C版本提供了错误的结果,我可以说是随机结果,为相同的
Hello World
+
ABCDEFGHIJKLMNOP
不同加密值的组合生成。
7m+HH5NusyA1VAfZ78KYCw==
NY5p8XtYLoAE/4VbCCrPIg==
是一些错误的值。 如果您解密这些字符串,您将分别得到
Hello Wold
Hello wood

翻译时我做错了什么


谢谢你的帮助

这似乎是处理初始化向量的问题。如果您注意到,CCCrypt函数接受指向IV的字节缓冲区内容的指针,但您没有提供长度参数。这意味着缓冲区的长度是已知的

根据维基百科()的说法,IV的长度是“通常密码的块大小”

所以基本上,当你在做

NSData *ivData = [@"" dataUsingEncoding:NSUTF8StringEncoding];
ivData.bytes属性现在将指向某个地方,在最佳情况下,它的全长将为0x00,但很可能不会。CCCrypt()函数将从正在传递的内存地址(指向空数组的指针)开始,并使用在那里找到的任何随机数据继续读取下一个[IV长度]字节

要解决这个问题,您需要以某种方式确保您正在传递一个指向缓冲区的指针,该缓冲区包含您想要的全零内容

我做这件事很简单

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;
}

它将截断数据,使其成为您想要使用的部分。由您决定,因为结果与您已有的结果相同。

在两个版本中对
CCCrypt()
的调用上放置一个断点,并比较参数。如果它们是相同的,那么问题可能会在那之后出现。如果他们不同,那就可以解释问题了。另外,看看哪些参数是不同的,如果有的话,可能会向你指出问题所在。谢谢@BenW,你建议的编辑解决了这个问题,我将接受你的答案。出于好奇,您知道为什么Swift中带有空字符串的
Data
初始化会产生与Objective-C中的
NSData
不同的结果吗?还是因为在Objective-C中,我们处理的是指针而不是实际数据?很难说。根据Swift文档,数据被桥接到NSData类,并且可以在与ObjC API一起工作的代码中互换使用,但是在初始化过程中仍然可能存在一些差异。另外,我们实际上是在讨论Swift字符串和NSString之间的区别,因为您要求String/NSString对象使用某种编码方法生成自身的数据/NSData表示,因此也可能存在实现上的差异。我还可以通过使用[[NSData alloc]创建ivData来实现它然而,我无法向自己证明,这每一次都是可行的。确保每次都能正常工作的唯一方法是,如果您对所引用空间的内容持肯定态度。所以我想我说的是,我也不能解释为什么它在Swift版本中工作,但肯定有一些我们不知道的实现细节。在Swift中更安全的方法可能是使用数据(kCCBlockSizeAES128),它使用0初始化新数据。
if (cryptStatus == kCCSuccess)
{
    cryptData.length = numBytesEncrypted;
}