initWithBase64EncodedString return nil - objective-c

My resultString is 'PHNhbWxwOlJlc3BvbnNlIH...c3BvbnNlPgoK' and when i am decoding it shows me decodedData as nil.
NSData *decodedData = [[NSData alloc] initWithBase64EncodedString:resultString options:0];
I also tried this string with https://www.base64decode.org/ ,
it successfully shows results.
What wrong here in decoding ?

Probably you have some invalid characters in your string, like padding new lines. Try to pass NSDataBase64DecodingIgnoreUnknownCharacters option instead of 0.
NSData *decodedData = [[NSData alloc] initWithBase64EncodedString:resultString options:NSDataBase64DecodingIgnoreUnknownCharacters];

Almost certainly your string is not valid Base64, but that it is "close enough" that base64decode.org accepts it. The most likely cause is that you've dropped a trailing =. base64decode.org is tolerant of that, and just quietly throws away what it can't decode (the last byte in that case). NSData is not tolerant of that, because it's not valid Base64.
base64decode.org is also tolerant of random non-base64 characters in the string and just throws them away. NSData is not (again, sine it's invalid).

Try this! Simple solution :) Must need Foundation.framework. By default initWithBase64EncodedString method returns nil when the input is not recognized as valid Base-64. Please check your string is a valid Base-64 type or not!
NSData *decodedData = [[NSData alloc] initWithBase64EncodedString:#"eyJuYW1lIjoidmlnbmVzaCJ9" options:0];
NSError *dataError;
NSDictionary* responseObject = [NSJSONSerialization JSONObjectWithData:decodedData
options:kNilOptions
error:&dataError];
if(dataError == nil) {
NSLog(#"Result %#",responseObject);
}

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.)

JSON data has "bad" characters that causes NSJSONSerialization to die

I am using the ATV version of TVH Client - if you haven't looked at this it's worth looking at TVH to glimpse madness in the face. It has a JSON API that sends back data, including the electronic program guide. Sometimes the channels put accented characters in their data. Here is an example, this is the result from Postman, note the ? char in the description:
{
"eventId": 14277,
"episodeId": 14278,
"channelName": "49.3 CometTV",
"channelUuid": "02fe96403d58d53d71fde60649bf2b9a",
"channelNumber": "49.3",
"start": 1480266000,
"stop": 1480273200,
"title": "The Brain That Wouldn't Die",
"description": "Dr. Bill Cortner and his fianc�e, Jan Compton , are driving to his lab when they get into a horrible car accident. Compton is decapitated. But Cortner is not fazed by this seemingly insurmountable hurdle. His expertise is in transplants, and he is excited to perform the first head transplant. Keeping Compton's head alive in his lab, Cortner plans the groundbreaking yet unorthodox surgery. First, however, he needs a body."
},
If this data is fed into NSJSONSerialization, it returns an error. So to avoid this, the data is first fed into this function:
+ (NSDictionary*)convertFromJsonToObjectFixUtf8:(NSData*)responseData error:(__autoreleasing NSError**)error {
NSMutableData *FileData = [NSMutableData dataWithLength:[responseData length]];
for (int i = 0; i < [responseData length]; ++i) {
char *a = &((char*)[responseData bytes])[i];
if ( (int)*a >0 && (int)*a < 0x20 ) {
((char*)[FileData mutableBytes])[i] = 0x20;
} else {
((char*)[FileData mutableBytes])[i] = ((char*)[responseData bytes])[i];
}
}
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:FileData //1
options:kNilOptions
error:error];
if( *error ) {
NSLog(#"[JSON Error (2nd)] output - %#", [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding]);
NSDictionary *userInfo = #{ NSLocalizedDescriptionKey:[NSString stringWithFormat:NSLocalizedString(#"Tvheadend returned malformed JSON - check your Tvheadend's Character Set for each mux and choose the correct one!", nil)] };
*error = [[NSError alloc] initWithDomain:#"Not ready" code:NSURLErrorBadServerResponse userInfo:userInfo];
return nil;
}
return json;
}
This cleans up the case when there is a control character in the data, but not an accent like the case above. When I feed in that data I get the "Tvheadend returned malformed JSON" error.
One problem is that the user can change the character set among a limited number of selections, and the server does not tell the client what it is. So one channel might use UTF8 and another ISO-8891-1, and there is no way to know which to use on the client side.
So: can anyone offer a suggestion on how to process this data so we feed clean strings into NSJSONSerialization?
I still do not know the root cause of the problem I am seeing - the server is sending not only high-bit characters like the ones I noted above, but I also found that it contained control characters too! Looking over other threads it appears I am not the only one seeing this problem, so hopefully others will find this useful...
The basic trick is to convert the original data from the server to a string using UTF8. If there are any of these "bad" chars in it, the conversion will fail. So you check if the resulting string is empty, and try another charset. Eventually you'll get data back. Now you take that string and strip out any control chars. Now you take that result, which is now UTF8 "clean", and convert it back to UTF8 NSData. That will pass through the JSON conversion without error. Phew!
Here is the solution I finally used:
// ... the original data from the URL is in responseData
NSString *str = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
if ( str == nil ) {
str = [[NSString alloc] initWithData:responseData encoding:NSISOLatin1StringEncoding];
}
if ( str == nil ) {
str = [[NSString alloc] initWithData:responseData encoding:NSASCIIStringEncoding];
}
NSCharacterSet *controls = [NSCharacterSet controlCharacterSet];
NSString *stripped = [[str componentsSeparatedByCharactersInSet:controls] componentsJoinedByString:#""];
NSData *data = [stripped dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
I hope someone finds this useful!

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.

Try to create NSString from bytes. It always returns an empty string

I am trying to create a string from bytes a received via network. The NSString I het is always an empty one.
if (stringLength > 0) {
NSData *bytes = [[NSData alloc] initWithBytes:data+1 length:stringLength];
result = [[NSString alloc] initWithData:bytes encoding:NSUTF8StringEncoding];
//result = [[NSString alloc] initWithBytes:data+1 length:stringLength encoding:NSASCIIStringEncoding];
}
As I said I get an empty NSString. The string is a base64 encoded value so it should be valid utf-8 since it only contains ascii symbols.
Maybe your raw bytes aren't UTF-8 after all. Or maybe, because you're passing data+1 instead of data itself, you're causing the encoding attempt to fail because the process thinks there's an improper UTF-8 encoding sequence. (Forgive me if I'm being presumptuous, but you have to take everything into account.) In any case, you're relying heavily on your assumption, and that's a trap we all fall into now and then.
Here's a strategy for you. If your attempt at creating an NSString instance using NSUTF8StringEncoding returns nil, then try using NSISOLatin1StringEncoding. And if that returns nil, then try using NSMacOSRomanStringEncoding.
Even if, after all of that, you get a string that's not quite right, it's still better than a nil string in that it could help to show you if there's some other area in which you've made a mistake.
Good luck to you in your endeavors.
Check if it's really base64 encoded..
CFErrorRef error = NULL;
CFDataRef decodedData;
SecTransformRef decoder;
decoder = SecDecodeTransformCreate(kSecBase64Encoding, &error);
if (error) {
CFShow(error);
exit(-1);
}
SecTransformSetAttribute(decoder,
kSecTransformInputAttributeName,
(CFDataRef *)bytes,
&error);
if (error) {
CFShow(error);
exit(-1);
}
decodedData = SecTransformExecute(decoder, &error);
if (error) {
CFShow(error);
exit(-1);
}

carriage return for encoding

Im trying to send ascii encoded message to a server. My problem is coming in when I try to append the carriage return to the string
-(void)button2Pressed
{
NSMutableString *mutableString = [NSMutableString stringWithString:#"h323name get"];
[self sendStringCommand:mutableString];
}
-(void)sendStringCommand:(NSMutableString*)string
{
[string appendString:#"\\r"];
NSLog(#"string %# wtf",[string dataUsingEncoding:NSASCIIStringEncoding]);
NSData * testData = [[NSData alloc]initWithBytes:[string dataUsingEncoding:NSASCIIStringEncoding] length:sizeof([string dataUsingEncoding:NSASCIIStringEncoding])];
[socket writeData:testData withTimeout:20 tag:1];
}
currently this outputs this:
string <68333233 6e616d65 20676574 5c72> wtf
which should be
string <68333233 6e616d65 20676574 0d> wtf
Just plain /r did a new line hence the wtf characters after the data in the nslog
You have too many backslashes. Try this:
[string appendString:#"\r"];
Also, your creation of testData is completely wrong. The way you are creating testData is passing a pointer to an NSData object as the "bytes" parameter, and passing the size of a pointer to an NSData as the "length" parameter. You should just do this:
NSData *testData = [string dataUsingEncoding:NSASCIIStringEncoding];