How do I do base64 encoding on iOS? How do I do base64 encoding on iOS? ios ios

How do I do base64 encoding on iOS?


This is a good use case for Objective C categories.

For Base64 encoding:

#import <Foundation/NSString.h>@interface NSString (NSStringAdditions)+ (NSString *) base64StringFromData:(NSData *)data length:(int)length;@end-------------------------------------------#import "NSStringAdditions.h"static char base64EncodingTable[64] = {  'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',  'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',  'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',  'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};@implementation NSString (NSStringAdditions)+ (NSString *) base64StringFromData: (NSData *)data length: (int)length {  unsigned long ixtext, lentext;  long ctremaining;  unsigned char input[3], output[4];  short i, charsonline = 0, ctcopy;  const unsigned char *raw;  NSMutableString *result;  lentext = [data length];   if (lentext < 1)    return @"";  result = [NSMutableString stringWithCapacity: lentext];  raw = [data bytes];  ixtext = 0;   while (true) {    ctremaining = lentext - ixtext;    if (ctremaining <= 0)        break;            for (i = 0; i < 3; i++) {        unsigned long ix = ixtext + i;       if (ix < lentext)          input[i] = raw[ix];       else  input[i] = 0;  }  output[0] = (input[0] & 0xFC) >> 2;  output[1] = ((input[0] & 0x03) << 4) | ((input[1] & 0xF0) >> 4);  output[2] = ((input[1] & 0x0F) << 2) | ((input[2] & 0xC0) >> 6);  output[3] = input[2] & 0x3F;  ctcopy = 4;  switch (ctremaining) {    case 1:       ctcopy = 2;       break;    case 2:       ctcopy = 3;       break;  }  for (i = 0; i < ctcopy; i++)     [result appendString: [NSString stringWithFormat: @"%c", base64EncodingTable[output[i]]]];  for (i = ctcopy; i < 4; i++)     [result appendString: @"="];  ixtext += 3;  charsonline += 4;  if ((length > 0) && (charsonline >= length))    charsonline = 0;  }       return result;}@end

For Base64 decoding:

#import <Foundation/Foundation.h>@class NSString;@interface NSData (NSDataAdditions)+ (NSData *) base64DataFromString:(NSString *)string;@end-------------------------------------------#import "NSDataAdditions.h"@implementation NSData (NSDataAdditions)+ (NSData *)base64DataFromString: (NSString *)string{    unsigned long ixtext, lentext;    unsigned char ch, inbuf[4], outbuf[3];    short i, ixinbuf;    Boolean flignore, flendtext = false;    const unsigned char *tempcstring;    NSMutableData *theData;    if (string == nil)    {        return [NSData data];    }    ixtext = 0;    tempcstring = (const unsigned char *)[string UTF8String];    lentext = [string length];    theData = [NSMutableData dataWithCapacity: lentext];    ixinbuf = 0;    while (true)    {        if (ixtext >= lentext)        {            break;        }        ch = tempcstring [ixtext++];        flignore = false;        if ((ch >= 'A') && (ch <= 'Z'))        {            ch = ch - 'A';        }        else if ((ch >= 'a') && (ch <= 'z'))        {            ch = ch - 'a' + 26;        }        else if ((ch >= '0') && (ch <= '9'))        {            ch = ch - '0' + 52;        }        else if (ch == '+')        {            ch = 62;        }        else if (ch == '=')        {            flendtext = true;        }        else if (ch == '/')        {            ch = 63;        }        else        {            flignore = true;         }        if (!flignore)        {            short ctcharsinbuf = 3;            Boolean flbreak = false;            if (flendtext)            {                if (ixinbuf == 0)                {                    break;                }                if ((ixinbuf == 1) || (ixinbuf == 2))                {                    ctcharsinbuf = 1;                }                else                {                    ctcharsinbuf = 2;                }                ixinbuf = 3;                flbreak = true;            }            inbuf [ixinbuf++] = ch;            if (ixinbuf == 4)            {                ixinbuf = 0;                outbuf[0] = (inbuf[0] << 2) | ((inbuf[1] & 0x30) >> 4);                outbuf[1] = ((inbuf[1] & 0x0F) << 4) | ((inbuf[2] & 0x3C) >> 2);                outbuf[2] = ((inbuf[2] & 0x03) << 6) | (inbuf[3] & 0x3F);                for (i = 0; i < ctcharsinbuf; i++)                {                    [theData appendBytes: &outbuf[i] length: 1];                }            }            if (flbreak)            {                break;            }        }    }    return theData;}    @end


A really, really fast implementation which was ported (and modified/improved) from the PHP Core library into native Objective-C code is available in the QSStrings Class from the QSUtilities Library. I did a quick benchmark: a 5.3MB image (JPEG) file took < 50ms to encode, and about 140ms to decode.

The code for the entire library (including the Base64 Methods) are available on GitHub.

Or alternatively, if you want the code to just the Base64 methods themselves, I've posted it here:

First, you need the mapping tables:

