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.
Related
// 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.)
In My App, i'm getting data from xml, where it is encrypted, and i need to decrypt the received nsstring,
UserName = #"QEjbHvzPjk+YuLDVPUJuEA==";
I Need to decrypt this nsstring into regular format, i searched and find aes , but it doesn't make any changes,
NSString* msg = [FBEncryptorAES decryptBase64String:UserName
keyString:#"01234567890abcdefghijklmnopqrstuvwxyz"];
if (msg)
{
UserName = msg;
NSLog(#"decrypted: %#", msg);
} else
{
UserName = #"(failed to decrypt)";
}
How can i decrypt the above nsstring, Thanks in Advance.
The string is not only AES encrypted, it is Base64 encoded. The trailing "==" is typical of base64 padding. Also AES encryption produces data bytes, not ASCII characters and the output is a multiple of the block size. It is common to Base64 encode the result of encryption so it is ASCII and can be included in XML.
For iOS 7 there are several Base64 API methods for NSData. Probably what you want is:
- (id)initWithBase64EncodedString:(NSString *)base64String options:(NSDataBase64DecodingOptions)options
Example:
NSString *userName = #"QEjbHvzPjk+YuLDVPUJuEA==";
NSData *data = [[NSData alloc] initWithBase64EncodedString:userName options:0];
NSLog(#"data: %#", data);
NSLog output:
data: <4048db1e fccf8e4f 98b8b0d5 3d426e10>
The data probably is AES encrypted, it is a multiple of block length, and if so you will need the key and also information on padding, mode and possibly iv.
Note that the FBEncryptorAES class method encryptedBase64String does accept Base64 input but the decryption key string is suspect and the encryption may not match this decryption method due to method and possible iv. So the FBEncryptorAES class may not be what you need.
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.
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];
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.