参看:https://github.com/Gurpartap/AESCrypt-ObjC
AESCrypt.h
// // AESCrypt.h // Gurpartap Singh // // Created by Gurpartap Singh on 06/05/12. // Copyright (c) 2012 Gurpartap Singh // // MIT License // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // #import <Foundation/Foundation.h> @interface AESCrypt : NSObject + (NSString *)encrypt:(NSString *)message password:(NSString *)password; + (NSString *)decrypt:(NSString *)base64EncodedString password:(NSString *)password; @end
AESCrypt.m
// // AESCrypt.m // Gurpartap Singh // // Created by Gurpartap Singh on 06/05/12. // Copyright (c) 2012 Gurpartap Singh // // MIT License // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // #import "AESCrypt.h" #import "NSData+Base64.h" #import "NSString+Base64.h" #import "NSData+CommonCrypto.h" @implementation AESCrypt + (NSString *)encrypt:(NSString *)message password:(NSString *)password { NSData *encryptedData = [[message dataUsingEncoding:NSUTF8StringEncoding] AES256EncryptedDataUsingKey:[[password dataUsingEncoding:NSUTF8StringEncoding] SHA256Hash] error:nil]; NSString *base64EncodedString = [NSString base64StringFromData:encryptedData length:[encryptedData length]]; return base64EncodedString; } + (NSString *)decrypt:(NSString *)base64EncodedString password:(NSString *)password { NSData *encryptedData = [NSData base64DataFromString:base64EncodedString]; NSData *decryptedData = [encryptedData decryptedAES256DataUsingKey:[[password dataUsingEncoding:NSUTF8StringEncoding] SHA256Hash] error:nil]; return [[NSString alloc] initWithData:decryptedData encoding:NSUTF8StringEncoding]; } @end
// // NSData+Base64.m // Gurpartap Singh // // Created by Gurpartap Singh on 06/05/12. // Copyright (c) 2012 Gurpartap Singh. All rights reserved. // #import <Foundation/Foundation.h> @class NSString; @interface NSData (Base64Additions) + (NSData *)base64DataFromString:(NSString *)string; @end
// // NSData+Base64.h // Gurpartap Singh // // Created by Gurpartap Singh on 06/05/12. // Copyright (c) 2012 Gurpartap Singh. All rights reserved. // #import "NSData+Base64.h" @implementation NSData (Base64Additions) + (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
/* * NSData+CommonCrypto.h * AQToolkit * * Created by Jim Dovey on 31/8/2008. * * Copyright (c) 2008-2009, Jim Dovey * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of this project's author nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import <Foundation/NSData.h> #import <Foundation/NSError.h> #import <CommonCrypto/CommonCryptor.h> #import <CommonCrypto/CommonHMAC.h> extern NSString * const kCommonCryptoErrorDomain; @interface NSError (CommonCryptoErrorDomain) + (NSError *) errorWithCCCryptorStatus: (CCCryptorStatus) status; @end @interface NSData (CommonDigest) - (NSData *) MD2Sum; - (NSData *) MD4Sum; - (NSData *) MD5Sum; - (NSData *) SHA1Hash; - (NSData *) SHA224Hash; - (NSData *) SHA256Hash; - (NSData *) SHA384Hash; - (NSData *) SHA512Hash; @end @interface NSData (CommonCryptor) - (NSData *) AES256EncryptedDataUsingKey: (id) key error: (NSError **) error; - (NSData *) decryptedAES256DataUsingKey: (id) key error: (NSError **) error; - (NSData *) DESEncryptedDataUsingKey: (id) key error: (NSError **) error; - (NSData *) decryptedDESDataUsingKey: (id) key error: (NSError **) error; - (NSData *) CASTEncryptedDataUsingKey: (id) key error: (NSError **) error; - (NSData *) decryptedCASTDataUsingKey: (id) key error: (NSError **) error; @end @interface NSData (LowLevelCommonCryptor) - (NSData *) dataEncryptedUsingAlgorithm: (CCAlgorithm) algorithm key: (id) key // data or string error: (CCCryptorStatus *) error; - (NSData *) dataEncryptedUsingAlgorithm: (CCAlgorithm) algorithm key: (id) key // data or string options: (CCOptions) options error: (CCCryptorStatus *) error; - (NSData *) dataEncryptedUsingAlgorithm: (CCAlgorithm) algorithm key: (id) key // data or string initializationVector: (id) iv // data or string options: (CCOptions) options error: (CCCryptorStatus *) error; - (NSData *) decryptedDataUsingAlgorithm: (CCAlgorithm) algorithm key: (id) key // data or string error: (CCCryptorStatus *) error; - (NSData *) decryptedDataUsingAlgorithm: (CCAlgorithm) algorithm key: (id) key // data or string options: (CCOptions) options error: (CCCryptorStatus *) error; - (NSData *) decryptedDataUsingAlgorithm: (CCAlgorithm) algorithm key: (id) key // data or string initializationVector: (id) iv // data or string options: (CCOptions) options error: (CCCryptorStatus *) error; @end @interface NSData (CommonHMAC) - (NSData *) HMACWithAlgorithm: (CCHmacAlgorithm) algorithm; - (NSData *) HMACWithAlgorithm: (CCHmacAlgorithm) algorithm key: (id) key; @end
/* * NSData+CommonCrypto.m * AQToolkit * * Created by Jim Dovey on 31/8/2008. * * Copyright (c) 2008-2009, Jim Dovey * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of this project's author nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import <Foundation/Foundation.h> #import "NSData+CommonCrypto.h" #import <CommonCrypto/CommonDigest.h> #import <CommonCrypto/CommonCryptor.h> #import <CommonCrypto/CommonHMAC.h> NSString * const kCommonCryptoErrorDomain = @"CommonCryptoErrorDomain"; @implementation NSError (CommonCryptoErrorDomain) + (NSError *) errorWithCCCryptorStatus: (CCCryptorStatus) status { NSString * description = nil, * reason = nil; switch ( status ) { case kCCSuccess: description = NSLocalizedString(@"Success", @"Error description"); break; case kCCParamError: description = NSLocalizedString(@"Parameter Error", @"Error description"); reason = NSLocalizedString(@"Illegal parameter supplied to encryption/decryption algorithm", @"Error reason"); break; case kCCBufferTooSmall: description = NSLocalizedString(@"Buffer Too Small", @"Error description"); reason = NSLocalizedString(@"Insufficient buffer provided for specified operation", @"Error reason"); break; case kCCMemoryFailure: description = NSLocalizedString(@"Memory Failure", @"Error description"); reason = NSLocalizedString(@"Failed to allocate memory", @"Error reason"); break; case kCCAlignmentError: description = NSLocalizedString(@"Alignment Error", @"Error description"); reason = NSLocalizedString(@"Input size to encryption algorithm was not aligned correctly", @"Error reason"); break; case kCCDecodeError: description = NSLocalizedString(@"Decode Error", @"Error description"); reason = NSLocalizedString(@"Input data did not decode or decrypt correctly", @"Error reason"); break; case kCCUnimplemented: description = NSLocalizedString(@"Unimplemented Function", @"Error description"); reason = NSLocalizedString(@"Function not implemented for the current algorithm", @"Error reason"); break; default: description = NSLocalizedString(@"Unknown Error", @"Error description"); break; } NSMutableDictionary * userInfo = [[NSMutableDictionary alloc] init]; [userInfo setObject: description forKey: NSLocalizedDescriptionKey]; if ( reason != nil ) [userInfo setObject: reason forKey: NSLocalizedFailureReasonErrorKey]; NSError * result = [NSError errorWithDomain: kCommonCryptoErrorDomain code: status userInfo: userInfo]; #if !__has_feature(objc_arc) [userInfo release]; #endif return ( result ); } @end #pragma mark - @implementation NSData (CommonDigest) - (NSData *) MD2Sum { unsigned char hash[CC_MD2_DIGEST_LENGTH]; (void) CC_MD2( [self bytes], (CC_LONG)[self length], hash ); return ( [NSData dataWithBytes: hash length: CC_MD2_DIGEST_LENGTH] ); } - (NSData *) MD4Sum { unsigned char hash[CC_MD4_DIGEST_LENGTH]; (void) CC_MD4( [self bytes], (CC_LONG)[self length], hash ); return ( [NSData dataWithBytes: hash length: CC_MD4_DIGEST_LENGTH] ); } - (NSData *) MD5Sum { unsigned char hash[CC_MD5_DIGEST_LENGTH]; (void) CC_MD5( [self bytes], (CC_LONG)[self length], hash ); return ( [NSData dataWithBytes: hash length: CC_MD5_DIGEST_LENGTH] ); } - (NSData *) SHA1Hash { unsigned char hash[CC_SHA1_DIGEST_LENGTH]; (void) CC_SHA1( [self bytes], (CC_LONG)[self length], hash ); return ( [NSData dataWithBytes: hash length: CC_SHA1_DIGEST_LENGTH] ); } - (NSData *) SHA224Hash { unsigned char hash[CC_SHA224_DIGEST_LENGTH]; (void) CC_SHA224( [self bytes], (CC_LONG)[self length], hash ); return ( [NSData dataWithBytes: hash length: CC_SHA224_DIGEST_LENGTH] ); } - (NSData *) SHA256Hash { unsigned char hash[CC_SHA256_DIGEST_LENGTH]; (void) CC_SHA256( [self bytes], (CC_LONG)[self length], hash ); return ( [NSData dataWithBytes: hash length: CC_SHA256_DIGEST_LENGTH] ); } - (NSData *) SHA384Hash { unsigned char hash[CC_SHA384_DIGEST_LENGTH]; (void) CC_SHA384( [self bytes], (CC_LONG)[self length], hash ); return ( [NSData dataWithBytes: hash length: CC_SHA384_DIGEST_LENGTH] ); } - (NSData *) SHA512Hash { unsigned char hash[CC_SHA512_DIGEST_LENGTH]; (void) CC_SHA512( [self bytes], (CC_LONG)[self length], hash ); return ( [NSData dataWithBytes: hash length: CC_SHA512_DIGEST_LENGTH] ); } @end @implementation NSData (CommonCryptor) - (NSData *) AES256EncryptedDataUsingKey: (id) key error: (NSError **) error { CCCryptorStatus status = kCCSuccess; NSData * result = [self dataEncryptedUsingAlgorithm: kCCAlgorithmAES128 key: key options: kCCOptionPKCS7Padding error: &status]; if ( result != nil ) return ( result ); if ( error != NULL ) *error = [NSError errorWithCCCryptorStatus: status]; return ( nil ); } - (NSData *) decryptedAES256DataUsingKey: (id) key error: (NSError **) error { CCCryptorStatus status = kCCSuccess; NSData * result = [self decryptedDataUsingAlgorithm: kCCAlgorithmAES128 key: key options: kCCOptionPKCS7Padding error: &status]; if ( result != nil ) return ( result ); if ( error != NULL ) *error = [NSError errorWithCCCryptorStatus: status]; return ( nil ); } - (NSData *) DESEncryptedDataUsingKey: (id) key error: (NSError **) error { CCCryptorStatus status = kCCSuccess; NSData * result = [self dataEncryptedUsingAlgorithm: kCCAlgorithmDES key: key options: kCCOptionPKCS7Padding error: &status]; if ( result != nil ) return ( result ); if ( error != NULL ) *error = [NSError errorWithCCCryptorStatus: status]; return ( nil ); } - (NSData *) decryptedDESDataUsingKey: (id) key error: (NSError **) error { CCCryptorStatus status = kCCSuccess; NSData * result = [self decryptedDataUsingAlgorithm: kCCAlgorithmDES key: key options: kCCOptionPKCS7Padding error: &status]; if ( result != nil ) return ( result ); if ( error != NULL ) *error = [NSError errorWithCCCryptorStatus: status]; return ( nil ); } - (NSData *) CASTEncryptedDataUsingKey: (id) key error: (NSError **) error { CCCryptorStatus status = kCCSuccess; NSData * result = [self dataEncryptedUsingAlgorithm: kCCAlgorithmCAST key: key options: kCCOptionPKCS7Padding error: &status]; if ( result != nil ) return ( result ); if ( error != NULL ) *error = [NSError errorWithCCCryptorStatus: status]; return ( nil ); } - (NSData *) decryptedCASTDataUsingKey: (id) key error: (NSError **) error { CCCryptorStatus status = kCCSuccess; NSData * result = [self decryptedDataUsingAlgorithm: kCCAlgorithmCAST key: key options: kCCOptionPKCS7Padding error: &status]; if ( result != nil ) return ( result ); if ( error != NULL ) *error = [NSError errorWithCCCryptorStatus: status]; return ( nil ); } @end static void FixKeyLengths( CCAlgorithm algorithm, NSMutableData * keyData, NSMutableData * ivData ) { NSUInteger keyLength = [keyData length]; switch ( algorithm ) { case kCCAlgorithmAES128: { if ( keyLength < 16 ) { [keyData setLength: 16]; } else if ( keyLength < 24 ) { [keyData setLength: 24]; } else { [keyData setLength: 32]; } break; } case kCCAlgorithmDES: { [keyData setLength: 8]; break; } case kCCAlgorithm3DES: { [keyData setLength: 24]; break; } case kCCAlgorithmCAST: { if ( keyLength < 5 ) { [keyData setLength: 5]; } else if ( keyLength > 16 ) { [keyData setLength: 16]; } break; } case kCCAlgorithmRC4: { if ( keyLength > 512 ) [keyData setLength: 512]; break; } default: break; } [ivData setLength: [keyData length]]; } @implementation NSData (LowLevelCommonCryptor) - (NSData *) _runCryptor: (CCCryptorRef) cryptor result: (CCCryptorStatus *) status { size_t bufsize = CCCryptorGetOutputLength( cryptor, (size_t)[self length], true ); void * buf = malloc( bufsize ); size_t bufused = 0; size_t bytesTotal = 0; *status = CCCryptorUpdate( cryptor, [self bytes], (size_t)[self length], buf, bufsize, &bufused ); if ( *status != kCCSuccess ) { free( buf ); return ( nil ); } bytesTotal += bufused; // From Brent Royal-Gordon (Twitter: architechies): // Need to update buf ptr past used bytes when calling CCCryptorFinal() *status = CCCryptorFinal( cryptor, buf + bufused, bufsize - bufused, &bufused ); if ( *status != kCCSuccess ) { free( buf ); return ( nil ); } bytesTotal += bufused; return ( [NSData dataWithBytesNoCopy: buf length: bytesTotal] ); } - (NSData *) dataEncryptedUsingAlgorithm: (CCAlgorithm) algorithm key: (id) key error: (CCCryptorStatus *) error { return ( [self dataEncryptedUsingAlgorithm: algorithm key: key initializationVector: nil options: 0 error: error] ); } - (NSData *) dataEncryptedUsingAlgorithm: (CCAlgorithm) algorithm key: (id) key options: (CCOptions) options error: (CCCryptorStatus *) error { return ( [self dataEncryptedUsingAlgorithm: algorithm key: key initializationVector: nil options: options error: error] ); } - (NSData *) dataEncryptedUsingAlgorithm: (CCAlgorithm) algorithm key: (id) key initializationVector: (id) iv options: (CCOptions) options error: (CCCryptorStatus *) error { CCCryptorRef cryptor = NULL; CCCryptorStatus status = kCCSuccess; NSParameterAssert([key isKindOfClass: [NSData class]] || [key isKindOfClass: [NSString class]]); NSParameterAssert(iv == nil || [iv isKindOfClass: [NSData class]] || [iv isKindOfClass: [NSString class]]); NSMutableData * keyData, * ivData; if ( [key isKindOfClass: [NSData class]] ) keyData = (NSMutableData *) [key mutableCopy]; else keyData = [[key dataUsingEncoding: NSUTF8StringEncoding] mutableCopy]; if ( [iv isKindOfClass: [NSString class]] ) ivData = [[iv dataUsingEncoding: NSUTF8StringEncoding] mutableCopy]; else ivData = (NSMutableData *) [iv mutableCopy]; // data or nil #if !__has_feature(objc_arc) [keyData autorelease]; [ivData autorelease]; #endif // ensure correct lengths for key and iv data, based on algorithms FixKeyLengths( algorithm, keyData, ivData ); status = CCCryptorCreate( kCCEncrypt, algorithm, options, [keyData bytes], [keyData length], [ivData bytes], &cryptor ); if ( status != kCCSuccess ) { if ( error != NULL ) *error = status; return ( nil ); } NSData * result = [self _runCryptor: cryptor result: &status]; if ( (result == nil) && (error != NULL) ) *error = status; CCCryptorRelease( cryptor ); return ( result ); } - (NSData *) decryptedDataUsingAlgorithm: (CCAlgorithm) algorithm key: (id) key // data or string error: (CCCryptorStatus *) error { return ( [self decryptedDataUsingAlgorithm: algorithm key: key initializationVector: nil options: 0 error: error] ); } - (NSData *) decryptedDataUsingAlgorithm: (CCAlgorithm) algorithm key: (id) key // data or string options: (CCOptions) options error: (CCCryptorStatus *) error { return ( [self decryptedDataUsingAlgorithm: algorithm key: key initializationVector: nil options: options error: error] ); } - (NSData *) decryptedDataUsingAlgorithm: (CCAlgorithm) algorithm key: (id) key // data or string initializationVector: (id) iv // data or string options: (CCOptions) options error: (CCCryptorStatus *) error { CCCryptorRef cryptor = NULL; CCCryptorStatus status = kCCSuccess; NSParameterAssert([key isKindOfClass: [NSData class]] || [key isKindOfClass: [NSString class]]); NSParameterAssert(iv == nil || [iv isKindOfClass: [NSData class]] || [iv isKindOfClass: [NSString class]]); NSMutableData * keyData, * ivData; if ( [key isKindOfClass: [NSData class]] ) keyData = (NSMutableData *) [key mutableCopy]; else keyData = [[key dataUsingEncoding: NSUTF8StringEncoding] mutableCopy]; if ( [iv isKindOfClass: [NSString class]] ) ivData = [[iv dataUsingEncoding: NSUTF8StringEncoding] mutableCopy]; else ivData = (NSMutableData *) [iv mutableCopy]; // data or nil #if !__has_feature(objc_arc) [keyData autorelease]; [ivData autorelease]; #endif // ensure correct lengths for key and iv data, based on algorithms FixKeyLengths( algorithm, keyData, ivData ); status = CCCryptorCreate( kCCDecrypt, algorithm, options, [keyData bytes], [keyData length], [ivData bytes], &cryptor ); if ( status != kCCSuccess ) { if ( error != NULL ) *error = status; return ( nil ); } NSData * result = [self _runCryptor: cryptor result: &status]; if ( (result == nil) && (error != NULL) ) *error = status; CCCryptorRelease( cryptor ); return ( result ); } @end @implementation NSData (CommonHMAC) - (NSData *) HMACWithAlgorithm: (CCHmacAlgorithm) algorithm { return ( [self HMACWithAlgorithm: algorithm key: nil] ); } - (NSData *) HMACWithAlgorithm: (CCHmacAlgorithm) algorithm key: (id) key { NSParameterAssert(key == nil || [key isKindOfClass: [NSData class]] || [key isKindOfClass: [NSString class]]); NSData * keyData = nil; if ( [key isKindOfClass: [NSString class]] ) keyData = [key dataUsingEncoding: NSUTF8StringEncoding]; else keyData = (NSData *) key; // this could be either CC_SHA1_DIGEST_LENGTH or CC_MD5_DIGEST_LENGTH. SHA1 is larger. unsigned char buf[CC_SHA1_DIGEST_LENGTH]; CCHmac( algorithm, [keyData bytes], [keyData length], [self bytes], [self length], buf ); return ( [NSData dataWithBytes: buf length: (algorithm == kCCHmacAlgMD5 ? CC_MD5_DIGEST_LENGTH : CC_SHA1_DIGEST_LENGTH)] ); } @end
// // NSString+Base64.h // Gurpartap Singh // // Created by Gurpartap Singh on 06/05/12. // Copyright (c) 2012 Gurpartap Singh. All rights reserved. // #import <Foundation/NSString.h> @interface NSString (Base64Additions) + (NSString *)base64StringFromData:(NSData *)data length:(NSUInteger)length; @end
// // NSStringAdditions.m // Gurpartap Singh // // Created by Gurpartap Singh on 06/05/12. // Copyright (c) 2012 Gurpartap Singh. All rights reserved. // #import "NSString+Base64.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 (Base64Additions) + (NSString *)base64StringFromData: (NSData *)data length: (NSUInteger)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