static const char _base64EncodingTable[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";static const short _base64DecodingTable[256] = {    -2, -2, -2, -2, -2, -2, -2, -2, -2, -1, -1, -2, -1, -1, -2, -2,    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,    -1, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, 62, -2, -2, -2, 63,    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -2, -2, -2, -2, -2, -2,    -2,  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, -2, -2, -2, -2, -2,    -2, 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, -2, -2, -2, -2, -2,    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2};

To Encode:

+ (NSString *)encodeBase64WithString:(NSString *)strData {    return [QSStrings encodeBase64WithData:[strData dataUsingEncoding:NSUTF8StringEncoding]];}+ (NSString *)encodeBase64WithData:(NSData *)objData {    const unsigned char * objRawData = [objData bytes];    char * objPointer;    char * strResult;    // Get the Raw Data length and ensure we actually have data    int intLength = [objData length];    if (intLength == 0) return nil;    // Setup the String-based Result placeholder and pointer within that placeholder    strResult = (char *)calloc((((intLength + 2) / 3) * 4) + 1, sizeof(char));    objPointer = strResult;    // Iterate through everything    while (intLength > 2) { // keep going until we have less than 24 bits        *objPointer++ = _base64EncodingTable[objRawData[0] >> 2];        *objPointer++ = _base64EncodingTable[((objRawData[0] & 0x03) << 4) + (objRawData[1] >> 4)];        *objPointer++ = _base64EncodingTable[((objRawData[1] & 0x0f) << 2) + (objRawData[2] >> 6)];        *objPointer++ = _base64EncodingTable[objRawData[2] & 0x3f];        // we just handled 3 octets (24 bits) of data        objRawData += 3;        intLength -= 3;     }    // now deal with the tail end of things    if (intLength != 0) {        *objPointer++ = _base64EncodingTable[objRawData[0] >> 2];        if (intLength > 1) {            *objPointer++ = _base64EncodingTable[((objRawData[0] & 0x03) << 4) + (objRawData[1] >> 4)];            *objPointer++ = _base64EncodingTable[(objRawData[1] & 0x0f) << 2];            *objPointer++ = '=';        } else {            *objPointer++ = _base64EncodingTable[(objRawData[0] & 0x03) << 4];            *objPointer++ = '=';            *objPointer++ = '=';        }    }    // Terminate the string-based result    *objPointer = '\0';    // Create result NSString object    NSString *base64String = [NSString stringWithCString:strResult encoding:NSASCIIStringEncoding];    // Free memory    free(strResult);    return base64String;}

To Decode:

+ (NSData *)decodeBase64WithString:(NSString *)strBase64 {    const char *objPointer = [strBase64 cStringUsingEncoding:NSASCIIStringEncoding];    size_t intLength = strlen(objPointer);    int intCurrent;    int i = 0, j = 0, k;    unsigned char *objResult = calloc(intLength, sizeof(unsigned char));    // Run through the whole string, converting as we go    while ( ((intCurrent = *objPointer++) != '\0') && (intLength-- > 0) ) {        if (intCurrent == '=') {            if (*objPointer != '=' && ((i % 4) == 1)) {// || (intLength > 0)) {                // the padding character is invalid at this point -- so this entire string is invalid                free(objResult);                return nil;            }            continue;        }        intCurrent = _base64DecodingTable[intCurrent];        if (intCurrent == -1) {            // we're at a whitespace -- simply skip over            continue;        } else if (intCurrent == -2) {            // we're at an invalid character            free(objResult);            return nil;        }        switch (i % 4) {            case 0:                objResult[j] = intCurrent << 2;                break;            case 1:                objResult[j++] |= intCurrent >> 4;                objResult[j] = (intCurrent & 0x0f) << 4;                break;            case 2:                objResult[j++] |= intCurrent >>2;                objResult[j] = (intCurrent & 0x03) << 6;                break;            case 3:                objResult[j++] |= intCurrent;                break;        }        i++;    }    // mop things up if we ended on a boundary    k = j;    if (intCurrent == '=') {        switch (i % 4) {            case 1:                // Invalid state                free(objResult);                return nil;            case 2:                k++;                // flow through            case 3:                objResult[k] = 0;        }    }    // Cleanup and setup the return NSData    NSData * objData = [[[NSData alloc] initWithBytes:objResult length:j] autorelease];    free(objResult);    return objData;}


At the time this question was originally posted, people were understandably directing you to third-party base 64 libraries because of the lack of any native routines. But iOS 7 introduced base 64 encoding routines (which actually simply just exposes private methods iOS had going back to iOS 4).

So, you can use the NSData method base64EncodedStringWithOptions: to create a base-64 string from a NSData.

NSString *string = [data base64EncodedStringWithOptions:kNilOptions];

And you can use initWithBase64EncodedString:options: to convert a base-64 string back to a NSData:

NSData *data = [[NSData alloc] initWithBase64EncodedString:string options:kNilOptions]; 

Or, in Swift:

let string = data.base64EncodedString()

And

let data = Data(base64Encoded: string)