How to Base64 encoding on the iPhone

82,575

Solution 1

You can see an example here.

This is for iOS7+.

I copy the code here, just in case:

// Create NSData object
NSData *nsdata = [@"iOS Developer Tips encoded in Base64"
  dataUsingEncoding:NSUTF8StringEncoding];

// Get NSString from NSData object in Base64
NSString *base64Encoded = [nsdata base64EncodedStringWithOptions:0];

// Print the Base64 encoded string
NSLog(@"Encoded: %@", base64Encoded);

// Let's go the other way...

// NSData from the Base64 encoded str
NSData *nsdataFromBase64String = [[NSData alloc]
  initWithBase64EncodedString:base64Encoded options:0];

// Decoded NSString from the NSData
NSString *base64Decoded = [[NSString alloc] 
  initWithData:nsdataFromBase64String encoding:NSUTF8StringEncoding];
NSLog(@"Decoded: %@", base64Decoded);

Solution 2

Use this library to encode Base64.

It also supports ARC

Solution 3

I also had trouble finding working code for the iPhone that I could understand.

I finally wrote this.

-(NSString *)Base64Encode:(NSData *)data;

-(NSString *)Base64Encode:(NSData *)data{

    //Point to start of the data and set buffer sizes
    int inLength = [data length];
    int outLength = ((((inLength * 4)/3)/4)*4) + (((inLength * 4)/3)%4 ? 4 : 0);
    const char *inputBuffer = [data bytes];
    char *outputBuffer = malloc(outLength+1);
    outputBuffer[outLength] = 0;

    //64 digit code
    static char Encode[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

    //Start the count
    int cycle = 0;
    int inpos = 0;
    int outpos = 0;
    char temp;

    //Pad the last to bytes, the outbuffer must always be a multiple of 4.
    outputBuffer[outLength-1] = '=';
    outputBuffer[outLength-2] = '=';

    /* http://en.wikipedia.org/wiki/Base64

        Text content     M         a         n
        ASCII            77        97        110
        8 Bit pattern    01001101  01100001  01101110

        6 Bit pattern    010011    010110    000101    101110
        Index            19        22        5         46
        Base64-encoded   T         W         F         u
    */

    while (inpos < inLength){
        switch (cycle) {

            case 0:
                outputBuffer[outpos++] = Encode[(inputBuffer[inpos] & 0xFC) >> 2];
                cycle = 1;
                break;

            case 1:
                temp = (inputBuffer[inpos++] & 0x03) << 4;
                outputBuffer[outpos] = Encode[temp];
                cycle = 2;
                break;

            case 2:
                outputBuffer[outpos++] = Encode[temp|(inputBuffer[inpos]&0xF0) >> 4];
                temp = (inputBuffer[inpos++] & 0x0F) << 2;
                outputBuffer[outpos] = Encode[temp];
                cycle = 3;
                break;

            case 3:
                outputBuffer[outpos++] = Encode[temp|(inputBuffer[inpos]&0xC0) >> 6];
                cycle = 4;
                break;

            case 4:
                outputBuffer[outpos++] = Encode[inputBuffer[inpos++] & 0x3f];
                cycle = 0;
                break;

            default:
                cycle = 0;
                break;
        }
    }
    NSString *pictemp = [NSString stringWithUTF8String:outputBuffer];
    free(outputBuffer);
    return pictemp;
}

Solution 4

reference

NSString *plainString = @"foo";

Encoding

NSData *plainData = [plainString dataUsingEncoding:NSUTF8StringEncoding];
NSString *base64String = [plainData base64EncodedStringWithOptions:0];
NSLog(@"%@", base64String); // Zm9v

Decoding

NSData *decodedData = [[NSData alloc] initWithBase64EncodedString:base64String options:0];
NSString *decodedString = [[NSString alloc] initWithData:decodedData encoding:NSUTF8StringEncoding];
NSLog(@"%@", decodedString); // foo 

Solution 5

Try this out...this worked perfectly for me.create a category Base64.h and Base 64.m,Import to any class you want to use and call it using single line for base 64 encoding to happen.

//
//  Base64.h
//  CryptTest
//  Created by SURAJ K THOMAS  on 02/05/2013.


#import <Foundation/Foundation.h>


@interface Base64 : NSObject {

}
+ (void) initialize;
+ (NSString*) encode:(const uint8_t*) input length:(NSInteger) length;
+ (NSString*) encode:(NSData*) rawBytes;
+ (NSData*) decode:(const char*) string length:(NSInteger) inputLength;
+ (NSData*) decode:(NSString*) string;
@end





#import "Base64.h"


@implementation Base64
#define ArrayLength(x) (sizeof(x)/sizeof(*(x)))

static char encodingTable[] = 
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static char decodingTable[128];

+ (void) initialize {
if (self == [Base64 class]) {
    memset(decodingTable, 0, ArrayLength(decodingTable));
    for (NSInteger i = 0; i < ArrayLength(encodingTable); i++) {
        decodingTable[encodingTable[i]] = i;
    }
}
}


+ (NSString*) encode:(const uint8_t*) input length:(NSInteger) length {
NSMutableData* data = [NSMutableData dataWithLength:((length + 2) / 3) * 4];
uint8_t* output = (uint8_t*)data.mutableBytes;

for (NSInteger i = 0; i < length; i += 3) {
    NSInteger value = 0;
    for (NSInteger j = i; j < (i + 3); j++) {
        value <<= 8;

        if (j < length) {
            value |= (0xFF & input[j]);
        }
    }

    NSInteger index = (i / 3) * 4;
    output[index + 0] =                    encodingTable[(value >> 18) & 0x3F];
    output[index + 1] =                    encodingTable[(value >> 12) & 0x3F];
    output[index + 2] = (i + 1) < length ? encodingTable[(value >> 6)  & 0x3F] : '=';
    output[index + 3] = (i + 2) < length ? encodingTable[(value >> 0)  & 0x3F] : '=';
}

return [[NSString alloc] initWithData:data
                              encoding:NSASCIIStringEncoding];
}


+ (NSString*) encode:(NSData*) rawBytes {
return [self encode:(const uint8_t*) rawBytes.bytes length:rawBytes.length];
}


+ (NSData*) decode:(const char*) string length:(NSInteger) inputLength {
if ((string == NULL) || (inputLength % 4 != 0)) {
    return nil;
}

while (inputLength > 0 && string[inputLength - 1] == '=') {
    inputLength--;
}

NSInteger outputLength = inputLength * 3 / 4;
NSMutableData* data = [NSMutableData dataWithLength:outputLength];
uint8_t* output = data.mutableBytes;

NSInteger inputPoint = 0;
NSInteger outputPoint = 0;
while (inputPoint < inputLength) {
    char i0 = string[inputPoint++];
    char i1 = string[inputPoint++];
    char i2 = inputPoint < inputLength ? string[inputPoint++] : 'A'; /* 'A' will   
decode to \0 */
    char i3 = inputPoint < inputLength ? string[inputPoint++] : 'A';

    output[outputPoint++] = (decodingTable[i0] << 2) | (decodingTable[i1] >> 4);
    if (outputPoint < outputLength) {
        output[outputPoint++] = ((decodingTable[i1] & 0xf) << 4) |   
(decodingTable[i2] >> 2);
    }
    if (outputPoint < outputLength) {
        output[outputPoint++] = ((decodingTable[i2] & 0x3) << 6) |   
decodingTable[i3];
    }
}

return data;
}


+ (NSData*) decode:(NSString*) string {
return [self decode:[string cStringUsingEncoding:NSASCIIStringEncoding]   
length:string.length];
}

@end

now import the above category to any class and convert the string like below


 NSString *authString = [[NSString stringWithFormat:@"OD0EK819OJFIFT6OJZZXT09Y1YUT1EJ2"]   
stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];


NSData *inputData = [authString dataUsingEncoding:NSUTF8StringEncoding];

NSString *finalAuth =[Base64 encode:inputData];
NSLog(@"Encoded string =%@", finalAuth);
Share:
82,575
respectTheCode
Author by

respectTheCode

I am the founder of App Press and Playlister. I specialize in Node.js, React, React Native and Swift.

Updated on September 01, 2020

Comments

  • respectTheCode
    respectTheCode over 3 years

    How do I do Base64 encoding on the iPhone?

    I have found a few examples that looked promising, but could never get any of them to work on the phone.

  • Peter
    Peter about 12 years
    Had a lot of problems while using this code with ARC. My app crashed randomly.
  • Sulthan
    Sulthan over 11 years
    What's the mess with calculating output length?
  • gdubs
    gdubs about 11 years
    Hi @kdda , I know this has been answered for awhile now. Was wondering ifyou have a decode for this? Thanks!
  • CodesInChaos
    CodesInChaos almost 11 years
    1) The allocated buffer is too small which leads to memory corruption and crashes. I took the liberty of fixing that with an edit. 2) Your length calculation is way overcomplicated. Wouldn't a simple (inLength+2)/3*4 be enough?
  • Peter Mortensen
    Peter Mortensen almost 10 years
    This answer is referenced in Is copy & paste programming bad?.
  • Bryan Bryce
    Bryan Bryce about 8 years
    Wow, base 64 encoding wasn't in NSData until iOS 7.
  • oabarca
    oabarca almost 8 years
    initWithBase64Encoding is deprecated. Those clases need an update.
  • Gajendra K Chauhan
    Gajendra K Chauhan over 6 years
    It is now deprecated