Ray Zhang 12 роки тому
батько
коміт
e9965cb4b5

+ 37 - 0
Apex Mobile/Apex Mobile/AESCrypt.h

@@ -0,0 +1,37 @@
+//
+//  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

+ 50 - 0
Apex Mobile/Apex Mobile/AESCrypt.m

@@ -0,0 +1,50 @@
+//
+//  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

+ 22 - 0
Apex Mobile/Apex Mobile/LICENSE

@@ -0,0 +1,22 @@
+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.

+ 17 - 0
Apex Mobile/Apex Mobile/NSData+Base64.h

@@ -0,0 +1,17 @@
+//
+//  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

+ 110 - 0
Apex Mobile/Apex Mobile/NSData+Base64.m

@@ -0,0 +1,110 @@
+//
+//  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

+ 112 - 0
Apex Mobile/Apex Mobile/NSData+CommonCrypto.h

@@ -0,0 +1,112 @@
+/*
+ *  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

+ 546 - 0
Apex Mobile/Apex Mobile/NSData+CommonCrypto.m

@@ -0,0 +1,546 @@
+/*
+ *  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

+ 15 - 0
Apex Mobile/Apex Mobile/NSString+Base64.h

@@ -0,0 +1,15 @@
+//
+//  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

+ 82 - 0
Apex Mobile/Apex Mobile/NSString+Base64.m

@@ -0,0 +1,82 @@
+//
+//  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

+ 57 - 0
Apex Mobile/Apex Mobile/README.md

@@ -0,0 +1,57 @@
+# AESCrypt-ObjC - Simple AES encryption / decryption for iOS and OS X
+
+AESCrypt is a simple to use, opinionated AES encryption / decryption Objective-C class that just works.
+
+AESCrypt uses the AES-256-CBC cipher and encodes the encrypted data with base64.
+
+A corresponding gem to easily handle AES encryption / decryption in Ruby is available at http://github.com/Gurpartap/aescrypt.
+
+## Installation
+
+Add this line to your class:
+
+    #import "AESCrypt.h"
+
+## Usage
+
+    NSString *message = @"top secret message";
+    NSString *password = @"p4ssw0rd";
+
+Encrypting
+
+    NSString *encryptedData = [AESCrypt encrypt:message password:password];
+
+Decrypting
+
+    NSString *message = [AESCrypt decrypt:encryptedData password:password];
+
+## Common sense
+
+AESCrypt includes Base64 and Crypto extensions for NSData and NSString classes. If you're already using an extension that provides these, there is no need to use the included classes. Change the code in the AESCrypt class to correspond to your existing implementation of these extensions.
+
+## Corresponding usage in Ruby
+
+The AESCrypt Ruby gem, available at http://github.com/Gurpartap/aescrypt, understands what you're talking about in your Objective-C code. The purpose of the Ruby gem and Objective-C class is to have something that works out of the box across the server (Ruby) and client (Objective-C). However, a standard encryption technique is implemented, which ensures that you can handle the data with any AES compatible library available across the web. So, you're not locked-in.
+
+Here's how you would use the Ruby gem:
+
+    message = "top secret message"
+    password = "p4ssw0rd"
+
+Encrypting
+
+    encrypted_data = AESCrypt.encrypt(message, password)
+
+Decrypting
+
+    message = AESCrypt.decrypt(encrypted_data, password)
+
+See the Ruby gem README at http://github.com/Gurpartap/aescrypt for more details.
+
+## License
+
+NSData+CommonCrypto is Copyright (c) 2008-2009, Jim Dovey
+
+AESCrypt is Copyright (c) 2012 Gurpartap Singh
+
+See LICENSE for license terms.