Objective C: AES 256 Encryption with NSData Keyvalue - objective-c

I want to do AES 256 encryption with a NSDATA Key. But everywhere I am finding example with NSString key. Now, how to use NSData key ?

You cannot use bytes as key. You have to use a string as key. Although, you can convert NSData bytes into a string. But note that the data has to be encoding with some valid string encoding.
Then you can use the following method to convert your NSData to a string , to use as a key.
NSString* newStr = [[[NSString alloc] initWithData:theData
encoding:NSUTF8StringEncoding] autorelease];

Related

AES256 CBC encryption/decryption in objective C. Getting null value in decryption. I am already having the encrypted value with me

// Code to decrypt value
{
NSString *dataString = #"8T79ubuRfEwpfSOO1yr3Q+nbsla4J7VqFCe4THnPOGxjk37+2QgdLUgq5yWqLtx+";
NSString *base64Key = #"82a645babc6vd41c9a2cb4d0d3ba17ad";
NSString *base64KeyIv = #"acf30ad62b693849";
NSData *key = [[NSData alloc] initWithBase64EncodedString:base64Key options:0];
NSData *keyiv = [[NSData alloc] initWithBase64EncodedString:base64KeyIv options:0];
NSData *data = [[NSData alloc] initWithBase64EncodedString:dataString options:0];
NSData *encryptedData = [ViewController crypt:data
iv:keyiv
key:key
context:kCCDecrypt];
NSString *decryptText = [[NSString alloc] initWithData:encryptedData
encoding:NSUTF8StringEncoding];
NSLog(#"Decrypted Result: %#", decryptText); //here getting NULL
}
I am getting null value while decryption.Please help me where I am wrong. AES256 CBC encryption/decryption in objective C. Getting null value in decryption. I am already having the encrypted value with me.
There are likely several errors here, and it's unclear what your -crypt:iv:key:context: method does. Do you know for certain that your encryption system exactly matches your -crypt:iv:key:context: method?
At a start, you're getting nil because the output isn't UTF-8 (because it's almost certainly corrupted due to passing the wrong key and IV).
Next, your crypt method should be generating errors because what you're passing is invalid, so you need to check those errors. They would likely tell you what's wrong.
At a minimum, you are decoding the key and IV incorrectly. If they're in Base64, they're the wrong length. They look like they're just UTF-8/ASCII encoded (which is a security issue, but your system may just be insecure). In Base64, this key is 24 bytes, while in ASCII it's 32 bytes (which is the correct key length).
If that's the only problem, then the fix would be:
NSData *key = [base64Key dataUsingEncoding:NSUTF8StringEncoding];
NSData *keyiv = [base64KeyIv dataUsingEncoding:NSUTF8StringEncoding];
(Ideally you'd rename the "base64..." identifier since these aren't Base64 encoded. dataString does appear to be Base64 encoded.)

Objective-C Base64 decoding returns nil

I have downloaded and added the following category into my project: https://github.com/nicklockwood/Base64
NSString *secret = #"7pgj8Dm6";
NSString *decodedSecret = [secret base64DecodedString];
NSLog(#"decoded Secret = %#", decodedSecret);
This however, always turns out to be nil. What is happening here ?
I hope it will helpful to you
NSString *decodeString = #"Raja";
Encode String
NSData *encodeData = [decodeString dataUsingEncoding:NSUTF8StringEncoding];
NSString *base64String = [encodeData base64EncodedStringWithOptions:0];
DLog(#"Encode String Value: %#", base64String);
Decode String
NSData *decodedData = [[NSData alloc] initWithBase64EncodedString:base64String options:0];
NSString *decodedString = [[NSString alloc] initWithData:decodedData encoding:NSUTF8StringEncoding];
DLog(#"Decode String Value: %#", base64String);
Thanks
I've failed to relax iOS native base64 decoder enough with NSDataBase64DecodingIgnoreUnknownCharacters to process jwt payloads
so I had to revert to a 3rdparty MF_Base64Codec
Sadly you might want to consider doing the 3rdparty route
until Apple will have fixed the bug or relaxed the decoder further to
accept what it currently considers crap input
Your input 7pgj8Dm6is an Invalid base64 encoded string. So the result will be always nil since the method base64DecodedString used only for UTF8 encoding.
As of iOS 7 and Mac OS 10.9, this library is not longer needed.
You can use initWithBase64EncodedString:options:
The default implementation of this method will reject non-alphabet characters, including line break characters. To support different encodings and ignore non-alphabet characters, specify an options value of NSDataBase64DecodingIgnoreUnknownCharacters.

Objective C: AES 256 Encryption with NSData Key

Previously I did Triple DES encryption to encrypt some data using a string key file, by defining a method
+ (NSData *)tripleDESEncryptWithKey:(NSString *)key dataToEncrypt:(NSData*)convertedData {}.
Now, similarly I am doing AES 256 encryption. But this time, I can not use a string as the key. I need to get NSData from a file in resources using
NSData *keyData = [NSData dataWithContentsOfFile:keyPath];
As I need to pass this key as parameter, I tried to convert it into string with
NSString *key = [[NSString alloc] initWithData:keyData encoding:NSUTF8StringEncoding];
but it returned NULL. So, How to use the Data key for AES 256 encryption ?
EDIT: I got that I should not use UTF8 encoding as the data file was made by Base64 encoding of a string. So Now the question is, how to get the string key using Base64 from keyData ?
If key variable returned NULL. Try to use like this.
NSString* key = [NSString stringWithUTF8String:[keyData bytes]];
Refer to KennyTM's Answer
UPDATE 1: You can also read the string directly from your file without convert in NSData
By NSFileHandle:
NSString * path = #"your key file path";
NSFileHandle * fileHandle = [NSFileHandle fileHandleForReadingAtPath:path];
NSData * buffer = nil;
while ((buffer = [fileHandle readDataOfLength:1024])) {
//do something with buffer
}
or use NSString
NSString * key = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
Refer to Dave DeLong's Answer
Note: Ensure your keyPath variable , Is it correct in the format of full or relative path?
UPDATE 2: You can also deal with Base64 Encoding with Matt Gallagher NSData+Base64 Class&Header (See also his blog there)
For encode base64
NSString * key = [[path dataUsingEncoding:NSUTF8StringEncoding] base64EncodedString];
Hope it helps you!
Read the file:
NSData* myData = [NSData dataWithContentsOfFile:myFileWithPath];
Then use one of the implementations in this post:
Base64 encoding options on the Mac and iPhone
to do your Base64 conversion.
Note: simply sticking your decryption key into a file is a bad idea. Optimally, the key would be stored securely by being encrypted by the user's own key.

encode a nsstring with utf-8Type for post connection

Trying to postdata in post connection using setHttpPost
NSString* strRequest = [NSString stringWithFormat:#"username=%#&password==%#&client_assertion_type=%#&client_assertion=%#&spEntityID=%#",
strUsrName,strPasswrd,#"JWT",strAppTknContent,#"http://localhost:8080/opensso"];
NSData* dataRequest = [NSData dataWithBytes:[strRequest UTF8String] length:[strRequest length]];
[theRequest setHTTPMethod: #"POST"];
[theRequest setHTTPBody: dataRequest];
want to encode the value for username,password,client_assertion_type alone utf-8 type
NSString* username = [ encode utf-8 type #"fff"];
how do i encode only the value of each key elements and post it
You cannot encode a string in UTF-8 and then put it in a NSString instance. NSString uses Unicode characters anyway but not in an encoded form.
Why would you want to encode them separately anyway? What exactly are you trying to achieve?
And just to point out a mistake in your code. The following line does not work once you have characters that require more than 1 byte in UTF-8:
NSData* dataRequest = [NSData dataWithBytes:[strRequest UTF8String] length:[strRequest length]];
The length parameter is expected to be the number of bytes but you are passing the number of characters.
A correct and simpler alternative is:
NSData* dataRequest = [strRequest dataUsingEncoding: NSUTF8StringEncoding ];
Update:
As you obviously want to properly URL encoded your parameters, you're probably looking for code like this:
NSString* strRequest = [NSString stringWithFormat:#"username=%#&password==%#&client_assertion_type=%#&client_assertion=%#&spEntityID=%#",
[strUsrName stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding],
[strPasswrd stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding],
#"JWT",
[strAppTknContent stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding],
[#"http://localhost:8080/opensso" stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]
];
NSData* dataRequest = [strRequest dataUsingEncoding: NSUTF8StringEncoding ];
Update 2:
It's a very strange design to transmit data that way. When it was first used, it probably was a hack to get something working quickly. Unfortunately, it became a standard.
Basically, you have two levels of encoding. The URL encoding to serves to put several key/value pairs into a single string such that the string can later be split again into the key/value pairs. It needs to know that a UTF-8 encoding is used on the second level so it can escape the problematic characters. It's does UTF-8 the string yet.
The second level translates the string (a sequence of characters) into a byte stream using the UTF-8 encoding since HTTP is specified as a transmission of bytes, not characters.

Sending hexadecimal data to devices (Converting NSString to hexadecimal data)

I'm trying to send hexadecimal data via WiFi.
The code is something like this:
NSString *abc = #"0x1b 0x50";
NSData *data = [[[NSData alloc] initWithData:[abc dataUsingEncoding:NSASCIIStringEncoding]]autorelease];
[outputStream write:[data bytes] maxLength:[data length]]];
Instead of sending the hexadecimal data, it's sending it in text format.
I tried with NSUTF8StringEncoding, but it's the same. I'm using it with the NSStream class.
You're not getting what you expect with NSString *abc = #"0x1b 0x50". It's almost the same as having NSString *abc = #"cat dog 123 0x0x0x"; just a bunch of words separated by spaces. So when you create your NSData object, you're just initializing it with a string of characters, not a series of actual numbers.
If you can get your numbers into an NSArray, this question/answer should help you: How to convert NSArray to NSData?
The data that you probably want to send is simply 0x1b50, which is the decimal number 6992 (assuming big-endian), and fits into two bytes. This is not the same as a string (which could contain anything) even if it happens to contain some human-readable representation of those numbers.
I'm assuming you want to send this as binary data, and if so one way would be to simply send a buffer formed by a single UInt16 instead of a string. I'm not very familiar with the relevant APIs, but look to see if you can populate the NSData with an integer, perhaps something like:
UInt16 i = 0x1b50; // Or = 6992
[[NSData alloc] initWithBytes: &i length: sizeof(i)]
[outputStream write: [data bytes] maxLength: [data length]]];
Again, I'm not fluent with Objective C, but this should be the general approach to sending the number 0x1b50 as binary data.