RNCryptor "encryptData" returning null - ios

New to iOS dev, trying to work on encoding data for secure data storage in db.
I found the current example here: https://github.com/RNCryptor/RNCryptor-objc
This is my code.
NSString * aPassword =#"tempkey";
NSData *data = [#"Data" dataUsingEncoding:NSUTF8StringEncoding];
NSError *error;
NSData *encryptedData = [RNEncryptor encryptData:data
withSettings:kRNCryptorAES256Settings
password:aPassword
error:&error];
NSLog(#"Data: %#", [[NSString alloc] initWithData:encryptedData encoding:NSUTF8StringEncoding]);
My log
2016-10-20 11:41:52.662 BlueBoard[57245:10027277] Data: (null)
Am I missing a step in this process? I've confirmed that it's null because it the db its being stored as null as well.

Your issue isn't that encryptedData is nil, it's that you are attempted to create an NSString from data that doesn't represent a string.
If you wish to convert encryptedData into a string for storage or other purposes, you should convert the data into a Base 64 encoded representation. Do this with the base64EncodedStringWithOptions: method.
NSString *base64String = [encryptedData base64EncodedStringWithOptions:0];
Of course when you want to decrypt the string later, you will need to convert the Base 64 encoded string back into NSData, and then decrypt that data.

Related

Check type of class an NSData store?

I have a library that process a string and converts it to an unknown format and insert it into a NSData. In a part of the code that library check if the NSData is empty, if not it sends to the server:
if (!dataToSend) {
return;
}
I thought the stored value would be a string or base64, for that tested the following codes:
NSLog(#"To string -> %#",[NSString stringWithUTF8String:[dataToSend bytes]]);
NSString *decodedString = [[NSString alloc] initWithData:dataToSend encoding:NSUTF8StringEncoding];
NSLog(#"Decode String Value: %#", decodedString);
In console I continue receiving (null), but the data is not null once I insert that code below from return;. How I can check the type of that NSData stores?
Check the type of NSData
if([yourData isKindOfClass: [NSData class]])

Change UIImage Class to send to node.js server in iOS?

I am creating an App for chatting. Now I want to send UIImage to server in JSON String so other user can receive image.I am using socket.io so I have to send event with data(JSON String).
Problems- When I try to convert UIImage to NSData and convert it to JSON it gives error 'Invalid type in JSON write (NSConcreteMutableData)'.
What will be the correct way to send UIImage to server?
code
NSData *imgData = UIImageJPEGRepresentation(image, .2);
NSString * imageString =[[NSString alloc]initWithBytes:[imageData bytes] length:[imageData length] encoding:NSASCIIStringEncoding];
also tried
NSString * imageString =[[NSString alloc]initWithData :imgData encoding:NSUTF8StringEncoding];
converted data to dictionary:
NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:imgData options:NSJSONReadingAllowFragments error:&error];
Any help would be appreciated.
The general approach would be to base64 encode the image data. In this way the image data is converted to a string format instead of binary.
Since iOS 7 NSData has provided base64 conversion methods that you can use instead of your current attempted conversion to and from strings.

Unable to generate an AES 256 key from password and salt for use with RNCryptor

I want to generate a key with Salt for AES 256 encryption.I am using BBASE lib, referred this link:
Create random 128 bit AES Encryption key in iOS
My code is:
NSData* salt = [BBAES randomDataWithLength:BBAESSaltDefaultLength];
NSData *key = [BBAES keyBySaltingPassword:#"password" salt:salt keySize:BBAESKeySize256 numberOfIterations:BBAESPBKDF2DefaultIterationsCount];
NSLog(#"Data ASE Key %#",key);
NSString *aString = [[NSString alloc] initWithData:key encoding:NSUTF8StringEncoding];
I want to use this 'key' into the following code:(here I am using RNCryptor lib)
NSData *encryptedData = [ RNEncryptor encryptData:bodyData withSettings:kRNCryptorAES256Settings password:aString error:&error];
NSData *decryptedData = [RNDecryptor decryptData:encryptedData withSettings:kRNCryptorAES256Settings password:aString error:&error];
I need to pass key of type NSString,But when I am converting NSData to NSString it gives NULL value and my application crashes. What should I do?? Is there any solution for this ??
Not all data is a valid UTF-8 string, most random data is not. Basically that is why Base64 exists, to convert 8-bit data to an ASCII string--and back. There are of course other methods.
But as Duncan states, why? Read the RNCryptor code, it already handles converting a password (string) to a secure key.
Thank you #Duncan & #Zaph :) I found a solution!!
Instead of
NSString *aString = [[NSString alloc] initWithData:key encoding:NSUTF8StringEncoding];
I used this:
NSString *aString = [[NSString alloc] initWithData:key encoding:NSASCIIStringEncoding];

Encoding for converting between NSString to NSData and back

I'm trying to encrypt/decrypt an NSString and return the original string in the end. Here's how I convert the string to a data object:
NSData *string_data = [string dataUsingEncoding:NSUTF8StringEncoding];
And after that data has been encrypted/decrypted I want it back to the original string by doing:
NSString *to_string = [NSString stringWithCString:[decrypted_data bytes] encoding:NSUTF8StringEncoding];
The encoding seems to match, but I still get a null when I try to print out to_string to the console. I've tried all sorts of encoding settings. It doesn't seem to work.
Use:
NSString *to_string = [[NSString alloc] initWithData:string_data encoding:NSUTF8StringEncoding];
It is not safe to use stringWithCString because the bytes buffer you get from NSData is not guaranteed to be null-terminated.

RNCryptor not working with JSON string

Here are my method's to use RNCryptor to encrypt/decrypt a JSON string that I am sending to the web service. I am using a static IV variable which may be bad practice but please don't focus on that. Here is how I'm doing it:
Note: I'm using Matt Gallagher's NSData+Base64 category found here (at bottom of page)
-(NSString*)encryptString:(NSString*)plaintext withKey:(NSString*)key error:(NSError**)error{
NSData *data = [plaintext dataUsingEncoding:NSUTF8StringEncoding];
NSData *encryptionKey = [NSData dataFromBase64String:key];
NSData *IV = [NSData dataFromBase64String:ENCRYPTION_IV];
RNCryptorEngine *engine = [[RNCryptorEngine alloc] initWithOperation:kCCEncrypt settings:kRNCryptorAES256Settings key:encryptionKey IV:IV error:error];
[engine addData:data error:error];
NSData *encryptedData = [engine finishWithError:error];
NSString *based64Encrypted = [encryptedData base64EncodedString];
NSLog(#"Encrytped: %#", based64Encrypted);
return based64Encrypted;
}
-(NSString*) decryptString:(NSString*)cipherText withKey:(NSString*)key error:(NSError**)error;{
NSData *data = [NSData dataFromBase64String:cipherText];
NSData *encryptionKey = [NSData dataFromBase64String:key];
NSData *IV = [NSData dataFromBase64String:ENCRYPTION_IV];
RNCryptorEngine *engine = [[RNCryptorEngine alloc] initWithOperation:kCCDecrypt settings:kRNCryptorAES256Settings key:encryptionKey IV:IV error:error];
[engine addData:data error:error];
NSData *decryptedData = [engine finishWithError:error];
NSString *decryptedString = [[NSString alloc] initWithData:decryptedData encoding:NSUTF8StringEncoding];
NSLog(#"Decrypted: %#", decryptedString);
return decryptedString;
}
When I use a string like hello world it works fine. When I use a string like {"username":"developer","password":"abcdefG*12"} I imagine it hase something to do with the encoding but I really know what to use.
when I encrypt that string I get a base64 string and when I try to decrypt that I get an empty string.
UPDATE
It looks like it's failing because of the : in the json string.
What's weirder is it only fails with the string is in json format, I thought it was the : cause I tried that first but upon further investigation if I broke any of the JSON requirements ,'s {'s }'s it stopped working. It works with the RNEncryptor however so I'm not sure what I'm doing wrong. Either way, I think we may redesign the current flow
UPDATE 2
Here is where I am calling these methods:
NSDictionary *credentials = #{#"username":#"developer",#"password":#"abcdefG*12"};
NSString *jsonString = [ credentials JSONStringWithOptions:JKSerializeOptionNone error:&error];
NSLog(#"json string: %#", jsonString); //OUTPUTS: {"username":"developer","password":"abcdefG*12"}
CCGEncryption *encryptionObject = [[CCGEncryption alloc] init]; //THIS IS THE OBJECT WHERE THE encrypt/decrypt methods are
NSString *encrypted = [encryptionObject encryptString:jsonString withKey:ENCRYPTION_KEY error:&error];
if(error){
NSLog(#"Error:%#", error); //NO ERROR
}
NSString *decrypted = [encryptionObject decryptString:encrypted withKey:ENCRYPTION_KEY error:&error];
if(error){
NSLog(#"Error:%#", error); //NO ERROR
}
NSLog(#"decrypted: %#", decrypted); //OUTPUT: decrypted:
You're not collecting the data returned by addData:. The engine encrypts/decrypts as you go so that you don't have to hold the entire plaintext and ciphertext in memory. It doesn't accumulate the data unless it has to (for padding reasons). I suspect that the tests that are working are of different lengths than the ones that aren't.
You are correct that using a fixed IV is bad practice. If you use the same IV and key in multiple messages, then it is possible for attackers to recover parts of your messages by comparing the ciphertexts. If you are using AES-CBC without a random IV and an HMAC, then your AES is insecure in several ways. That is the problem RNCryptor was built to address and why the data format looks the way it does.
#jbtule is correct that I didn't particularly mean for people to use the engine directly and haven't heavily documented it, but there's no problem using it, and I can document it better to support that. That said, the engine itself is insanely simple; I just created it as a way to share code between the encryptor and decryptor. There's not much reason to use RNCryptor if you're going to bypass most of the security it provides. For the above code, it'd be a lot simpler to just call the one-shot CCCrypt().

Resources