1

So I'm trying to decode a base64 encoded string but I'm not having any luck.. decodedString is always null! I've tried for hours and totally out of ideas. Even tried third party libraries.

Code:

NSString *input = @"H4sIAAAAAAAEALWSTW/TQBCG/0q15wTN7Je9voU2RFFUFCnuASGE9mMcTB0n9QcSQvx3xm6QWsSFAzev53l3Zp9dcb8+HFab9fZOFGJ/3Ny+bbvdrt+MX56ePp9OeDyKhSi3TJWr+z0zEtAtQS1RligLowowbxSAzqWdyA/7NUMP+7tVueb12FPXi5vi5uOP+XubuJoHkpjQOghBW5c5Dzpo0sZj8FYaztVtP6MSeHG+XIMKpJQEQQcgnSobrHVRxco6qY2WcgoOdHq4NkKzENV7fyKOrnx3brneXNeHoavjY+PbxD+jb6hNfg7BQlCqh7Kesb+eNkfjZM65R/o+zxUpwxAzTyoinyL5hLnPJBkbK6h8YPTSnb9SHGbcGcgQfJDBWY0qhop5ixoJdRYUMZ6oedf44zzO5G1ftxxEqbSx4uenufVvr/9vile3MJndPbeaxPaD715YskswS4WlxAKhgCnASv+wKPMSTYHuuf7NN3XyA92ex3bgTdU/mB8vU/Iw+GHsOfpa2MvrFEGBTSEjrPiRVImCT8T7qJSMs5VJbPMX5JgDcAQDAAA=";

NSData *decodedData = [[NSData alloc] initWithBase64EncodedString:input options:0];
NSString *decodedString = [[NSString alloc] initWithData:decodedData encoding:NSUTF8StringEncoding];
NSLog(@"Decode String Value: %@", decodedString);
Cinder Biscuits
  • 4,880
  • 31
  • 51
astric mobiles
  • 468
  • 3
  • 14
  • 3
    Did you check `decodedData` ? Most probably, it is not a valid UTF-8 sequence. – Martin R Mar 12 '19 at 13:02
  • 2
    `decodedData` is not nil (I tested it). But the question, is what is it supposed to represent? The start being `<1f8b08`, it let me think that's a GZip file. So you need to unzip it first. And then, if it's supposed to be a valid String, you can find it. – Larme Mar 12 '19 at 13:06
  • 2
    The decoded data is `<1f8b0800 00000000 0400b592 ... e4980370 04030000>`. What does that represent? What string result do you expect? – Martin R Mar 12 '19 at 13:06
  • So I expect to be a compressed string that will decompress with gzip. But I'm struggling to decode the base64 – astric mobiles Mar 12 '19 at 13:08
  • 1
    Here for a third party that can help you and which has a method that seems to supports the idea it's a GZip: https://github.com/nicklockwood/GZIP/blob/abe8958353972c77b79f0fd1adafb94d52d4096d/GZIP/NSData%2BGZIP.m#L130 – Larme Mar 12 '19 at 13:08
  • 1
    @astricmobiles You can't decode it to a string because it's binary data. – Cinder Biscuits Mar 12 '19 at 13:09
  • So, @Larme, do I need to decompress first, then decode? – astric mobiles Mar 12 '19 at 13:09
  • @astricmobiles: The problem is *not* the Base64 decoding, the `initWithBase64EncodedString` step *succeeds.* – Martin R Mar 12 '19 at 13:10
  • You don't understand: Base64 is a way to represent HexData (could be an image, etc.) into a String (and vice-versa) using a certain algorithm, and with "basic characters" (no no issue about encoding). GZip is a compression of HexData. We can have a representation of a String into HexData according to the encoding (and encoding usually doesn't manage all the hex values, there are combination that produce invalid characters) we want. You need to decompose each step and understand them. – Larme Mar 12 '19 at 13:13
  • ok @Larme, So I think I get it... I need to decompress the string which will output HexData. and then I can decode the HexData? Have I understood that correctly? – astric mobiles Mar 12 '19 at 13:16

2 Answers2

4

The Base64 decoded output is not a string, it is binary data.

You are getting nil returned because it is not a UTF-8 string and arbitrary data is generally not valid UTF-8.

Decode using NSDataBase64DecodingIgnoreUnknownCharacters to avoid the decoder discarding non-Base-64 bytes.

NSData *decodedData = [[NSData alloc]initWithBase64EncodedString:input
                       options:NSDataBase64DecodingIgnoreUnknownCharacters];

Once you have decodedData, you can decompress the buffer with whatever function or library you decide on, then you can read the string. You may want to look at the answer here for an idea of how to decompress your data.

Cinder Biscuits
  • 4,880
  • 31
  • 51
2

decodedData is not nil. It's value is: <1f8b0800 ...

1f8b let me think it's a GZip.

Any hex data is not convertible as such into a String using UTF8 Encoding. UTF8 doesn't have value for each possible hex. There are non-valid combination, and so your final string is nil. For instance, transform an UIImage into PNG HexData (using UIImagePNGRepresentation()) and try it to convert it into a NSString using NSUTF8StringEncoding. You'll see.

Using the code of https://github.com/nicklockwood/GZIP/ (first one I found):

NSData *unzippedData = [decodedData gunzippedData];
NSString *decodedString = [[NSString alloc] initWithData:unzippedData encoding:NSUTF8StringEncoding];

Output:

"MESSAGEID":"PgGCBnrKKsGuhqq_mm1gg","TIMESTAMP":"2019-03-12T12:53:05.3004826","TYPE":"UPDATE","users" : [{"userId":"8be21d1690bb46979a04b4e45a1ba625","insId":"20","operId":"30222e0b4b0e4df6b669c3cf69245422","itemUserId":15,"fName":"Aaron","lName":"Strickland","calendarId":0,"editTime":"2019-03-12T12:53:05.3815928","keyId":"ce71bc7ae3c145adad18a72e56cf0fab","projectId":"950710ab2b96413cbfd186141e147b3e","delFlag":0,"userPin":"123456"}],"keys" : [{"keyId":"ce71bc7ae3c145adad18a72e56cf0fab","projectId":"950710ab2b96413cbfd186141e147b3e","insId":"20","itemKeyId":15,"startTime":"2016-05-31T21:10:00","endTime":"2019-03-28T15:19:00","validateCount":13,"editTime":"2019-03-12T12:53:05.3815928","updateStatus":1,"delFlag":0,"calendarId":"b306db7e1f924fdebade3813dd596f5d"}]

Seems almost like JSON. I would have add "{" and "}" around it.

With a little of workaround:

NSMutableData *finalData = [[NSMutableData alloc] initWithData:[@"{" dataUsingEncoding:NSUTF8StringEncoding]];
[finalData appendData:unzippedData];
[finalData appendData:[@"}" dataUsingEncoding:NSUTF8StringEncoding]];
NSData *dictionary = [NSJSONSerialization JSONObjectWithData:finalData options:0 error:nil];
NSLog(@"dictionary: %@", dictionary);

It's up to you to know why the syntax is strange, but with that you a "usable" NSDictionary.

Larme
  • 24,190
  • 6
  • 51
  • 81