Last active
December 17, 2016 03:42
-
-
Save danielphillips/3907443 to your computer and use it in GitHub Desktop.
NSString Crypto category
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import <Foundation/Foundation.h> | |
#import <CommonCrypto/CommonHMAC.h> | |
@interface NSString (Crypto) | |
- (NSString *)md5; | |
+ (NSString *)encodeBase64WithString:(NSString *)strData; | |
+ (NSString *)encodeBase64WithData:(NSData *)objData; | |
+ (NSData *)decodeBase64WithString:(NSString *)strBase64; | |
- (NSString*)sha1; | |
- (NSString*)base64; | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import "NSString+Crypto.h" | |
@implementation NSString (Crypto) | |
- (NSString *) md5 | |
{ | |
const char *cStr = [self UTF8String]; | |
unsigned char result[16]; | |
CC_MD5( cStr, strlen(cStr), result ); // This is the md5 call | |
return [NSString stringWithFormat: | |
@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", | |
result[0], result[1], result[2], result[3], | |
result[4], result[5], result[6], result[7], | |
result[8], result[9], result[10], result[11], | |
result[12], result[13], result[14], result[15] | |
]; | |
} | |
-(NSString*)sha1{ | |
const char *cstr = [self cStringUsingEncoding:NSUTF8StringEncoding]; | |
NSData *data = [NSData dataWithBytes:cstr length:self.length]; | |
uint8_t digest[CC_SHA1_DIGEST_LENGTH]; | |
CC_SHA1(data.bytes, data.length, digest); | |
NSMutableString* output = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2]; | |
for(int i = 0; i < CC_SHA1_DIGEST_LENGTH; i++) | |
[output appendFormat:@"%02x", digest[i]]; | |
return output; | |
} | |
-(NSString*)base64{ | |
return [NSString encodeBase64WithString:self]; | |
} | |
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 | |
}; | |
+ (NSString *)encodeBase64WithString:(NSString *)strData { | |
return [NSString 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, 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'; | |
NSString *resultString = [NSString stringWithCString:strResult encoding:NSASCIIStringEncoding]; | |
free(strResult); | |
// Return the results as an NSString object | |
return resultString; | |
} | |
+ (NSData *)decodeBase64WithString:(NSString *)strBase64 { | |
const char * objPointer = [strBase64 cStringUsingEncoding:NSASCIIStringEncoding]; | |
int intLength = strlen(objPointer); | |
int intCurrent; | |
int i = 0, j = 0, k; | |
char * objResult; | |
objResult = calloc(intLength, sizeof(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; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment