How can I discover the amount of free memory in iOS? - ios

How can I discover the amount of free memory in iOS?

Use this code:
natural_t freeMemory(void) {
mach_port_t host_port = mach_host_self();
mach_msg_type_number_t host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t);
vm_size_t pagesize;
vm_statistics_data_t vm_stat;
host_page_size(host_port, &pagesize);
if (host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size) != KERN_SUCCESS) NSLog(#"Failed to fetch vm statistics");
natural_t mem_used = (vm_stat.active_count + vm_stat.inactive_count + vm_stat.wire_count) * pagesize;
natural_t mem_free = vm_stat.free_count * pagesize;
natural_t mem_total = mem_used + mem_free;
return mem_free;
}
I'm not claiming credit for this code; I got it from here.
Hope this helps!

- (uint64_t)getFreeDiskspace
{
uint64_t totalSpace = 0;
uint64_t totalFreeSpace = 0;
__autoreleasing error = nil;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSDictionary *dictionary = [[NSFileManager defaultManager] attributesOfFileSystemForPath:[paths lastObject] error: &error];
if (dictionary) {
NSNumber *fileSystemSizeInBytes = [dictionary objectForKey: NSFileSystemSize];
NSNumber *freeFileSystemSizeInBytes = [dictionary objectForKey:NSFileSystemFreeSize];
totalSpace = [fileSystemSizeInBytes unsignedLongLongValue];
totalFreeSpace = [freeFileSystemSizeInBytes unsignedLongLongValue];
NSLog(#"Memory Capacity of %llu MiB with %llu MiB Free memory available.", ((totalSpace/1024ll)/1024ll), ((totalFreeSpace/1024ll)/1024ll));
} else {
NSLog(#"Error Obtaining System Memory Info: Domain = %#, Code = %d", [error domain], [error code]);
}
return totalFreeSpace;
}
This is working

Related

Getting wrong Value after I decrypt the String using 3DES in Objective-c

3DES encryption is working fine and getting wrong values for decryption with same logic.
Please find the below logic to call Encryption / Decryption method
NSString *cipherEnString = [self doCipher:#"Test" enc:kCCEncrypt];
NSString *cipherDecString = [self doCipher:cipherEnString enc:kCCDecrypt];
And the code for Encryption / Decryption is added below.
- (NSString*) doCipher:(NSString*)plainText enc:(CCOperation)encryptOrDecrypt{
const void *vplainText;
size_t plainTextBufferSize;
if (encryptOrDecrypt == kCCDecrypt)
{
NSString *encStr = [self encodeStringTo64:plainText];
NSData *EncryptData = [encStr dataUsingEncoding:NSUTF8StringEncoding];
plainTextBufferSize = [EncryptData length];
vplainText = [EncryptData bytes];
}
else
{
plainTextBufferSize = [plainText length];
vplainText = (const void *) [plainText UTF8String];
}
CCCryptorStatus ccStatus;
uint8_t *bufferPtr = NULL;
size_t bufferPtrSize = 0;
size_t movedBytes = 0;
// uint8_t ivkCCBlockSize3DES;
bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1);
bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t));
memset((void *)bufferPtr, 0x0, bufferPtrSize);
unsigned char secretKey[24]= {0x01, 0x02, 0x03, 0x05, 0x07, 0x0B, 0x0D, 0x11,0x12, 0x11, 0x0D, 0x0B, 0x07, 0x02, 0x04,0x08,0x01, 0x02, 0x03, 0x05, 0x07, 0x0B, 0x0D, 0x11};
unsigned char IV3[8]={0x01, 0x02, 0x03, 0x05, 0x07, 0x0B, 0x0D, 0x11};
uint8_t iv[kCCBlockSize3DES];
memset((void *) iv, 0x0, (size_t) sizeof(iv));
ccStatus = CCCrypt(encryptOrDecrypt,
kCCAlgorithm3DES,
kCCOptionPKCS7Padding ,
secretKey, //"123456789012345678901234", //key
kCCKeySize3DES,
IV3 , //iv,
vplainText, //plainText,
plainTextBufferSize,
(void *)bufferPtr,
bufferPtrSize,
&movedBytes);
/*else*/ if (ccStatus == kCCParamError) return #"PARAM ERROR";
else if (ccStatus == kCCBufferTooSmall) return #"BUFFER TOO SMALL";
else if (ccStatus == kCCMemoryFailure) return #"MEMORY FAILURE";
else if (ccStatus == kCCAlignmentError) return #"ALIGNMENT";
else if (ccStatus == kCCDecodeError) return #"DECODE ERROR";
else if (ccStatus == kCCUnimplemented) return #"UNIMPLEMENTED";
NSString *result;
if (encryptOrDecrypt == kCCDecrypt)
{
result = [ [NSString alloc] initWithData: [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes] encoding:NSASCIIStringEncoding];
NSString *s = [[NSString alloc] initWithBytes:bufferPtr
length:movedBytes
encoding:NSUTF8StringEncoding];
NSLog(#"%#",s);
}
else
{
NSData *myData = [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes];
NSString *base64String = [myData base64EncodedStringWithOptions:0];
return base64String;
}
return result;
}
- (NSString*)encodeStringTo64:(NSString*)fromString
{
NSData *plainData = [fromString dataUsingEncoding:NSUTF8StringEncoding];
NSString *base64String;
if ([plainData respondsToSelector:#selector(base64EncodedStringWithOptions:)]) {
base64String = [plainData base64EncodedStringWithOptions:kNilOptions]; // iOS 7+
}
else {
NSString *base64String = [plainData base64EncodedStringWithOptions:0];
NSLog(#"%#", base64String);// pre iOS7
}
return base64String;
}
You are trying to hard to convert the base64 encrypted string to encrypted data:
Current:
NSString *encStr = [self encodeStringTo64:plainText];
NSData *encryptData = [encStr dataUsingEncoding:NSUTF8StringEncoding];
Correct:
NSData *encryptData = [[NSData alloc] initWithBase64EncodedString:plainText options:0];
Additionally you don't need the method:
- (NSString *)encodeStringTo64:(NSString*)fromString
Adding a couple of hex dumps of the data to be encrypted/decrypted before and after would show this problem.
It is also better to create a basic encryption method that takes and returns NSData and add methods that perform any encoding/decoding that call the encryption method. Less co-mingling of responsibilities makes the code simpler and easier to understand and debug.
See this SO answer to see how to eliminate malloc and instead just use NSMutableData instead.

How can we encrypt bytes through DES/CBC/NOPADDING in Objective C?

I am trying to encrypt bytes data through DES/CBS/NOPADDING algorithm but unable to get correct output. What I have tried is given below in code. Please have a look and suggest.
#import "STEncryptViewController.h"
#import <CommonCrypto/CommonCryptor.h>
#import "STEncryptorDES.h"
#import "NSData+Base64.h"
#import <CommonCrypto/CommonDigest.h>
#define KEY #"MY_TEST_KEY"
#interface STEncryptViewController ()
#end
#implementation STEncryptViewController
#synthesize message;
#synthesize encrypted;
#synthesize decrypted;
#synthesize key;
#synthesize outputMessage;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
- (IBAction)encrypt:(id)sender
{
const unsigned char bytes[] = {65,17,17,17,17,17,17,17};
NSData *data = [NSData dataWithBytes:bytes length:sizeof(bytes)];
NSString *str = self.key.text;
NSData* data12 = [str dataUsingEncoding:NSUTF8StringEncoding];
NSUInteger len = str.length;
uint8_t *bytes1 = (uint8_t *)[data12 bytes];
NSMutableString *result = [NSMutableString stringWithCapacity:len * 3];
// [result appendString:#"["];
//Key convertion
int i = 0;
while(i < len){
if (i) {
[result appendString:#","];
}
[result appendFormat:#"%d", bytes1[i]];
i++;
}
// [result appendString:#"]"];
NSLog (#"String is %#",str);
NSLog (#"Byte array is %#",result);
//
Byte iv1 [] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
Byte iv [] = {1, 35, 69, 103, -119, -85, -51, -17};
NSData *ivData = [NSData dataWithBytes:iv length:sizeof(iv)];
NSData *encryptedData = [STEncryptorDES encryptData1:data key:[NSData dataWithBytes:iv1 length:sizeof(iv1)] iv:ivData];
NSLog(#"encrypted : %#", [encryptedData base64EncodedString]);
self.outputMessage.text = [NSString stringWithFormat:#"Encrypted String ::>> %#",[encryptedData base64EncodedString]];
[self doCipher:nil enc:kCCEncrypt];
}
- (NSData *)md5DataFromString:(NSString *)input
{
const char *cStr = [input UTF8String];
unsigned char digest[16];
CC_MD5( cStr, strlen(cStr), digest ); // This is the md5 call
return [NSData dataWithBytes:digest length:CC_MD5_DIGEST_LENGTH];
}
- (IBAction)decrypt:(id)sender
{
NSData *valueData = [self hexToBytes:self.decrypted.text];
NSData *keyData = [self md5DataFromString:self.key.text];
Byte iv [] = {1, 35, 69, 103, -119, -85, -51, -17};
NSData *ivData = [NSData dataWithBytes:iv length:sizeof(iv)];
NSData *decryptedData = [STEncryptorDES decryptData:valueData key:keyData iv:ivData];
NSLog(#"decrypted : %#", [[NSString alloc] initWithData:decryptedData encoding:NSASCIIStringEncoding]);
self.outputMessage.text = [NSString stringWithFormat:#"Decrypted String ::>> %#", [[NSString alloc] initWithData:decryptedData encoding:NSASCIIStringEncoding]];
}
- (NSString*)doCipher:(NSString*)plainText enc:(CCOperation)encryptOrDecrypt{
NSData *key123 = [self hexToBytes:#"MY_TEST_KEY"];
const void *vplainText;
size_t plainTextBufferSize;
if (encryptOrDecrypt == kCCDecrypt)
{
NSData *EncryptData = [self hexToBytes:#"5454545454545454"];
// NSData *EncryptData =[NSData dataWithBase64EncodedString:plainText];
plainTextBufferSize = [EncryptData length];
vplainText = [EncryptData bytes];
}
else
{
plainTextBufferSize = [plainText length];
vplainText = (const void *) [plainText UTF8String];
}
CCCryptorStatus ccStatus;
uint8_t *bufferPtr = NULL;
size_t bufferPtrSize = 0;
size_t movedBytes = 0;
// uint8_t ivkCCBlockSize3DES;
bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1);
bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t));
memset((void *)bufferPtr, 0x0, bufferPtrSize);
unsigned char cKey[FBENCRYPT_KEY_SIZE];
bzero(cKey, sizeof(cKey));
[key123 getBytes:cKey length:FBENCRYPT_KEY_SIZE];
//unsigned char result1[24]= {0,0,0,0,0,0,0,0,0,0,0,00,0,0,0,0,0,0,0,00,00,00,00,0};
unsigned char IV3[8]={1, 35, 69, 103, -119, -85, -51, -17};
uint8_t iv[kCCBlockSize3DES];
memset((void *) iv, 0x0, (size_t) sizeof(iv));
ccStatus = CCCrypt(encryptOrDecrypt,
kCCAlgorithm3DES,
0x0000 ,
cKey, //"123456789012345678901234", //key
kCCKeySize3DES,
IV3 , //iv,
vplainText, //plainText,
plainTextBufferSize,
(void *)bufferPtr,
bufferPtrSize,
&movedBytes);
//if (ccStatus == kCCSuccess) NSLog(#"SUCCESS");
/*else*/ if (ccStatus == kCCParamError) return #"PARAM ERROR";
else if (ccStatus == kCCBufferTooSmall) return #"BUFFER TOO SMALL";
else if (ccStatus == kCCMemoryFailure) return #"MEMORY FAILURE";
else if (ccStatus == kCCAlignmentError) return #"ALIGNMENT";
else if (ccStatus == kCCDecodeError) return #"DECODE ERROR";
else if (ccStatus == kCCUnimplemented) return #"UNIMPLEMENTED";
NSString *result;
if (encryptOrDecrypt == kCCDecrypt)
{
result = [ [NSString alloc] initWithData: [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes] encoding:NSASCIIStringEncoding];
}
else
{
NSData *myData = [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes];
NSLog(#"data is: %#", myData);
// result = [NSData base64StringFromData:myData length:myData.length];
// result = [[NSString alloc]initWithData:myData encoding:NSUTF8StringEncoding];
result = nil;
}
return result;
}
-(NSData*)hexToBytes:(NSString *)hex {
NSString *safeStr = [hex stringByReplacingOccurrencesOfString:#"0" withString:#"A"];
NSMutableData* data = [NSMutableData data];
int idx;
for (idx = 0; idx+2 <= safeStr.length; idx+=2) {
NSRange range = NSMakeRange(idx, 2);
NSString* hexStr = [safeStr substringWithRange:range];
NSScanner* scanner = [NSScanner scannerWithString:hexStr];
unsigned int intValue;
[scanner scanHexInt:&intValue];
[data appendBytes:&intValue length:1];
}
NSLog(#"%lu",(unsigned long)data.hash);
return data;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
This was my all effort. Currently it is working but not expected output getting. Please suggest me what am I missing here?
One glaring error is that STEncryptorDES is used and is specifies padding but the question states that padding should be used.
Observations:
- You call doCipher with nil and do not use it's return value, delete the unneeded/unused code from the question.
- There is a lot of code to perform a rather simple operation.
- It seems that the test data variable is named iv1, use a better name if that is correct.
- DES should not be used for new work, only when necessary to interoperate with existing work, it is not very secure. New work should use AES.
- #synthesize has not been needed for several years.
In cryptography "DESede/CBC/NoPadding" use following code might be help for you.
Byte iv [] = {1, 35, 69, 103, -119, -85, -51, -17};
NSData *ivData = [NSData dataWithBytes:iv length:sizeof(iv)];
NSData key = ["MY_TEST_KEY" dataUsingEncoding:NSUTF8StringEncoding]
char cKey[key.length];
bzero(cKey, sizeof(cKey));
[key getBytes:cKey length:key.length];
// setup iv
char cIv[kCCBlockSizeDES];
bzero(cIv, kCCBlockSizeDES);
if (ivData) {
[ivData getBytes:cIv length:kCCBlockSizeDES];
}
// setup output buffer
size_t bufferSize = [data length] + kCCBlockSizeDES;
void *buffer = malloc(bufferSize);
// do encrypt
size_t encryptedSize = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
kCCAlgorithm3DES,
ccNoPadding,
cKey,
key.length,
cIv,
[data bytes],
[data length],
buffer,
bufferSize,
&encryptedSize);
if (cryptStatus == kCCSuccess) {
resultData = [NSData dataWithBytes:buffer length:encryptedSize];
free(buffer);
} else {
free(buffer);
NSLog(#"[ERROR] failed to encrypt|CCCryptoStatus: %d", cryptStatus);
return nil;
}

Storing and Retrieving compressed texts as BLOB from Sqlite via FMDB

I am trying to store text data as compressed blobs.
[db executeUpdate:#"create table blobTable (a text, b blob)"];
[db executeUpdate:#"insert into blobTable (a, b) values (?, compressMe('random text string'))", #"lord of the rings"];
And then I try to query them using:
FMResultSet *rs = [db executeQuery:#"select uncompressMe(b) as k from blobTable where a = ?", #"lord of the rings"];
Where compressMe and uncompressMe are defined as:
FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:dbPath];
[queue inDatabase:^(FMDatabase *adb) {
[adb makeFunctionNamed:#"compressMe" maximumArguments:1 withBlock:^(sqlite3_context *context, int aargc, sqlite3_value **aargv) {
if (sqlite3_value_type(aargv[0]) == SQLITE_TEXT) {
#autoreleasepool {
const char *c = (const char *)sqlite3_value_text(aargv[0]);
NSString *s = [NSString stringWithUTF8String:c];
NSLog(#"string to compress: %#", s);
NSData *compressedBody = [self gzipDeflate:[s dataUsingEncoding:NSUTF8StringEncoding]];
sqlite3_result_blob(context, (__bridge const void *)(compressedBody), [compressedBody length], nil);
}
}
else {
NSLog(#"Unknown formart for StringStartsWithH (%d) %s:%d", sqlite3_value_type(aargv[0]), __FUNCTION__, __LINE__);
sqlite3_result_null(context);
}
}];
}];
[queue inDatabase:^(FMDatabase *adb) {
[adb makeFunctionNamed:#"uncompressMe" maximumArguments:1 withBlock:^(sqlite3_context *context, int aargc, sqlite3_value **aargv) {
if (sqlite3_value_type(aargv[0]) == SQLITE_BLOB) {
#autoreleasepool {
NSLog(#"inside uncompressMe");
NSUInteger len = sqlite3_value_bytes(aargv[0]);
Byte *byteData = (Byte*)malloc(len);
memcpy(byteData, sqlite3_value_blob(aargv[0]), len);
NSData *data = [[NSData alloc] initWithBytes:byteData length:len];
NSData *deflatedBody = [self gzipInflate:data];
NSString *deflatedString = [[NSString alloc] initWithData:deflatedBody encoding:NSUTF8StringEncoding];
sqlite3_result_text(context, (__bridge const void *)(deflatedString), -1, SQLITE_UTF8);
}
}
else {
NSLog(#"Unknown formart for StringStartsWithH (%d) %s:%d", sqlite3_value_type(aargv[0]), __FUNCTION__, __LINE__);
sqlite3_result_null(context);
}
}];
}];
For the sake of completeness, the zip functions are defined as such:
- (NSData *)gzipInflate:(NSData*)data
{
if ([data length] == 0) return data;
unsigned full_length = [data length];
unsigned half_length = [data length] / 2;
NSMutableData *decompressed = [NSMutableData dataWithLength: full_length + half_length];
BOOL done = NO;
int status;
z_stream strm;
strm.next_in = (Bytef *)[data bytes];
strm.avail_in = [data length];
strm.total_out = 0;
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
if (inflateInit2(&strm, (15+32)) != Z_OK) return nil;
while (!done)
{
// Make sure we have enough room and reset the lengths.
if (strm.total_out >= [decompressed length])
[decompressed increaseLengthBy: half_length];
strm.next_out = [decompressed mutableBytes] + strm.total_out;
strm.avail_out = [decompressed length] - strm.total_out;
// Inflate another chunk.
status = inflate (&strm, Z_SYNC_FLUSH);
if (status == Z_STREAM_END) done = YES;
else if (status != Z_OK) break;
}
if (inflateEnd (&strm) != Z_OK) return nil;
// Set real length.
if (done)
{
[decompressed setLength: strm.total_out];
return [NSData dataWithData: decompressed];
}
else return nil;
}
- (NSData *)gzipDeflate:(NSData*)data
{
if ([data length] == 0) return data;
z_stream strm;
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.total_out = 0;
strm.next_in=(Bytef *)[data bytes];
strm.avail_in = [data length];
// Compresssion Levels:
// Z_NO_COMPRESSION
// Z_BEST_SPEED
// Z_BEST_COMPRESSION
// Z_DEFAULT_COMPRESSION
if (deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, (15+16), 8, Z_DEFAULT_STRATEGY) != Z_OK) return nil;
NSMutableData *compressed = [NSMutableData dataWithLength:16384]; // 16K chunks for expansion
do {
if (strm.total_out >= [compressed length])
[compressed increaseLengthBy: 16384];
strm.next_out = [compressed mutableBytes] + strm.total_out;
strm.avail_out = [compressed length] - strm.total_out;
deflate(&strm, Z_FINISH);
} while (strm.avail_out == 0);
deflateEnd(&strm);
[compressed setLength: strm.total_out];
return [NSData dataWithData:compressed];
}
However, the uncompressMe function doesnt seem to succeed. It fails in the Inflate method, which always returns a nil. Any thoughts what I might be doing wrong? I have checked to make sure that the blob column does get populated.
I feel like issue is from below code:
NSUInteger len = sqlite3_value_bytes(aargv[0]);
Byte *byteData = (Byte*)malloc(len);
memcpy(byteData, sqlite3_value_blob(aargv[0]), len);
NSData *data = [[NSData alloc] initWithBytes:byteData length:len];
Try this to load NSData from database instead of creating byte variable and copying it.
const void *bytes = sqlite3_column_blob(statement, 3);
NSData *data = [[NSData alloc] initWithBytes:bytes length:size];

AES 128 with CBC

I'm going mad with a simple AES 128 in Objective C and there's no way to get the expected ciphered text in a simple test. Could anyone tell me what am I doing wrong?
Test:
- (void)testAES128_1
{
NSString *testVector = #"6bc1bee22e409f96e93d7e117393172a";
NSString *initVector = #"000102030405060708090A0B0C0D0E0F";
NSString *key = #"2b7e151628aed2a6abf7158809cf4f3c";
NSString *expected = #"7649abac8119b246cee98e9b12e9197d";
NSData *inputData = [self dataFromHexString:testVector];
NSData *keyData = [self dataFromHexString:key];
NSData *expectedData = [self dataFromHexString:expected];
NSData *current = [inputData AES128EncryptWithIV:initVector andKey:key];
// What I get in current = cf2ea38a123be20765eb8c5c56caf224 != expected
BOOL res = [inputData isEqualToData:current];
XCTAssertTrue(res);
}
// For Converting incoming HexString into NSData
- (NSData *)dataFromHexString:(NSString *)string
{
NSMutableData *stringData = [[NSMutableData alloc] init];
unsigned char whole_byte;
char byte_chars[3] = {'\0','\0','\0'};
int i;
for (i=0; i < [string length] / 2; i++) {
byte_chars[0] = [string characterAtIndex:i*2];
byte_chars[1] = [string characterAtIndex:i*2+1];
whole_byte = strtol(byte_chars, NULL, 16);
[stringData appendBytes:&whole_byte length:1];
}
return stringData;
}
Category NSData (AES):
- (NSData *)AES128EncryptWithIV:(NSString *)iv andKey:(NSString *)key {
char ivPtr[kCCKeySizeAES128 + 1];
bzero(ivPtr, sizeof(ivPtr));
// fetch iv data
[iv getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding];
char keyPtr[kCCKeySizeAES128+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 numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, 0,
keyPtr, kCCKeySizeAES128,
ivPtr /* initialization vector (optional) */,
[self bytes], dataLength, /* input */
buffer, bufferSize, /* output */
&numBytesEncrypted);
if (cryptStatus == kCCSuccess) {
//the returned NSData takes ownership of the buffer and will free it on deallocation
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}
free(buffer); //free the buffer;
return nil;
}
I am working with these set of AES test vectors:
http://www.inconteam.com/software-development/41-encryption/55-aes-test-vectors#aes-cbc-128
Thanks
Simply you are not converting the iv in hex ascii to an NSData. The example test vector have an iv so to obtain the matching cipher text you need to use the Initialization vector.
Note: The line:
BOOL res = [inputData isEqualToData:current];
should be:
BOOL res = [expectedData isEqualToData:current];
Note: The output block count is not larger if there is no padding.
Here is my test code:
No need for a Category, I just make there methods class methods.
+ (void)testAES128_1 {
NSString *testVector = #"6bc1bee22e409f96e93d7e117393172a";
NSString *initVector = #"000102030405060708090A0B0C0D0E0F";
NSString *key = #"2b7e151628aed2a6abf7158809cf4f3c";
NSString *expected = #"7649abac8119b246cee98e9b12e9197d";
NSData *inputData = [self dataFromHexString:testVector];
NSData *keyData = [self dataFromHexString:key];
NSData *ivData = [self dataFromHexString:initVector];
NSData *expectedData = [self dataFromHexString:expected];
NSError *error;
NSData *current = [Test doCipher:inputData
iv:ivData
key:keyData
context:kCCEncrypt
error:&error];
BOOL res = [expectedData isEqualToData:current];
NSLog(#"Match: %#", res ? #"Yes" : #"No"); // Match: Yes
}
+ (NSData *)doCipher:(NSData *)dataIn
iv:(NSData *)iv
key:(NSData *)symmetricKey
context:(CCOperation)encryptOrDecrypt // kCCEncrypt or kCCDecrypt
error:(NSError **)error
{
CCCryptorStatus ccStatus = kCCSuccess;
size_t cryptBytes = 0;
NSMutableData *dataOut = [NSMutableData dataWithLength:dataIn.length + kCCBlockSizeAES128];
ccStatus = CCCrypt( encryptOrDecrypt,
kCCAlgorithmAES128,
0, //kCCOptionPKCS7Padding,
symmetricKey.bytes,
kCCKeySizeAES128,
iv.bytes,
dataIn.bytes,
dataIn.length,
dataOut.mutableBytes,
dataOut.length,
&cryptBytes);
if (ccStatus == kCCSuccess) {
dataOut.length = cryptBytes;
}
else {
if (error) {
*error = [NSError errorWithDomain:#"kEncryptionError"
code:ccStatus
userInfo:nil];
}
dataOut = nil;
}
return dataOut;
}

Use CCCrypt encrypt/decrypt file

I don't know why the original mp3Data size is 4750347 bytes, and decryptData size is 4750344 bytes
Is there any implemetation error in TripleDES method?
Thanks for any reply.
- (void) testTripleDESMp3
{
NSString * mp3Path = [[self libraryPath]stringByAppendingPathComponent:#"A.mp3"];
NSData *mp3Data = [[NSData alloc] initWithContentsOfFile:mp3Path] ;//4750347
NSData *encryptData = [self TripleDES:mp3Data encryptOrDecrypt:kCCEncrypt key:#"12345"];//bufferPtrSize 4750352, plainTextBufferSize:4750347, movedBytes:47503520 ,NSData 6333804
NSData *decryptData = [self TripleDES:encryptData encryptOrDecrypt:kCCDecrypt key:#"12345"];//bufferPtrSize 4750360, plainTextBufferSize:4750352, movedBytes:4750344,NSData 4750344
//mp3Data 4750347 -> encryptData 6333804-> decryptData 4750344
NSError* error;
NSString * mp3Path2 = [[self libraryPath]stringByAppendingPathComponent:#"B.mp3"];
[decryptData writeToFile:mp3Path2 options:NSDataWritingAtomic error:&error];
}
- (NSData*)TripleDES:(NSData*)plainData encryptOrDecrypt:(CCOperation)encryptOrDecrypt key:(NSString*)key {
const void *vplainText;
size_t plainTextBufferSize;
if (encryptOrDecrypt == kCCDecrypt)
{
NSData *EncryptData = [GTMBase64 decodeData:plainData];
plainTextBufferSize = [EncryptData length];
vplainText = [EncryptData bytes];
}
else
{
plainTextBufferSize = [plainData length];
vplainText = (const void *)[plainData bytes];
}
CCCryptorStatus ccStatus;
//I am not sure use char*/void*/uint8_t
uint8_t *bufferPtr = NULL;
size_t bufferPtrSize = 0;
size_t movedBytes = 0;
bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1);
bufferPtr = static_cast<uint8_t *>(malloc( bufferPtrSize * sizeof(uint8_t)));
//bufferPtr = (char *)malloc( bufferPtrSize * sizeof(char));
memset((void *)bufferPtr, 0x0, bufferPtrSize);
// memset((void *) iv, 0x0, (size_t) sizeof(iv));
NSString *initVec = #"init Vec";
const void *vkey = (const void *) [key UTF8String];
const void *vinitVec = (const void *) [initVec UTF8String];
ccStatus = CCCrypt(encryptOrDecrypt,
kCCAlgorithm3DES,
kCCOptionPKCS7Padding,//kCCOptionECBMode,
vkey,
kCCKeySize3DES,
vinitVec, //"init Vec", //iv,
vplainText, //"Your Name", //plainText,
plainTextBufferSize,
(void *)bufferPtr,
bufferPtrSize,
&movedBytes);
if (ccStatus == kCCSuccess) NSLog(#"SUCCESS");
else if (ccStatus == kCCParamError) NSLog( #"PARAM ERROR");
else if (ccStatus == kCCBufferTooSmall) NSLog( #"BUFFER TOO SMALL");
else if (ccStatus == kCCMemoryFailure) NSLog( #"MEMORY FAILURE");
else if (ccStatus == kCCAlignmentError) NSLog( #"ALIGNMENT");
else if (ccStatus == kCCDecodeError) NSLog( #"DECODE ERROR");
else if (ccStatus == kCCUnimplemented) NSLog( #"UNIMPLEMENTED");
NSData *result;
if (encryptOrDecrypt == kCCDecrypt)
{
result = [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes];
}
else
{
NSData *myData = [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes];
result = [GTMBase64 encodeData:myData];
}
//bufferPtrSize 1931240, plainTextBufferSize:1931232, movedBytes:1931232
NSLog(#"bufferPtrSize %d, plainTextBufferSize:%d, movedBytes:%d", (int)bufferPtrSize,(int)plainTextBufferSize, (int)movedBytes);//
return result;
}

Resources