J'ai un fichier crypté avec AES. J'utilise la catégorie NSData suivante:NSData avec CCCrypt dans un environnement multithread
#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
Le processus de descrypt semble fonctionner correctement lorsque je charge le fichier entier du système de fichiers avec le code suivant:
[NSData dataWithContentsOfFile:dataPath];
Le problème se produit lorsque le fichier est pas lire avec l'appel précédent, mais quand un code externe qui tronque le fichier et init un NSData avec seulement un petit morceau de données et essayer de déchiffrer cela, en particulier les problèmes se produit lorsque différents threads utilisent ce code (ou du moins est ce que je pense):
- (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;
}
}
Qu'est-ce qui se passe est que la fonction CCCrypt dans ce cas échouer avec le code d'erreur -4304 AKA "kCCDecodeError - Données d'entrée n'a pas décodé ou déchiffrer correctement." De plus, si dans l'appel CCCrypt au lieu de kCCOptionPKCS7Padding je passe 0 -> pas de remplissage la méthode déchiffre le premier morceau de données mais quand le thread est commuté échoue avec -4300 AKA "kCCParamError - valeur de paramètre illégal."
Avec le message suivant dans la console:
[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
Quelqu'un peut-il aider?
Donc, votre suggestion est d'avoir une référence partagée de CCCryptor et l'utiliser entre plusieurs appels CCCryptorUpdate()? Je vais certainement essayer et je vous le ferai savoir! Mais l'option kCCOptionPKCS7Padding n'est pas utilisée pour ne pas se préoccuper du rembourrage? –
kCCOptionPKCS7Padding indique qu'il doit appliquer un remplissage PKCS à ce que vous lui remettez. Vous le transmettez au milieu d'un cours d'eau. Vous ne pouvez pas appliquer un remplissage aléatoire au milieu d'un flux. (Vous devez également garder une trace de votre IV, donc vous ne pouvez pas non plus commencer à déchiffrer au milieu du flux.) –
J'ai essayé d'implémenter ce que vous m'avez suggéré, mais il y a encore des problèmes: la classe qui appelle mon code et nécessite donc le morceau de données (et dont je n'ai aucun contrôle) nécessite parfois le morceau de données qui ne sont pas multiples de 16 octets plutôt généralement requis est de 2 octets et cela brise mon processus de décryptage –