Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

URL Safe Base64 in Objective-C

I've looked at numerous Stack Overflow posts on how to decode Base64 encoded strings in Objective C, but I'm still having issues with it.

Essentially, I'm trying to port a Python script to Objective C. The Python line of code is:

zlib.decompress(base64.urlsafe_b64decode(string))

When I run "string" through the Python version of base64.urlsafe_b64decode, it turns out correctly and can then be properly Zlib-decompressed. When I run the "string" through any variant of an Objective C Base64 decoder, it sort of works, but the results are not the same and the Zlib decompression fails.

Is there a difference between URL-safe Base 64 decoding and the code that's widely available here on SO? If anyone has experienced difficulties like this before, any insight on what to do is appreciated.

Thanks, SO!

Edit 1: I used the Base 64 code found here. The original data (still Base64 encoded) can be found here, the Objective-C generated can be found here, and the Python generated can be found here. Ideally, I want the Objective C code to decode to the same text as the Python script.

like image 587
Jake Wood Avatar asked Jun 19 '12 17:06

Jake Wood


2 Answers

Special thanks to Graham for pointing out the RFC differences, I was able to solve the problem. If anyone in the future encounters this, here's how to solve it:

  1. Download the NSData+Base64 code from here.
  2. In NSData+Base64.m, you'll need to change the look-up tables to the following:
//
// Mapping from 6 bit pattern to ASCII character.
//
static unsigned char base64EncodeLookup[65] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";

//
// Definition for "masked-out" areas of the base64DecodeLookup mapping
//
#define xx 65

//
// Mapping from ASCII character to 6 bit pattern.
//
static unsigned char base64DecodeLookup[256] =
{
    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 
    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 
    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 62, xx, xx, 
    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, xx, xx, xx, xx, xx, xx, 
    xx,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 
    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, xx, xx, xx, xx, 63, 
    xx, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 
    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, xx, xx, xx, xx, xx, 
    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 
    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 
    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 
    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 
    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 
    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 
    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 
    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 
};

This will make Objective C's decoding equivalent to Python's.

like image 110
Jake Wood Avatar answered Oct 03 '22 15:10

Jake Wood


iOS 7.0 and later has the method "base64EncodedStringWithOptions" on NSData that will do the above lookup. But this method does not return a URL safe encoded string. So one would have to do the replacements manually to get a URL safe encoded string. See below..

NSData *originalData = [originalString dataUsingEncoding:NSUTF8StringEncoding];
NSString *base64String = [originalData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
base64String = [base64String stringByReplacingOccurrencesOfString:@"/" withString:@"_"];
base64String = [base64String stringByReplacingOccurrencesOfString:@"+" withString:@"-"];

The resultant base64String is now URL safe.

like image 20
Kris Subramanian Avatar answered Oct 03 '22 14:10

Kris Subramanian