Re: Feeding NSUnarchiver bad data can cause crash
Re: Feeding NSUnarchiver bad data can cause crash
- Subject: Re: Feeding NSUnarchiver bad data can cause crash
- From: "Louis C. Sacha" <email@hidden>
- Date: Thu, 3 Jun 2004 10:12:15 -0700
Hello...
Another possibility would be to append some sort of signature or
checksum to the end of the data produced by the archiver, before you
encrypt it.
Then after you decrypt the data, you could check the last bytes of
the data for the signature or verify the checksum before passing the
rest of the data to the unarchiver.
/* typed in email, etc... */
In other words, something like the following when you archive:
- (void)saveEncryptedArchiveFromObject:(id)plaintext
{
NSData *archivedData = [NSArchiver
archivedDataWithRootObject:plaintext];
// create a checksum NSData object, however you prefer (but
it should be a fixed length)
NSData *checksumData = [self
checksumDataCalculatedFor
Data:archivedData];
NSMutableData *combinedData = [NSMutableData
dataWith
Data:archivedData];
[combinedData append
Data:checksumData];
// encrypt your data
NSData *encryptedData = [self encryptedDataUsing
Data:combinedData];
// write the data out
[encryptedData writeToFile:@"/some/Path" atomically:TRUE];
Then, when decrypting:
- (id)archivedObjectFromEncryptedData:(NSData *)fileData
{
id plaintext = nil;
// unencrypt the data from the file
NSData *unencryptedData = [self unencryptedDataFrom
Data:fileData];
// break the data back into parts
NSData *archivedData = nil;
NSData *checksumData = nil;
unsigned rawLength = [unecryptedData length];
if (rawLength > CHECKSUM_LENGTH)
{
archivedData = [unecryptedData
subDataWithRange:NSMakeRange(0, rawLength - CHECKSUM_LENGTH)];
checksumData = [unecryptedData
subDataWithRange:NSMakeRange(rawLength - CHECKSUM_LENGTH ,
CHECKSUM_LENGTH)];
// verify the checksum
if ([self isValidChecksum:checksumData for
Data:archivedData])
{
// unarchive the data since checksum was valid
plaintext = [NSUnarchiver
unarchiveObjectWith
Data:archivedData];
}
}
return plaintext;
}
The checksumDataCalculatedForData:, isValidChecksum:forData:,
encryptedDataUsingData:, and unencryptedDataFromData: methods used
above would all be part of your own implementation.
Hope that helps,
Louis
The setup I'm using is this. An attributed string is archived, and
the archived data is encrypted using a Blowfish symmetric cipher,
producing a second data object which is saved to disk. Later, the
encrypted data is decrypted. If the key used for decryption is the
wrong one, the data will decrypt, but will be "bad" data. If this is
passed to an NSUnarchiver for unarchiving as an attributed string,
the unarchiver forces it to unarchive, resulting an error:
*** +[NSUnarchiver unarchiveObjectWithData:]: extra data discarded
and, sometimes, a SIGNAL 11 crash:
*** malloc_zone_malloc[414]: argument too large: 4294967286
If exactly the same encrypted data is decrypted with the correct
key, producing "good" data, it unarchives just fine, never crashes,
and all is cool.
The magic numbers you mention would be extremely useful if I knew
how to access them. Perhaps it's possible to parse the decrypted
data to see if the magic number is there? Or is it only present when
the archive is written to file? In my case, it's the encrypted
archive, not the archive itself, which is saved to disk.
Regards,
-Jeremy
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.