How do we queue image upload task in offline mode? - ios

In my app I have to implement a form which works offline as well.
There are some images to be uploaded in the form. The way I currently implement is by first saving the image in Application directory. And saving it's file location in database then delete it when I upload. This process is too lengthy and mind boggling. What do you guys suggest? Should I save it the image as Data in sqlite instead or this approach i took is better.
This is how I implemented it:
ALAssetsLibrary *lib=[ALAssetsLibrary new];
for (int i=0; i<assets.count; i++) {
ALAsset *asset=assets[i];
NSString *baseDir=[fileMgr GetDocumentDirectory];
//STORING FILE INTO LOCAL
[lib assetForURL:asset.defaultRepresentation.url
resultBlock:^(ALAsset *asset){
ALAssetRepresentation *repr = [asset defaultRepresentation];
CGImageRef cgImg = [repr fullResolutionImage];
NSString *fname = repr.filename;
UIImage *img = [UIImage imageWithCGImage:cgImg];
NSData *data = UIImagePNGRepresentation(img);
[data writeToFile:[baseDir stringByAppendingPathComponent:fname]
atomically:YES];
//FOR LOCAL URL OF THE IMAGE
NSString *imageURL = [baseDir stringByAppendingPathComponent:fname];
NSLog(#"%# URL OF IMAGE ",imageURL);
}
failureBlock:^(NSError *error){
}];
}
NSLog(#"COPIED %lu FILE INTO LOCAL MEMORY",(unsigned long)assets.count);

yes you can save the image in database as a string. create an catagory NSString+NSStringAdditions.h like this.
//
// NSString+NSStringAdditions.h
// RemoteControl
//
// Created by Bhaskar on 09/05/14.
// Copyright (c) 2014 Bhaskar. All rights reserved.
//
#import <Foundation/Foundation.h>
#interface NSString (NSStringAdditions)
+ (NSString *) base64StringFromData:(NSData *)data length:(int)length;
+ (NSData *) base64DataFromString:(NSString *)string;
#end
//
// NSString+NSStringAdditions.m
// RemoteControl
//
// Created by Bhaskar on 09/05/14.
// Copyright (c) 2014 Bhaskar. All rights reserved.
//
#import "NSString+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;
}
+ (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

Related

aes cbc encrypt, decrypt result is diffrent(objecitve-c, c#)

i have a code in c# for aes decryption
i want make same encryption result by objective-c
but i failed.. help me
i can fix objective-c code, what can i for this?
c# for decrypt
private static readonly string AES_KEY = "asdfasdfasdfasdf";
private static readonly int BUFFER_SIZE = 1024 * 4;
private static readonly int KEY_SIZE = 128;
private static readonly int BLOCK_SIZE = 128;
static public string Composite(string value)
{
using (AesManaged aes = new AesManaged())
using (MemoryStream ims = new MemoryStream(Convert.FromBase64String(value), false))
{
aes.KeySize = KEY_SIZE;
aes.BlockSize = BLOCK_SIZE;
aes.Mode = CipherMode.CBC;
aes.Key = Encoding.UTF8.GetBytes(AES_KEY);
byte[] iv = new byte[aes.IV.Length];
ims.Read(iv, 0, iv.Length);
aes.IV = iv;
using (ICryptoTransform ce = aes.CreateDecryptor(aes.Key, aes.IV))
using (CryptoStream cs = new CryptoStream(ims, ce, CryptoStreamMode.Read))
using (DeflateStream ds = new DeflateStream(cs, CompressionMode.Decompress))
using (MemoryStream oms = new MemoryStream())
{
byte[] buf = new byte[BUFFER_SIZE];
for (int size = ds.Read(buf, 0, buf.Length); size > 0; size = ds.Read(buf, 0, buf.Length))
{
oms.Write(buf, 0, size);
}
return Encoding.UTF8.GetString(oms.ToArray());
}
}
}
objective-c for encrypt
- (NSString *)AES128EncryptWithKey:(NSString *)key
{
NSData *plainData = [self dataUsingEncoding:NSUTF8StringEncoding];
NSData *encryptedData = [plainData AES128EncryptWithKey:key];
NSString *encryptedString = [encryptedData stringUsingEncodingBase64];
return encryptedString;
}
#import "NSData+AESCrypt.h"
#import <CommonCrypto/CommonCryptor.h>
static char encodingTable[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 NSData (AESCrypt)
- (NSData *)AES128EncryptWithKey:(NSString *)key
{
// 'key' should be 16 bytes for AES128
char keyPtr[kCCKeySizeAES128 + 1]; // room for terminator (unused)
bzero( keyPtr, sizeof( keyPtr ) ); // fill with zeroes (for padding)
// fetch key data
[key getCString:keyPtr maxLength:sizeof( keyPtr ) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [self length];
//See the doc: For block ciphers, the output size will always be less than or
//equal to the input size plus the size of one block.
//That's why we need to add the size of one block here
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc( bufferSize );
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt( kCCEncrypt, kCCAlgorithmAES128, kCCModeCBC | kCCOptionPKCS7Padding,
keyPtr, kCCKeySizeAES128,
NULL /* initialization vector (optional) */,
[self bytes], dataLength, /* input */
buffer, bufferSize, /* output */
&numBytesEncrypted );
if( cryptStatus == kCCSuccess )
{
//the returned NSData takes ownership of the buffer and will free it on deallocation
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}
free( buffer ); //free the buffer
return nil;
}
- (NSString *)base64Encoding
{
const unsigned char *bytes = [self bytes];
NSMutableString *result = [NSMutableString stringWithCapacity:self.length];
unsigned long ixtext = 0;
unsigned long lentext = self.length;
long ctremaining = 0;
unsigned char inbuf[3], outbuf[4];
unsigned short i = 0;
unsigned short charsonline = 0, ctcopy = 0;
unsigned long ix = 0;
while( YES )
{
ctremaining = lentext - ixtext;
if( ctremaining <= 0 ) break;
for( i = 0; i < 3; i++ )
{
ix = ixtext + i;
if( ix < lentext ) inbuf[i] = bytes[ix];
else inbuf [i] = 0;
}
outbuf [0] = (inbuf [0] & 0xFC) >> 2;
outbuf [1] = ((inbuf [0] & 0x03) << 4) | ((inbuf [1] & 0xF0) >> 4);
outbuf [2] = ((inbuf [1] & 0x0F) << 2) | ((inbuf [2] & 0xC0) >> 6);
outbuf [3] = inbuf [2] & 0x3F;
ctcopy = 4;
switch( ctremaining )
{
case 1:
ctcopy = 2;
break;
case 2:
ctcopy = 3;
break;
}
for( i = 0; i < ctcopy; i++ )
[result appendFormat:#"%c", encodingTable[outbuf[i]]];
for( i = ctcopy; i < 4; i++ )
[result appendString:#"="];
ixtext += 3;
charsonline += 4;
}
return [NSString stringWithString:result];
}
------------------------------------------------------------
------------------------------------------------------------

Implementation of RC4 Encryption and URL encoding in objective c

I've to implement the RC4 encryption algorithm in my application for URL encoding.The sample part is listed below for your reference.
Actual value Before Encryption : 10/28/2013
Expected value After Encryption : ˆ!˜·hÇÔÞò
After URL encoding it should be : %0C%88%21%98%B7h%C7%D4%DE%F2
KEY USED is:#"psw"
I've tried but value after encryption & URL encoding returns in this way:
After encryption : !·hÇÔÞò
After URL encoding : %0C%C2%88%21%C2%98%C2%B7h%C3%87%C3%94%C3%9E%C3%B2
I tried converting the java code into objective c code.The java code works fine ,were as the objective c is not working, which you can see in the above result.
Here is the Java code
import java.net.URLEncoder;
public class RC4 {
private char[] key;
private int[] sbox;
private static final int SBOX_LENGTH = 256;
private static final int KEY_MIN_LENGTH = 1;
public static void main(String[] args) {
try {
RC4 rc4 = new RC4("psw");
char[] result = rc4.encrypt("10/28/2013".toCharArray());
System.out.println("encrypted string:\n"
+ new String(toByteArray(result)));
System.out.println("decrypted string:\n"
+ new String(rc4.decrypt(result)));
System.out.println("decrypted string:\n"
+ URLEncoder.encode(new String(toByteArray(result))));
} catch (InvalidKeyException e) {
System.err.println(e.getMessage());
}
}
static byte[] toByteArray(char[] chars) {
byte[] bytes = new byte[chars.length];
for (int i = 0; i < chars.length; i++) {
// bytes[i*2] = (byte) (chars[i] >> 8);
bytes[i] = (byte) chars[i];
}
return bytes;
}
public RC4(String key) throws InvalidKeyException {
setKey(key);
}
public RC4() {
}
public char[] decrypt(final char[] msg) {
return encrypt(msg);
}
public char[] encrypt(final char[] msg) {
sbox = initSBox(key);
char[] code = new char[msg.length];
int i = 0;
int j = 0;
for (int n = 0; n < msg.length; n++) {
i = (i + 1) % SBOX_LENGTH;
j = (j + sbox[i]) % SBOX_LENGTH;
swap(i, j, sbox);
int rand = sbox[(sbox[i] + sbox[j]) % SBOX_LENGTH];
code[n] = (char) (rand ^ (int) msg[n]);
}
return code;
}
private int[] initSBox(char[] key) {
int[] sbox = new int[SBOX_LENGTH];
int j = 0;
for (int i = 0; i < SBOX_LENGTH; i++) {
sbox[i] = i;
}
for (int i = 0; i < SBOX_LENGTH; i++) {
j = (j + sbox[i] + key[i % key.length]) % SBOX_LENGTH;
swap(i, j, sbox);
}
return sbox;
}
private void swap(int i, int j, int[] sbox) {
int temp = sbox[i];
sbox[i] = sbox[j];
sbox[j] = temp;
}
public void setKey(String key) throws InvalidKeyException {
if (!(key.length() >= KEY_MIN_LENGTH && key.length() < SBOX_LENGTH)) {
throw new InvalidKeyException("Key length has to be between "
+ KEY_MIN_LENGTH + " and " + (SBOX_LENGTH - 1));
}
this.key = key.toCharArray();
}
public class InvalidKeyException extends Exception {
private static final long serialVersionUID = 1L;
public InvalidKeyException(String message) {
super(message);
}
}
}
Its corresponding Objective c Code
-(NSString *)encrypt:(NSString *)string{
[self frameSBox:#"psw"];
unichar code[string.length];
const unichar* buffer = code;
int i = 0;
int j = 0;
for (int n = 0; n < string.length; n++) {
i = (i + 1) % self.SBOX_LENGTH;
j = (j + [[self.sBox objectAtIndex:i]integerValue]) % self.SBOX_LENGTH;
[self swap:i with:j];
int index=([[self.sBox objectAtIndex:i] integerValue]+[[self.sBox objectAtIndex:j] integerValue]);
int rand=([[self.sBox objectAtIndex:(index%self.SBOX_LENGTH)] integerValue]);
code[n]=(rand ^ (int)[string characterAtIndex:n]);
}
buffer = code;
return [NSString stringWithCharacters:buffer length:string.length];
}
-(NSArray *)frameSBox:(NSString *)keyValue{
if (self.sBox == nil) {
self.sBox=[[NSMutableArray alloc]init];
}
self.SBOX_LENGTH=256;
int j = 0;
for (int i = 0; i < self.SBOX_LENGTH; i++) {
[self.sBox addObject:[NSNumber numberWithInteger:i]];
}
for (int i = 0; i < self.SBOX_LENGTH; i++) {
j = (j + [[self.sBox objectAtIndex:i] integerValue] + [keyValue characterAtIndex:(i % keyValue.length)]) % self.SBOX_LENGTH;
[self swap:i with:j];
}
return self.sBox;
}
-(void)swap:(int)i with:(int)j{
id tempObj = [self.sBox objectAtIndex:i];
[self.sBox replaceObjectAtIndex:i withObject:[self.sBox objectAtIndex:j]];
[self.sBox replaceObjectAtIndex:j withObject:tempObj];
}
//I'm calling in a different class by creating the RC4encryptor object
NSString *unescaped = [[RC4StringEncryptor encryptor] encrypt:#"10/28/2013"];
logDebug(#"the value is:%#",unescaped);
NSString *escapedString = (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(
NULL,
(__bridge CFStringRef) unescaped,
NULL,
CFSTR("!*'();:#&=+$,/?%#[]\" "),
kCFStringEncodingUTF8));
NSLog(#"escapedString: %#",escapedString);
I've also tried
#import <CommonCrypto/CommonCryptor.h>
#implementation NSData (RC4)
- (NSData *)RC4EncryptWithKey:(NSString *)key {
char keyPtr[kCCKeySizeMinRC4+1];
bzero(keyPtr, sizeof(keyPtr));
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [self length];
size_t bufferSize = dataLength + kCCKeySizeMinRC4;
void *buffer = malloc(bufferSize);
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmRC4, kCCModeRC4,
keyPtr, kCCKeySizeMinRC4,
NULL ,
[self bytes], dataLength,
buffer, bufferSize,
&numBytesEncrypted);
if (cryptStatus == kCCSuccess) {
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}
free(buffer);
return nil;
}
- (NSData*) encryptString:(NSString*)plaintext withKey:(NSString*)key {
return [[plaintext dataUsingEncoding:NSUTF8StringEncoding] RC4EncryptWithKey:key];
}
But this above code doesn't work for me.Kindly help me in this....
Somehow I fixed your code and it encrypts-decrypts perfectly. Here it is:
#interface RC4Crypt()
#property (nonatomic, strong) NSArray * key;
#property (nonatomic, strong) NSMutableArray * sBox;
#end
#implementation RC4Crypt
static const int SBOX_LENGTH = 256;
static const int KEY_MIN_LENGTH = 1;
-(NSString *)encrypt:(NSString *)string withKey:(NSString *)key{
self.sBox = [[self frameSBox:key] mutableCopy];
unichar code[string.length];
int i = 0;
int j = 0;
for (int n = 0; n < string.length; n++) {
i = (i + 1) % SBOX_LENGTH;
j = (j + [[self.sBox objectAtIndex:i]integerValue]) % SBOX_LENGTH;
[self.sBox exchangeObjectAtIndex:i withObjectAtIndex:j];
int index=([self.sBox[i] integerValue]+[self.sBox[j] integerValue]);
int rand=([self.sBox[(index%SBOX_LENGTH)] integerValue]);
code[n]=(rand ^ (int)[string characterAtIndex:n]);
}
const unichar* buffer;
buffer = code;
return [NSString stringWithCharacters:buffer length:string.length];
}
- (NSString*) decrypt:(NSString*)string withKey:(NSString*)key
{
return [self encrypt:string withKey:key];
}
-(NSArray *)frameSBox:(NSString *)keyValue{
NSMutableArray *sBox = [[NSMutableArray alloc] initWithCapacity:SBOX_LENGTH];
int j = 0;
for (int i = 0; i < SBOX_LENGTH; i++) {
[sBox addObject:[NSNumber numberWithInteger:i]];
}
for (int i = 0; i < SBOX_LENGTH; i++) {
j = (j + [sBox[i] integerValue] + [keyValue characterAtIndex:(i % keyValue.length)]) % SBOX_LENGTH;
[sBox exchangeObjectAtIndex:i withObjectAtIndex:j];
}
return [NSArray arrayWithArray:sBox];
}
#end

Verify digital signature with public key in iOS

How to Verify digital signature with public key in iOS without using any third party code(e.g.) open SSL?
I need to verify Digital signature in iOS App with a public key. Can some one help me how to achieve that without using third party software.
I am trying below code but the problem is I don't have certificate in my App so can not create SecTrustRef.
CODE:
NSString *certPath = [[NSBundle mainBundle] pathForResource:#"yyy"
ofType:#"xxx"];
SecCertificateRef myCertificate = nil;
NSData *certificateData = [[NSData alloc] initWithContentsOfFile :certPath];
myCertificate = SecCertificateCreateWithData(kCFAllocatorDefault, (__bridge CFDataRef)certificateData);
SecPolicyRef myPolicy = SecPolicyCreateBasicX509();
SecTrustRef trustRef;
SecTrustCreateWithCertificates(myCertificate, myPolicy, &trustRef);
SecKeyRef keyRef = SecTrustCopyPublicKey (trustRef);
BOOL status = SecKeyRawVerify (keyRef,
kSecPaddingPKCS1SHA1,
(const uint8_t *)[data bytes],
(size_t)[data length],
(const uint8_t *)[signature bytes],
(size_t)[signature length]
);
I have the following:
Public Key (NSString*)
Signature (NSString*)
Data (NSString*)
Please help me what all option I have in iOS SDK if I don't want to use ant third party open source.
You can package your public key in a X509 certificate to use the iOS built in functions easily, using openSSL:
openssl req -x509 -out public_key.pem -outform pem -new -newkey rsa:2048 -keyout private_key.pem
the PEM format is base64 encoded, you can switch the -outform to DER to get binary file.
you can import the PEM format by adding a const NSString to your program and adding category to NSData with this function:
- (id) initWithBase64EncodedString:(NSString *) string {
NSMutableData *mutableData = nil;
if( string ) {
unsigned long ixtext = 0;
unsigned long lentext = 0;
unsigned char ch = 0;
unsigned char inbuf[4], outbuf[3]; // buffer sizes fixed by AOL LLC
short i = 0, ixinbuf = 0;
BOOL flignore = NO;
BOOL flendtext = NO;
NSData *base64Data = nil;
const unsigned char *base64Bytes = nil;
// Convert the string to ASCII data.
base64Data = [string dataUsingEncoding:NSASCIIStringEncoding];
base64Bytes = [base64Data bytes];
mutableData = [NSMutableData dataWithCapacity:[base64Data length]];
lentext = [base64Data length];
while( YES ) {
if( ixtext >= lentext ) break;
ch = base64Bytes[ixtext++];
flignore = NO;
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 = YES;
else if( ch == '/' ) ch = 63;
else flignore = YES;
if( ! flignore ) {
short ctcharsinbuf = 3;
BOOL flbreak = NO;
if( flendtext ) {
if( ! ixinbuf ) break;
if( ( ixinbuf == 1 ) || ( ixinbuf == 2 ) ) ctcharsinbuf = 1;
else ctcharsinbuf = 2;
ixinbuf = 3;
flbreak = YES;
}
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++ )
[mutableData appendBytes:&outbuf[i] length:1];
}
if( flbreak ) break;
}
}
}
self = [self initWithData:mutableData];
return self;
}
ofcourse you pull this file into the certificateData
if you want to use your existing public key just pull it out and write it in a X509 cert format using openSSL
$ openssl rsa -in id_rsa -out pub.der -outform DER -pubout
good luck
If your key data is packaged as PKCS12 data, use SecPKCS12Import to import it and use the public key.
You need to pass a digest (hash) of your data to the verification function. See iOS: Verifying a File With a Certificate and Signature - Public Key is Wrong, Verification Fails
#interface HDSecurityPolicy :AFSecurityPolicy
#end
#implementation HDSecurityPolicy
///pem formate(base64) -> NSData
- (void)setPinnedCertificates:(NSSet *)pinnedCertificates {
[super setPinnedCertificates:pinnedCertificates];
if (self.pinnedCertificates) {
NSMutableSet *mutablePinnedPublicKeys = [NSMutableSet setWithCapacity:[self.pinnedCertificates count]];
for (NSData *pubCertificate in self.pinnedCertificates) {
id publicKey = [HDSecurityPolicy publicSecKeyFromKeyBits:pubCertificate];
if (!publicKey) {
continue;
}
[mutablePinnedPublicKeys addObject:publicKey];
}
[self setValue:mutablePinnedPublicKeys forKey:#"pinnedPublicKeys"];
}
}
// 从公钥证书文件中获取到公钥的SecKeyRef指针
+ (id)publicSecKeyFromKeyBits:(NSData *)givenData {
NSMutableDictionary *options = [NSMutableDictionary dictionary];
options[(__bridge id)kSecAttrKeyType] = (__bridge id) kSecAttrKeyTypeRSA;
options[(__bridge id)kSecAttrKeyClass] = (__bridge id) kSecAttrKeyClassPublic;
NSError *error = nil;
CFErrorRef ee = (__bridge CFErrorRef)error;
////'SecKeyCreateWithData' is only available on iOS 10.0 or newer
id ret = (__bridge_transfer id)SecKeyCreateWithData((__bridge CFDataRef)givenData, (__bridge CFDictionaryRef)options, &ee);
if (error) {
return nil;
}
return ret;
}
#end

How to decode / convert a base64 string to NSData?

Hello I am trying to figure out how convert / decode a base64 string in an iOS application to NSData, so I can decrypt the data that I encrypted.
The method I used for converting the NSData to a base 64 string can be found here Is there a similar way to create method to decode / convert the base 64 string to NSData?
This is what I was looking for.
+ (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;
}

How do I do base64 encoding on iOS?

I'd like to do base64 encoding and decoding, but I could not find any support from the iPhone SDK. How can I do base64 encoding and decoding with or without a library?
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)
iOS includes built in support for base64 encoding and decoding. If you look at resolv.h you should see the two functions b64_ntop and b64_pton . The Square SocketRocket library provides a reasonable example of how to use these functions from objective-c.
These functions are pretty well tested and reliable - unlike many of the implementations you may find in random internet postings.
Don't forget to link against libresolv.dylib.
Since this seems to be the number one google hit on base64 encoding and iphone, I felt like sharing my experience with the code snippet above.
It works, but it is extremely slow. A benchmark on a random image (0.4 mb) took 37 seconds on native iphone. The main reason is probably all the OOP magic - single char NSStrings etc, which are only autoreleased after the encoding is done.
Another suggestion posted here (ab)uses the openssl library, which feels like overkill as well.
The code below takes 70 ms - that's a 500 times speedup. This only does base64 encoding (decoding will follow as soon as I encounter it)
+ (NSString *) base64StringFromData: (NSData *)data length: (int)length {
int lentext = [data length];
if (lentext < 1) return #"";
char *outbuf = malloc(lentext*4/3+4); // add 4 to be sure
if ( !outbuf ) return nil;
const unsigned char *raw = [data bytes];
int inp = 0;
int outp = 0;
int do_now = lentext - (lentext%3);
for ( outp = 0, inp = 0; inp < do_now; inp += 3 )
{
outbuf[outp++] = base64EncodingTable[(raw[inp] & 0xFC) >> 2];
outbuf[outp++] = base64EncodingTable[((raw[inp] & 0x03) << 4) | ((raw[inp+1] & 0xF0) >> 4)];
outbuf[outp++] = base64EncodingTable[((raw[inp+1] & 0x0F) << 2) | ((raw[inp+2] & 0xC0) >> 6)];
outbuf[outp++] = base64EncodingTable[raw[inp+2] & 0x3F];
}
if ( do_now < lentext )
{
char tmpbuf[2] = {0,0};
int left = lentext%3;
for ( int i=0; i < left; i++ )
{
tmpbuf[i] = raw[do_now+i];
}
raw = tmpbuf;
outbuf[outp++] = base64EncodingTable[(raw[inp] & 0xFC) >> 2];
outbuf[outp++] = base64EncodingTable[((raw[inp] & 0x03) << 4) | ((raw[inp+1] & 0xF0) >> 4)];
if ( left == 2 ) outbuf[outp++] = base64EncodingTable[((raw[inp+1] & 0x0F) << 2) | ((raw[inp+2] & 0xC0) >> 6)];
}
NSString *ret = [[[NSString alloc] initWithBytes:outbuf length:outp encoding:NSASCIIStringEncoding] autorelease];
free(outbuf);
return ret;
}
I left out the line-cutting since I didn't need it, but it's trivial to add.
For those who are interested in optimizing: the goal is to minimize what happens in the main loop. Therefore all logic to deal with the last 3 bytes is treated outside the loop.
Also, try to work on data in-place, without additional copying to/from buffers. And reduce any arithmetic to the bare minimum.
Observe that the bits that are put together to look up an entry in the table, would not overlap when they were to be orred together without shifting. A major improvement could therefore be to use 4 separate 256 byte lookup tables and eliminate the shifts, like this:
outbuf[outp++] = base64EncodingTable1[(raw[inp] & 0xFC)];
outbuf[outp++] = base64EncodingTable2[(raw[inp] & 0x03) | (raw[inp+1] & 0xF0)];
outbuf[outp++] = base64EncodingTable3[(raw[inp+1] & 0x0F) | (raw[inp+2] & 0xC0)];
outbuf[outp++] = base64EncodingTable4[raw[inp+2] & 0x3F];
Of course you could take it a whole lot further, but that's beyond the scope here.
In mvds's excellent improvement, there are two problems. Change code to this:
raw = tmpbuf;
inp = 0;
outbuf[outp++] = base64EncodingTable[(raw[inp] & 0xFC) >> 2];
outbuf[outp++] = base64EncodingTable[((raw[inp] & 0x03) << 4) | ((raw[inp+1] & 0xF0) >> 4)];
if ( left == 2 ) outbuf[outp++] = base64EncodingTable[((raw[inp+1] & 0x0F) << 2) | ((raw[inp+2] & 0xC0) >> 6)];
else outbuf[outp++] = '=';
outbuf[outp++] = '=';
Better solution :
There is a built in function in NSData
[data base64Encoding]; //iOS < 7.0
[data base64EncodedStringWithOptions:NSDataBase64Encoding76CharacterLineLength]; //iOS >= 7.0
Glad people liked it. The end-game was a little flawed I must admit. Besides rightly setting inp=0 you should either also increase tmpbuf's size to 3, like
unsigned char tmpbuf[3] = {0,0,0};
or leave out the orring of raw[inp+2]; if we would have a raw[inp+2] != 0 for this chunk we would still be in the loop of course...
Either way works, you might consider keeping the final table lookup block identical to the one in the loop for clarity. In the final version I used I did
while ( outp%4 ) outbuf[outp++] = '=';
To add the ==
Sorry I didn't check RFC's and stuff, should have done a better job!
Under iOS8 and later use - (NSString *)base64EncodedStringWithOptions:(NSDataBase64EncodingOptions)options of NSData
#import "NSDataAdditions.h"
#implementation NSData (NSDataAdditions)
+ (NSData *) base64DataFromString: (NSString *)string {
unsigned long ixtext, lentext;
unsigned char ch, input[4], output[3];
short i, ixinput;
Boolean flignore, flendtext = false;
const char *temporary;
NSMutableData *result;
if (!string)
return [NSData data];
ixtext = 0;
temporary = [string UTF8String];
lentext = [string length];
result = [NSMutableData dataWithCapacity: lentext];
ixinput = 0;
while (true) {
if (ixtext >= lentext)
break;
ch = temporary[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 ctcharsinput = 3;
Boolean flbreak = false;
if (flendtext) {
if (ixinput == 0)
break;
if ((ixinput == 1) || (ixinput == 2))
ctcharsinput = 1;
else
ctcharsinput = 2;
ixinput = 3;
flbreak = true;
}
input[ixinput++] = ch;
if (ixinput == 4){
ixinput = 0;
output[0] = (input[0] << 2) | ((input[1] & 0x30) >> 4);
output[1] = ((input[1] & 0x0F) << 4) | ((input[2] & 0x3C) >> 2);
output[2] = ((input[2] & 0x03) << 6) | (input[3] & 0x3F);
for (i = 0; i < ctcharsinput; i++)
[result appendBytes: &output[i] length: 1];
}
if (flbreak)
break;
}
}
return result;
}
#end
For an update to use the NSData (NSDataBase64Encoding) category methods in iOS7 see my answer here: https://stackoverflow.com/a/18927627/1602729
Here's a compact Objective-C version as a Category on NSData. It takes some thinking about...
#implementation NSData (DataUtils)
static char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
- (NSString *)newStringInBase64FromData
{
NSMutableString *dest = [[NSMutableString alloc] initWithString:#""];
unsigned char * working = (unsigned char *)[self bytes];
int srcLen = [self length];
// tackle the source in 3's as conveniently 4 Base64 nibbles fit into 3 bytes
for (int i=0; i<srcLen; i += 3)
{
// for each output nibble
for (int nib=0; nib<4; nib++)
{
// nibble:nib from char:byt
int byt = (nib == 0)?0:nib-1;
int ix = (nib+1)*2;
if (i+byt >= srcLen) break;
// extract the top bits of the nibble, if valid
unsigned char curr = ((working[i+byt] << (8-ix)) & 0x3F);
// extract the bottom bits of the nibble, if valid
if (i+nib < srcLen) curr |= ((working[i+nib] >> ix) & 0x3F);
[dest appendFormat:#"%c", base64[curr]];
}
}
return dest;
}
#end
Padding can be added if required by making the scope of 'byt' wider and appending 'dest' with (2-byt) "=" characters before returning.
A Category can then be added to NSString, thus:
#implementation NSString (StringUtils)
- (NSString *)newStringInBase64FromString
{
NSData *theData = [NSData dataWithBytes:[self UTF8String] length:[self length]];
return [theData newStringInBase64FromData];
}
#end
iOS has had built-in Base64 encoding and decoding methods (without using libresolv) since iOS 4. However, it was only declared in the iOS 7 SDK. Apple documentation states that you can use it when targeting iOS 4 and above.
NSData *myData = ... some data
NSString *base64String = [myData base64Encoding];
NSData *decodedData = [[NSData alloc] initWithBase64Encoding:base64String];
Here is an example to convert an NSData object to Base 64. It also shows how to go the other way (decode a base 64 encoded NSData object):
NSData *dataTake2 =
[#"iOS Developer Tips" dataUsingEncoding:NSUTF8StringEncoding];
// Convert to Base64 data
NSData *base64Data = [dataTake2 base64EncodedDataWithOptions:0];
// Do something with the data...
// Now convert back from Base64
NSData *nsdataDecoded = [base64Data initWithBase64EncodedData:base64Data options:0];
in iOS 7
NSData *data=[[NSData alloc]init];
[data base64Encoding];
I have done it using the following class..
#implementation Base64Converter
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', '+', '/'
};
+ (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
While calling call
[Base64Converter base64StringFromData:dataval length:lengthval];
That's it...
I Think This will be helpful
+ (NSString *)toBase64String:(NSString *)string {
NSData *data = [string dataUsingEncoding: NSUnicodeStringEncoding];
NSString *ret = [data base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
return ret;
}
+ (NSString *)fromBase64String:(NSString *)string {
NSData *aData = [string dataUsingEncoding:NSUTF8StringEncoding];
NSData *aDataDecoded = [[NSData alloc]initWithBase64EncodedString:string options:0];
NSString *decryptedStr = [[NSString alloc]initWithData:aDataDecoded encoding:NSUTF8StringEncoding];
return [decryptedStr autorelease];
}
Download Base64
Do following code to convert an image to base64
NSString *base64String=[UIImagePNGRepresentation(image) base64Encoding];
As per your requirement i have created a sample demo using Swift 4 in which you can encode/decode string and image as per your requirement.
I have also added sample methods of relevant operations.
//
// Base64VC.swift
// SOF_SortArrayOfCustomObject
//
// Created by Test User on 09/01/18.
// Copyright © 2018 Test User. All rights reserved.
//
import UIKit
import Foundation
class Base64VC: NSObject {
//----------------------------------------------------------------
// MARK:-
// MARK:- String to Base64 Encode Methods
//----------------------------------------------------------------
func sampleStringEncodingAndDecoding() {
if let base64String = self.base64Encode(string: "TestString") {
print("Base64 Encoded String: \n\(base64String)")
if let originalString = self.base64Decode(base64String: base64String) {
print("Base64 Decoded String: \n\(originalString)")
}
}
}
//----------------------------------------------------------------
func base64Encode(string: String) -> String? {
if let stringData = string.data(using: .utf8) {
return stringData.base64EncodedString()
}
return nil
}
//----------------------------------------------------------------
func base64Decode(base64String: String) -> String? {
if let base64Data = Data(base64Encoded: base64String) {
return String(data: base64Data, encoding: .utf8)
}
return nil
}
//----------------------------------------------------------------
// MARK:-
// MARK:- Image to Base64 Encode Methods
//----------------------------------------------------------------
func sampleImageEncodingAndDecoding() {
if let base64ImageString = self.base64Encode(image: UIImage.init(named: "yourImageName")!) {
print("Base64 Encoded Image: \n\(base64ImageString)")
if let originaImage = self.base64Decode(base64ImageString: base64ImageString) {
print("originalImageData \n\(originaImage)")
}
}
}
//----------------------------------------------------------------
func base64Encode(image: UIImage) -> String? {
if let imageData = UIImagePNGRepresentation(image) {
return imageData.base64EncodedString()
}
return nil
}
//----------------------------------------------------------------
func base64Decode(base64ImageString: String) -> UIImage? {
if let base64Data = Data(base64Encoded: base64ImageString) {
return UIImage(data: base64Data)!
}
return nil
}
}

Resources