gpt4 book ai didi

objective-c - NSData 与 CCCrypt 在多线程环境中

转载 作者:行者123 更新时间:2023-12-04 06:25:08 41 4
gpt4 key购买 nike

我有一个使用 AES 加密的文件。
我使用以下 NSData 类别:

#import <CommonCrypto/CommonCryptor.h>

@implementation NSData (AES)

- (NSData *)AES256DecryptWithKey:(NSString *)key {

// 'key' should be 32 bytes for AES256, will be null-padded otherwise
char keyPtr[kCCKeySizeAES256+1]; // room for terminator (unused)
bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding)

// fetch key data
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];

NSUInteger dataLength = [self length];

//See the doc: For block ciphers, the output size will always be less than or
//equal to the input size plus the size of one block.
//That's why we need to add the size of one block here
size_t bufferSize = dataLength + kCCBlockSizeAES128;

void *buffer = malloc(bufferSize);

size_t numBytesDecrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt,
kCCAlgorithmAES128,
kCCOptionPKCS7Padding,
keyPtr,
kCCKeySizeAES256,
NULL /* initialization vector (optional) */,
[self bytes], dataLength, /* input */
buffer, bufferSize, /* output */
&numBytesDecrypted);

NSLog(@"Bytes decrypted: %d",numBytesDecrypted);

if (cryptStatus == kCCSuccess) {
//the returned NSData takes ownership of the buffer and will free it on deallocation
return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
}

NSLog(@"Decrypt failed with error code %d",cryptStatus);
free(buffer); //free the buffer;
return nil;
}

@end

当我使用以下代码从文件系统加载整个文件时,descrypt 过程似乎工作正常:
[NSData dataWithContentsOfFile:dataPath];

当文件没有被先前的调用读取时出现问题,但是当一个外部代码将文件分 block 并用一小块数据初始化一个 NSData 并尝试解密它时,特别是当不同的线程使用此代码时会出现问题(或者至少是我的想法):
- (NSData *)readDataOfLength:(NSUInteger)length
{
HTTPLogTrace2(@"%@[%p]: readDataOfLength:%lu", THIS_FILE, self, (unsigned long)length);

if (![self openFileIfNeeded])
{
// File opening failed,
// or response has been aborted due to another error.
return nil;
}

// Determine how much data we should read.
//
// It is OK if we ask to read more bytes than exist in the file.
// It is NOT OK to over-allocate the buffer.

UInt64 bytesLeftInFile = fileLength - fileOffset;

NSUInteger bytesToRead = (NSUInteger)MIN(length, bytesLeftInFile);

// Make sure buffer is big enough for read request.
// Do not over-allocate.

if (buffer == NULL || bufferSize < bytesToRead)
{
bufferSize = bytesToRead;
buffer = reallocf(buffer, (size_t)bufferSize);

if (buffer == NULL)
{
HTTPLogError(@"%@[%p]: Unable to allocate buffer", THIS_FILE, self);

[self abort];
return nil;
}
}

// Perform the read

HTTPLogVerbose(@"%@[%p]: Attempting to read %lu bytes from file", THIS_FILE, self, bytesToRead);

ssize_t result = read(fileFD, buffer, bytesToRead);

// Check the results

if (result < 0)
{
HTTPLogError(@"%@: Error(%i) reading file(%@)", THIS_FILE, errno, filePath);

[self abort];
return nil;
}
else if (result == 0)
{
HTTPLogError(@"%@: Read EOF on file(%@)", THIS_FILE, filePath);

[self abort];
return nil;
}
else // (result > 0)
{
HTTPLogVerbose(@"%@[%p]: Read %d bytes from file", THIS_FILE, self, result);

fileOffset += result;

NSData *data = [NSData dataWithBytes:buffer length:result];
return [data AES256DecryptWithKey:@"abcdefghijklmnopqrstuvwxyz123456"];
//return data;
}
}

发生的情况是,在这种情况下,函数 CCCrypt 失败,错误代码为 -4304 AKA “kCCDecodeError - 输入数据未正确解码或解密”。

此外,如果在 CCCrypt 调用而不是 kCCOptionPKCS7Padding 中,我通过 0 -> 不填充该方法解密第一 block 数据,但是当线程切换时,它会失败,并显示 -4300 AKA “kCCParamError - 非法参数值”。

在控制台中显示以下消息:
[Switching to process 13059 thread 0x0]
2011-05-25 18:00:03.631 Drm[1843:6e0b] Bytes decrypted: 131072
2011-05-25 18:00:03.647 Drm[1843:6e0b] Bytes decrypted: 68096
[Switching to process 11779 thread 0x0]
2011-05-25 18:00:04.547 Drm[1843:6e0b] Bytes decrypted: 0
2011-05-25 18:00:04.555 Drm[1843:6e0b] Decrypt failed with error code -4300

有人可以帮忙吗?

最佳答案

AES 是一种分组密码。您必须一次解密一个 block 。 AES block 是 128 位的(这与 AES256DecryptWithKey 中的“256”无关)。所以你必须保证你传递的数据是16字节的倍数。

我没试过CCCrypt()这样,这不是它的真正用途。 CCCrypt()当您想要进行一次性解密时,这是一个便利功能。当你想做“随用随用”的解密时,你可以使用 CCCryptorCreate()然后多次调用CCCryptorUpdate()最后是 CCCryptorFinal() (或者您可以调用 CCCryptorFinal() 然后调用 CCCryptorReset() 以使用相同的 key 解密更多内容)。最后您调用CCCryptorRelease()释放你的密码器。

编辑 我想了更多,并意识到 CCCrypt()即使您将输入分解为 16 字节的 block ,也不能以这种方式使用。每个 AES 加密 block 都会修改下一个 block 的 IV,因此您不能只在流中间启动某人。这就是为什么你需要一个持久的 CCCryptor对象在整个 session 中。

关于objective-c - NSData 与 CCCrypt 在多线程环境中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6127318/

41 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com