├── CryptoCoding.podspec.json ├── CryptoCoding ├── CryptoCoding.h └── CryptoCoding.m ├── Examples └── TodoList │ ├── Classes │ ├── NewItemViewController.h │ ├── NewItemViewController.m │ ├── NewItemViewController.xib │ ├── TodoItem.h │ ├── TodoItem.m │ ├── TodoList.h │ ├── TodoList.m │ ├── TodoListAppDelegate.h │ ├── TodoListAppDelegate.m │ ├── TodoListViewController.h │ ├── TodoListViewController.m │ └── TodoListViewController.xib │ ├── CryptoToDoList-Info.plist │ ├── CryptoToDoList.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── xcshareddata │ │ └── xcschemes │ │ └── CryptoCoder.xcscheme │ ├── CryptoToDoList_Prefix.pch │ ├── Default-568h@2x.png │ ├── MainWindow.xib │ ├── TodoList.plist │ └── main.m ├── LICENCE.md └── README.md /CryptoCoding.podspec.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "CryptoCoding", 3 | "version": "1.1.1", 4 | "summary": "CryptoCoding is a superset of the NSCoding protocol that allows for simple, seamless encryption of any NSCoding-compatible object.", 5 | "homepage": "https://github.com/nicklockwood/CryptoCoding", 6 | "license": "zlib", 7 | "authors": "Nick Lockwood", 8 | "source": { 9 | "git": "https://github.com/nicklockwood/CryptoCoding.git", 10 | "tag": "1.1.1" 11 | }, 12 | "platforms": { 13 | "ios": "4.3", 14 | "osx": "10.6" 15 | }, 16 | "source_files": "CryptoCoding/CryptoCoding.{h,m}", 17 | "requires_arc": true 18 | } -------------------------------------------------------------------------------- /CryptoCoding/CryptoCoding.h: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoCoding.h 3 | // 4 | // Version 1.1.1 5 | // 6 | // Created by Nick Lockwood on 23/09/2012. 7 | // Copyright (c) 2011 Charcoal Design 8 | // 9 | // Distributed under the permissive zlib License 10 | // Get the latest version from here: 11 | // 12 | // https://github.com/nicklockwood/CryptoCoding 13 | // 14 | // This software is provided 'as-is', without any express or implied 15 | // warranty. In no event will the authors be held liable for any damages 16 | // arising from the use of this software. 17 | // 18 | // Permission is granted to anyone to use this software for any purpose, 19 | // including commercial applications, and to alter it and redistribute it 20 | // freely, subject to the following restrictions: 21 | // 22 | // 1. The origin of this software must not be misrepresented; you must not 23 | // claim that you wrote the original software. If you use this software 24 | // in a product, an acknowledgment in the product documentation would be 25 | // appreciated but is not required. 26 | // 27 | // 2. Altered source versions must be plainly marked as such, and must not be 28 | // misrepresented as being the original software. 29 | // 30 | // 3. This notice may not be removed or altered from any source distribution. 31 | // 32 | 33 | 34 | #import 35 | 36 | 37 | #pragma GCC diagnostic push 38 | #pragma GCC diagnostic ignored "-Wobjc-missing-property-synthesis" 39 | 40 | 41 | extern NSString *const CryptoCoderErrorDomain; 42 | extern NSString *const CryptoCoderException; 43 | 44 | 45 | extern const float CryptoCodingVersion; 46 | 47 | 48 | @interface NSData (CryptoCoding) 49 | 50 | - (NSData *)AESEncryptedDataWithPassword:(NSString *)password 51 | IV:(NSData **)IV 52 | salt:(NSData **)salt 53 | error:(NSError **)error 54 | version:(float)version; 55 | 56 | - (NSData *)AESDecryptedDataWithPassword:(NSString *)password 57 | IV:(NSData *)IV 58 | salt:(NSData *)salt 59 | error:(NSError **)error 60 | version:(float)version; 61 | @end 62 | 63 | 64 | @interface CryptoArchive : NSObject 65 | 66 | @property (nonatomic, strong, readonly) NSData *iv; 67 | @property (nonatomic, strong, readonly) NSData *salt; 68 | @property (nonatomic, strong, readonly) NSData *cypher; 69 | @property (nonatomic, strong, readonly) Class rootObjectClass; 70 | @property (nonatomic, assign, readonly) float version; 71 | 72 | - (instancetype)initWithRootObject:(id)rootObject password:(NSString *)password; 73 | - (id)unarchiveRootObjectWithPassword:(NSString *)password; 74 | 75 | @end 76 | 77 | 78 | @protocol CryptoCoding 79 | 80 | + (NSString *)CCPassword; 81 | 82 | @end 83 | 84 | 85 | @interface CryptoCoder : NSObject 86 | 87 | + (id)unarchiveObjectWithData:(NSData *)data; 88 | + (id)unarchiveObjectWithFile:(NSString *)path; 89 | + (NSData *)archivedDataWithRootObject:(id)rootObject; 90 | + (BOOL)archiveRootObject:(id)rootObject toFile:(NSString *)path; 91 | 92 | + (void)setClassName:(NSString *)codedName forClass:(Class)cls; 93 | + (NSString *)classNameForClass:(Class)cls; 94 | + (void)setClass:(Class)cls forClassName:(NSString *)codedName; 95 | + (Class)classForClassName:(NSString *)codedName; 96 | 97 | @end 98 | 99 | 100 | #pragma GCC diagnostic pop 101 | 102 | -------------------------------------------------------------------------------- /CryptoCoding/CryptoCoding.m: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoCoding.m 3 | // 4 | // Version 1.1.1 5 | // 6 | // Created by Nick Lockwood on 23/09/2012. 7 | // Copyright (c) 2011 Charcoal Design 8 | // 9 | // Distributed under the permissive zlib License 10 | // Get the latest version from here: 11 | // 12 | // https://github.com/nicklockwood/CryptoCoding 13 | // 14 | // This software is provided 'as-is', without any express or implied 15 | // warranty. In no event will the authors be held liable for any damages 16 | // arising from the use of this software. 17 | // 18 | // Permission is granted to anyone to use this software for any purpose, 19 | // including commercial applications, and to alter it and redistribute it 20 | // freely, subject to the following restrictions: 21 | // 22 | // 1. The origin of this software must not be misrepresented; you must not 23 | // claim that you wrote the original software. If you use this software 24 | // in a product, an acknowledgment in the product documentation would be 25 | // appreciated but is not required. 26 | // 27 | // 2. Altered source versions must be plainly marked as such, and must not be 28 | // misrepresented as being the original software. 29 | // 30 | // 3. This notice may not be removed or altered from any source distribution. 31 | // 32 | 33 | #import "CryptoCoding.h" 34 | #import 35 | #import 36 | 37 | 38 | #pragma clang diagnostic ignored "-Wobjc-missing-property-synthesis" 39 | #pragma clang diagnostic ignored "-Wnullable-to-nonnull-conversion" 40 | #pragma clang diagnostic ignored "-Wpartial-availability" 41 | #pragma clang diagnostic ignored "-Wdirect-ivar-access" 42 | #pragma clang diagnostic ignored "-Wdouble-promotion" 43 | #pragma clang diagnostic ignored "-Wfloat-conversion" 44 | #pragma clang diagnostic ignored "-Wgnu" 45 | 46 | 47 | #import 48 | #if !__has_feature(objc_arc) 49 | #error This class requires automatic reference counting 50 | #endif 51 | 52 | 53 | NSString *const CryptoCoderErrorDomain = @"CryptoCoderErrorDomain"; 54 | NSString *const CryptoCoderException = @"CryptoCoderException"; 55 | 56 | #if (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_5_0) || \ 57 | (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_7) 58 | 59 | const float CryptoCodingVersion = 1.0f; 60 | 61 | #else 62 | 63 | const float CryptoCodingVersion = 2.0f; 64 | 65 | #endif 66 | 67 | 68 | @implementation NSData (CryptoCoding) 69 | 70 | //based on blog post by Rob Napier: http://robnapier.net/blog/aes-commoncrypto-564 71 | 72 | + (NSData *)AESKeyWithPassword:(NSString *)password salt:(NSData *)salt error:(__autoreleasing NSError **)error version:(float)version 73 | { 74 | if ((version ?: CryptoCodingVersion) >= 2.0f) 75 | { 76 | 77 | #if (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_5_0) || \ 78 | (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_7) 79 | 80 | //generate key using CCKeyDerivationPBKDF 81 | NSMutableData *key = [NSMutableData dataWithLength:kCCKeySizeAES128]; 82 | int result = CCKeyDerivationPBKDF(kCCPBKDF2, // algorithm 83 | password.UTF8String, // password 84 | [password lengthOfBytesUsingEncoding:NSUTF8StringEncoding], // password length 85 | salt.bytes, // salt 86 | salt.length, // salt length 87 | kCCPRFHmacAlgSHA1, // PRF 88 | 1024, // rounds 89 | key.mutableBytes, // derived key 90 | key.length); // derived key length 91 | 92 | #else 93 | 94 | //CCKeyDerivationPBKDF is not available on iOS < 5 or Mac OS < 10.7 95 | NSMutableData *key = nil; 96 | int result = kCCUnimplemented; 97 | 98 | #endif 99 | 100 | if (result == kCCSuccess) 101 | { 102 | return key; 103 | } 104 | else 105 | { 106 | if (error) *error = [NSError errorWithDomain:CryptoCoderErrorDomain code:result userInfo:@{NSLocalizedDescriptionKey: @"Could not generate encryption key"}]; 107 | return nil; 108 | } 109 | } 110 | else 111 | { 112 | //use legacy key generation mechanism 113 | NSMutableData *key = [NSMutableData dataWithData:[password dataUsingEncoding:NSUTF8StringEncoding]]; 114 | [key appendData:salt]; 115 | key.length = MAX([key length], CC_MD5_DIGEST_LENGTH); 116 | for (NSInteger i = 0; i < 1024; i++) 117 | { 118 | CC_MD5(key.bytes, (CC_LONG)key.length, key.mutableBytes); 119 | [key setLength:CC_MD5_DIGEST_LENGTH]; 120 | } 121 | key.length = kCCKeySizeAES128; 122 | return key; 123 | } 124 | } 125 | 126 | - (NSData *)AESEncryptedDataWithPassword:(NSString *)password IV:(__autoreleasing NSData **)IV salt:(__autoreleasing NSData **)salt error:(__autoreleasing NSError **)error version:(float)version 127 | { 128 | //generate IV if not supplied 129 | if (*IV == nil) 130 | { 131 | *IV = [NSMutableData dataWithLength:kCCBlockSizeAES128]; 132 | if (SecRandomCopyBytes(kSecRandomDefault, kCCBlockSizeAES128, ((NSMutableData *)*IV).mutableBytes)) 133 | { 134 | if (error) *error = [NSError errorWithDomain:CryptoCoderErrorDomain code:errno userInfo:@{NSLocalizedDescriptionKey: @"Could not generate initialization vector value"}]; 135 | return nil; 136 | } 137 | } 138 | 139 | //generate salt if not supplied 140 | if (*salt == nil) 141 | { 142 | *salt = [NSMutableData dataWithLength:8]; 143 | if (SecRandomCopyBytes(kSecRandomDefault, [*salt length], ((NSMutableData *)*salt).mutableBytes)) 144 | { 145 | if (error) *error = [NSError errorWithDomain:CryptoCoderErrorDomain code:errno userInfo:@{NSLocalizedDescriptionKey: @"Could not generate salt value"}]; 146 | return nil; 147 | } 148 | } 149 | 150 | //generate key 151 | NSData *key = [NSData AESKeyWithPassword:password salt:*salt error:error version:version]; 152 | if (!key) return nil; 153 | 154 | //encrypt the data 155 | size_t length = 0; 156 | NSMutableData *cypher = [NSMutableData dataWithLength:self.length + kCCBlockSizeAES128]; 157 | CCCryptorStatus result = CCCrypt(kCCEncrypt, // operation 158 | kCCAlgorithmAES128, // algorithm 159 | kCCOptionPKCS7Padding, // options 160 | key.bytes, // key 161 | key.length, // key length 162 | (*IV).bytes, // iv 163 | self.bytes, // input 164 | self.length, // data length, 165 | cypher.mutableBytes, // ouput 166 | cypher.length, // output max length 167 | &length); // output length 168 | if (result == kCCSuccess) 169 | { 170 | cypher.length = length; 171 | } 172 | else 173 | { 174 | if (error) *error = [NSError errorWithDomain:CryptoCoderErrorDomain code:result userInfo:@{NSLocalizedDescriptionKey: @"Could not encrypt data"}]; 175 | return nil; 176 | } 177 | return cypher; 178 | } 179 | 180 | - (NSData *)AESDecryptedDataWithPassword:(NSString *)password IV:(NSData *)IV salt:(NSData *)salt error:(__autoreleasing NSError **)error version:(float)version 181 | { 182 | //generate key 183 | NSData *key = [NSData AESKeyWithPassword:password salt:salt error:error version:version]; 184 | 185 | //decrypt the data 186 | size_t length = 0; 187 | NSMutableData *cleartext = [NSMutableData dataWithLength:self.length + kCCBlockSizeAES128]; 188 | CCCryptorStatus result = CCCrypt(kCCDecrypt, // operation 189 | kCCAlgorithmAES128, // algorithm 190 | kCCOptionPKCS7Padding, // options 191 | key.bytes, // key 192 | key.length, // key length 193 | IV.bytes, // iv 194 | self.bytes, // input 195 | self.length, // data length, 196 | cleartext.mutableBytes, // ouput 197 | cleartext.length, // output max length 198 | &length); // output length 199 | if (result == kCCSuccess) 200 | { 201 | cleartext.length = length; 202 | } 203 | else 204 | { 205 | if (error) *error = [NSError errorWithDomain:CryptoCoderErrorDomain code:result userInfo:@{NSLocalizedDescriptionKey: @"Could not decrypt data"}]; 206 | return nil; 207 | } 208 | return cleartext; 209 | } 210 | 211 | @end 212 | 213 | 214 | @interface CryptoArchive () 215 | 216 | @property (nonatomic, strong) NSData *iv; 217 | @property (nonatomic, strong) NSData *salt; 218 | @property (nonatomic, strong) NSData *cypher; 219 | @property (nonatomic, strong) Class rootObjectClass; 220 | @property (nonatomic, assign) float version; 221 | 222 | @end 223 | 224 | 225 | @implementation CryptoArchive 226 | 227 | - (instancetype)initWithRootObject:(id)rootObject password:(NSString *)password 228 | { 229 | if ((self = [self init])) 230 | { 231 | NSData *iv = nil; 232 | NSData *salt = nil; 233 | NSData *data = [NSKeyedArchiver archivedDataWithRootObject:rootObject]; 234 | self.version = CryptoCodingVersion; 235 | self.rootObjectClass = [(NSObject *)rootObject classForCoder]; 236 | self.cypher = [data AESEncryptedDataWithPassword:password IV:&iv salt:&salt error:NULL version:CryptoCodingVersion]; 237 | self.salt = salt; 238 | self.iv = iv; 239 | } 240 | return self; 241 | } 242 | 243 | - (id)unarchiveRootObjectWithPassword:(NSString *)password 244 | { 245 | if (floor(_version) <= CryptoCodingVersion) 246 | { 247 | NSData *data = [_cypher AESDecryptedDataWithPassword:password IV:_iv salt:_salt error:NULL version:_version]; 248 | return [NSKeyedUnarchiver unarchiveObjectWithData:data]; 249 | } 250 | else 251 | { 252 | NSLog(@"Unsupported CryptoArchive version (%f)", _version); 253 | return nil; 254 | } 255 | } 256 | 257 | + (BOOL)supportsSecureCoding 258 | { 259 | return YES; 260 | } 261 | 262 | - (instancetype)initWithCoder:(NSCoder *)aDecoder 263 | { 264 | if ([aDecoder respondsToSelector:@selector(decodeObjectOfClass:forKey:)]) 265 | { 266 | //secure coding 267 | self.iv = [aDecoder decodeObjectOfClass:[NSData class] forKey:@"iv"]; 268 | self.salt = [aDecoder decodeObjectOfClass:[NSData class] forKey:@"salt"]; 269 | self.cypher = [aDecoder decodeObjectOfClass:[NSData class] forKey:@"cypher"]; 270 | self.rootObjectClass = NSClassFromString([aDecoder decodeObjectOfClass:[NSString class] forKey:@"className"]); 271 | self.version = [[aDecoder decodeObjectOfClass:[NSNumber class] forKey:@"version"] floatValue]; 272 | } 273 | else 274 | { 275 | //regular coding 276 | self.iv = [aDecoder decodeObjectForKey:@"iv"]; 277 | self.salt = [aDecoder decodeObjectForKey:@"salt"]; 278 | self.cypher = [aDecoder decodeObjectForKey:@"cypher"]; 279 | self.rootObjectClass = NSClassFromString([aDecoder decodeObjectForKey:@"className"]); 280 | self.version = [[aDecoder decodeObjectForKey:@"version"] floatValue]; 281 | } 282 | return self; 283 | } 284 | 285 | - (void)encodeWithCoder:(NSCoder *)aCoder 286 | { 287 | [aCoder encodeObject:_iv forKey:@"iv"]; 288 | [aCoder encodeObject:_salt forKey:@"salt"]; 289 | [aCoder encodeObject:_cypher forKey:@"cypher"]; 290 | [aCoder encodeObject:NSStringFromClass(_rootObjectClass) forKey:@"className"]; 291 | [aCoder encodeObject:@(_version) forKey:@"version"]; 292 | } 293 | 294 | - (id)copyWithZone:(NSZone *)zone 295 | { 296 | CryptoArchive *copy = [[CryptoArchive allocWithZone:zone] init]; 297 | copy.iv = _iv; 298 | copy.salt = _salt; 299 | copy.cypher = _cypher; 300 | copy.rootObjectClass = _rootObjectClass; 301 | copy.version = _version; 302 | return copy; 303 | } 304 | 305 | - (NSString *)description 306 | { 307 | return [NSString stringWithFormat:@"<%@: %p version=%g>", [self class], (void *)self, _version]; 308 | } 309 | 310 | @end 311 | 312 | 313 | @implementation CryptoCoder 314 | 315 | + (id)unarchiveObjectWithData:(NSData *)data 316 | { 317 | id object = data? [NSKeyedUnarchiver unarchiveObjectWithData:data]: nil; 318 | if ([object isKindOfClass:[CryptoArchive class]]) 319 | { 320 | CryptoArchive *archive = object; 321 | Class class = archive.rootObjectClass; 322 | if ([class respondsToSelector:@selector(CCPassword)]) 323 | { 324 | NSString *password = [class CCPassword]; 325 | object = [archive unarchiveRootObjectWithPassword:password]; 326 | } 327 | else 328 | { 329 | [NSException raise:CryptoCoderException format:@"%@ does not conform to the CryptoCoding protocol", class]; 330 | object = nil; 331 | } 332 | } 333 | return object; 334 | } 335 | 336 | + (id)unarchiveObjectWithFile:(NSString *)path 337 | { 338 | //load the file 339 | return [self unarchiveObjectWithData:[NSData dataWithContentsOfFile:path]]; 340 | } 341 | 342 | + (NSData *)archivedDataWithRootObject:(id)rootObject 343 | { 344 | Class class = [(NSObject *)rootObject classForCoder]; 345 | if ([class respondsToSelector:@selector(CCPassword)]) 346 | { 347 | NSString *password = [class CCPassword]; 348 | CryptoArchive *archive = [[CryptoArchive alloc] initWithRootObject:rootObject password:password]; 349 | return [NSKeyedArchiver archivedDataWithRootObject:archive]; 350 | } 351 | else 352 | { 353 | [NSException raise:CryptoCoderException format:@"%@ does not conform to the CryptoCoding protocol", class]; 354 | return nil; 355 | } 356 | } 357 | 358 | + (BOOL)archiveRootObject:(id)rootObject toFile:(NSString *)path 359 | { 360 | return [[self archivedDataWithRootObject:rootObject] writeToFile:path atomically:YES]; 361 | } 362 | 363 | + (void)setClassName:(NSString *)codedName forClass:(Class)cls 364 | { 365 | [NSKeyedArchiver setClassName:codedName forClass:cls]; 366 | } 367 | 368 | + (NSString *)classNameForClass:(Class)cls 369 | { 370 | return [NSKeyedArchiver classNameForClass:cls]; 371 | } 372 | 373 | + (void)setClass:(Class)cls forClassName:(NSString *)codedName 374 | { 375 | [NSKeyedUnarchiver setClass:cls forClassName:codedName]; 376 | } 377 | 378 | + (Class)classForClassName:(NSString *)codedName 379 | { 380 | return [NSKeyedUnarchiver classForClassName:codedName]; 381 | } 382 | 383 | @end 384 | -------------------------------------------------------------------------------- /Examples/TodoList/Classes/NewItemViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // NewItemViewController.h 3 | // TodoList 4 | // 5 | // Created by Nick Lockwood on 15/04/2010. 6 | // Copyright 2010 Charcoal Design. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class TodoItem; 12 | 13 | @interface NewItemViewController : UIViewController 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Examples/TodoList/Classes/NewItemViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // NewItemViewController.m 3 | // TodoList 4 | // 5 | // Created by Nick Lockwood on 15/04/2010. 6 | // Copyright 2010 Charcoal Design. All rights reserved. 7 | // 8 | 9 | #import "NewItemViewController.h" 10 | #import "TodoList.h" 11 | #import "TodoItem.h" 12 | 13 | @interface NewItemViewController() 14 | 15 | @property (nonatomic, strong) TodoItem *item; 16 | 17 | @end 18 | 19 | 20 | @implementation NewItemViewController 21 | 22 | @synthesize item = _item; 23 | 24 | #pragma mark - 25 | #pragma mark UITextViewDelegate methods 26 | 27 | - (void)textViewDidChange:(UITextView *)textView 28 | { 29 | if (self.item == nil) 30 | { 31 | //create a new TodoItem and add to list 32 | self.item = [TodoItem itemWithLabel:textView.text]; 33 | [[TodoList sharedList].items addObject:self.item]; 34 | } 35 | else 36 | { 37 | //update the TodoItem 38 | self.item.label = textView.text; 39 | } 40 | 41 | //save the TodoList 42 | [[TodoList sharedList] save]; 43 | } 44 | 45 | #pragma mark - 46 | #pragma mark Cleanup 47 | 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /Examples/TodoList/Classes/NewItemViewController.xib: -------------------------------------------------------------------------------- 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 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /Examples/TodoList/Classes/TodoItem.h: -------------------------------------------------------------------------------- 1 | // 2 | // TodoItem.h 3 | // TodoList 4 | // 5 | // Created by Nick Lockwood on 08/04/2010. 6 | // Copyright 2010 Charcoal Design. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface TodoItem : NSObject 13 | 14 | + (TodoItem *)itemWithLabel:(NSString *)label; 15 | 16 | @property (nonatomic, strong) NSString *label; 17 | @property (nonatomic, assign) BOOL checked; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Examples/TodoList/Classes/TodoItem.m: -------------------------------------------------------------------------------- 1 | // 2 | // TodoItem.m 3 | // TodoList 4 | // 5 | // Created by Nick Lockwood on 08/04/2010. 6 | // Copyright 2010 Charcoal Design. All rights reserved. 7 | // 8 | 9 | #import "TodoItem.h" 10 | 11 | 12 | @implementation TodoItem 13 | 14 | @synthesize label = _label, checked = _checked; 15 | 16 | + (TodoItem *)itemWithLabel:(NSString *)label 17 | { 18 | TodoItem *item = [[self alloc] init]; 19 | item.label = label; 20 | return item; 21 | } 22 | 23 | #pragma mark - 24 | #pragma mark NSCoding 25 | 26 | - (instancetype)initWithCoder:(NSCoder *)decoder 27 | { 28 | if ((self = [super init])) 29 | { 30 | self.label = [decoder decodeObjectForKey:@"label"]; 31 | self.checked = [[decoder decodeObjectForKey:@"checked"] boolValue]; 32 | } 33 | return self; 34 | } 35 | 36 | - (void)encodeWithCoder:(NSCoder *)encoder 37 | { 38 | [encoder encodeObject:self.label forKey:@"label"]; 39 | [encoder encodeObject:@(self.checked) forKey:@"checked"]; 40 | } 41 | 42 | #pragma mark - 43 | #pragma mark Cleanup 44 | 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /Examples/TodoList/Classes/TodoList.h: -------------------------------------------------------------------------------- 1 | // 2 | // TodoList.h 3 | // TodoList 4 | // 5 | // Created by Nick Lockwood on 15/04/2010. 6 | // Copyright 2010 Charcoal Design. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "CryptoCoding.h" 11 | 12 | 13 | @interface TodoList : NSObject 14 | 15 | @property (nonatomic, strong) NSMutableArray *items; 16 | 17 | + (TodoList *)sharedList; 18 | - (void)save; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /Examples/TodoList/Classes/TodoList.m: -------------------------------------------------------------------------------- 1 | // 2 | // TodoList.m 3 | // TodoList 4 | // 5 | // Created by Nick Lockwood on 15/04/2010. 6 | // Copyright 2010 Charcoal Design. All rights reserved. 7 | // 8 | 9 | #import "TodoList.h" 10 | #import "TodoItem.h" 11 | 12 | 13 | @implementation TodoList 14 | 15 | @synthesize items = _items; 16 | 17 | 18 | #pragma mark - 19 | #pragma mark Loading and saving 20 | 21 | + (NSString *)documentsDirectory 22 | { 23 | NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 24 | return paths[0]; 25 | } 26 | 27 | + (TodoList *)sharedList 28 | { 29 | static TodoList *sharedList = nil; 30 | if (sharedList == nil) 31 | { 32 | //attempt to load saved file 33 | NSString *path = [[self documentsDirectory] stringByAppendingPathComponent:@"TodoList.plist"]; 34 | sharedList = [CryptoCoder unarchiveObjectWithFile:path]; 35 | 36 | //if that fails, create new list 37 | if (sharedList == nil) 38 | { 39 | sharedList = [[TodoList alloc] init]; 40 | } 41 | } 42 | return sharedList; 43 | } 44 | 45 | - (instancetype)init 46 | { 47 | if ((self = [super init])) 48 | { 49 | //load default items 50 | _items = [[NSMutableArray alloc] init]; 51 | NSString *path = [[NSBundle mainBundle] pathForResource:@"TodoList" ofType:@"plist"]; 52 | for (NSString *label in [NSArray arrayWithContentsOfFile:path]) 53 | { 54 | [_items addObject:[TodoItem itemWithLabel:label]]; 55 | } 56 | } 57 | return self; 58 | } 59 | 60 | + (NSString *)CCPassword 61 | { 62 | //password 63 | return @"YsMXOHm2vsoIxTdSZWMILEVnQtgupefHGSROCLmwTnX3wBaCac"; 64 | } 65 | 66 | - (void)save 67 | { 68 | NSString *path = [[[self class] documentsDirectory] stringByAppendingPathComponent:@"TodoList.plist"]; 69 | [CryptoCoder archiveRootObject:self toFile:path]; 70 | } 71 | 72 | 73 | #pragma mark - 74 | #pragma mark NSCoding 75 | 76 | - (instancetype)initWithCoder:(NSCoder *)aDecoder 77 | { 78 | if ((self = [super init])) 79 | { 80 | self.items = [aDecoder decodeObjectForKey:@"items"]; 81 | } 82 | return self; 83 | } 84 | 85 | - (void)encodeWithCoder:(NSCoder *)aCoder 86 | { 87 | [aCoder encodeObject:self.items forKey:@"items"]; 88 | } 89 | 90 | 91 | #pragma mark - 92 | #pragma mark Cleanup 93 | 94 | 95 | @end 96 | -------------------------------------------------------------------------------- /Examples/TodoList/Classes/TodoListAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // TodoListAppDelegate.h 3 | // TodoList 4 | // 5 | // Created by Nick Lockwood on 08/04/2010. 6 | // Copyright Charcoal Design 2010. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TodoListAppDelegate : NSObject 12 | 13 | @property (nonatomic, strong) IBOutlet UIWindow *window; 14 | @property (nonatomic, strong) IBOutlet UINavigationController *viewController; 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /Examples/TodoList/Classes/TodoListAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // TodoListAppDelegate.m 3 | // TodoList 4 | // 5 | // Created by Nick Lockwood on 08/04/2010. 6 | // Copyright Charcoal Design 2010. All rights reserved. 7 | // 8 | 9 | #import "TodoListAppDelegate.h" 10 | #import "TodoListViewController.h" 11 | 12 | @implementation TodoListAppDelegate 13 | 14 | @synthesize window; 15 | @synthesize viewController; 16 | 17 | - (void)applicationDidFinishLaunching:(__unused UIApplication *)application 18 | { 19 | // Override point for customization after app launch 20 | self.window.rootViewController = self.viewController; 21 | [self.window makeKeyAndVisible]; 22 | } 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Examples/TodoList/Classes/TodoListViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TodoList1ViewController.h 3 | // TodoList1 4 | // 5 | // Created by Nick Lockwood on 08/04/2010. 6 | // Copyright Charcoal Design 2010. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TodoListViewController : UIViewController 12 | 13 | @property (nonatomic, strong) IBOutlet UITableView *tableView; 14 | 15 | - (IBAction)toggleEditing:(id)sender; 16 | - (IBAction)createNewItem; 17 | 18 | @end 19 | 20 | -------------------------------------------------------------------------------- /Examples/TodoList/Classes/TodoListViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // TodoListViewController.m 3 | // TodoList 4 | // 5 | // Created by Nick Lockwood on 08/04/2010. 6 | // Copyright Charcoal Design 2010. All rights reserved. 7 | // 8 | 9 | #import "TodoListViewController.h" 10 | #import "NewItemViewController.h" 11 | #import "TodoItem.h" 12 | #import "TodoList.h" 13 | 14 | 15 | @implementation TodoListViewController 16 | 17 | @synthesize tableView = _tableView; 18 | 19 | - (void)viewDidAppear:(BOOL)animated 20 | { 21 | [super viewDidAppear:animated]; 22 | [self.tableView reloadData]; 23 | } 24 | 25 | - (IBAction)toggleEditing:(id)sender 26 | { 27 | [self.tableView setEditing:!self.tableView.editing animated:YES]; 28 | [sender setTitle:(self.tableView.editing)? @"Done" : @"Edit"]; 29 | } 30 | 31 | - (IBAction)createNewItem 32 | { 33 | UIViewController *viewController = [[NewItemViewController alloc] init]; 34 | [self.navigationController pushViewController:viewController animated:YES]; 35 | } 36 | 37 | #pragma mark - 38 | #pragma mark UITableViewDelegate methods 39 | 40 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 41 | { 42 | TodoItem *item = [TodoList sharedList].items[(NSUInteger)indexPath.row]; 43 | item.checked = !item.checked; 44 | [[TodoList sharedList] save]; 45 | [tableView reloadData]; 46 | } 47 | 48 | - (UITableViewCellEditingStyle)tableView:(__unused UITableView *)tableView editingStyleForRowAtIndexPath:(__unused NSIndexPath *)indexPath 49 | { 50 | return UITableViewCellEditingStyleDelete; 51 | } 52 | 53 | - (void)tableView:(__unused UITableView *)_tableView commitEditingStyle:(__unused UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath 54 | { 55 | [[TodoList sharedList].items removeObjectAtIndex:(NSUInteger)indexPath.row]; 56 | [[TodoList sharedList] save]; 57 | [self.tableView reloadData]; 58 | } 59 | 60 | #pragma mark - 61 | #pragma mark UITableViewDataSource methods 62 | 63 | - (NSInteger)tableView:(__unused UITableView *)table numberOfRowsInSection:(__unused NSInteger)section 64 | { 65 | return (NSInteger)[[TodoList sharedList].items count]; 66 | } 67 | 68 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 69 | { 70 | static NSString *cellType = @"Cell"; 71 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellType]; 72 | if (cell == nil) 73 | { 74 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellType]; 75 | } 76 | 77 | TodoItem *item = ([TodoList sharedList].items)[(NSUInteger)indexPath.row]; 78 | cell.textLabel.text = item.label; 79 | if (item.checked) 80 | { 81 | cell.accessoryType = UITableViewCellAccessoryCheckmark; 82 | } 83 | else 84 | { 85 | cell.accessoryType = UITableViewCellAccessoryNone; 86 | } 87 | 88 | return cell; 89 | } 90 | 91 | @end 92 | -------------------------------------------------------------------------------- /Examples/TodoList/Classes/TodoListViewController.xib: -------------------------------------------------------------------------------- 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 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /Examples/TodoList/CryptoToDoList-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIconFile 12 | 13 | CFBundleIdentifier 14 | $(PRODUCT_BUNDLE_IDENTIFIER) 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundleName 18 | ${PRODUCT_NAME} 19 | CFBundlePackageType 20 | APPL 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | NSMainNibFile 28 | MainWindow 29 | 30 | 31 | -------------------------------------------------------------------------------- /Examples/TodoList/CryptoToDoList.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 012EAFC4116E25680023862F /* TodoItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 012EAFC3116E25680023862F /* TodoItem.m */; }; 11 | 01457AEB117723E2005BBF82 /* NewItemViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 01457AE9117723E2005BBF82 /* NewItemViewController.m */; }; 12 | 01457AEC117723E2005BBF82 /* NewItemViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 01457AEA117723E2005BBF82 /* NewItemViewController.xib */; }; 13 | 01457AF2117724D1005BBF82 /* TodoList.m in Sources */ = {isa = PBXBuildFile; fileRef = 01457AF1117724D1005BBF82 /* TodoList.m */; }; 14 | 01CDB16D160F53E800B929AD /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 01CDB16C160F53E800B929AD /* Default-568h@2x.png */; }; 15 | 01CDB173160F5D4400B929AD /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 01CDB172160F5D4400B929AD /* Security.framework */; }; 16 | 01CDB1E516112B0100B929AD /* CryptoCoding.m in Sources */ = {isa = PBXBuildFile; fileRef = 01CDB1E416112B0100B929AD /* CryptoCoding.m */; }; 17 | 1D3623260D0F684500981E51 /* TodoListAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D3623250D0F684500981E51 /* TodoListAppDelegate.m */; }; 18 | 1D60589B0D05DD56006BFB54 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; }; 19 | 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; 20 | 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; 21 | 288765A50DF7441C002DB57D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765A40DF7441C002DB57D /* CoreGraphics.framework */; }; 22 | 28AD733F0D9D9553002E5188 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28AD733E0D9D9553002E5188 /* MainWindow.xib */; }; 23 | 28D7ACF80DDB3853001CB0EB /* TodoListViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 28D7ACF70DDB3853001CB0EB /* TodoListViewController.m */; }; 24 | B2E4C05B155145E600219D16 /* TodoListViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = B2E4C05A155145E600219D16 /* TodoListViewController.xib */; }; 25 | B2E4C066155149FF00219D16 /* TodoList.plist in Resources */ = {isa = PBXBuildFile; fileRef = B2E4C065155149FF00219D16 /* TodoList.plist */; }; 26 | /* End PBXBuildFile section */ 27 | 28 | /* Begin PBXFileReference section */ 29 | 012EAFC2116E25680023862F /* TodoItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TodoItem.h; sourceTree = ""; }; 30 | 012EAFC3116E25680023862F /* TodoItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TodoItem.m; sourceTree = ""; }; 31 | 01457AE8117723E2005BBF82 /* NewItemViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NewItemViewController.h; sourceTree = ""; }; 32 | 01457AE9117723E2005BBF82 /* NewItemViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NewItemViewController.m; sourceTree = ""; }; 33 | 01457AEA117723E2005BBF82 /* NewItemViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = NewItemViewController.xib; path = Classes/NewItemViewController.xib; sourceTree = ""; }; 34 | 01457AF0117724D1005BBF82 /* TodoList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TodoList.h; sourceTree = ""; }; 35 | 01457AF1117724D1005BBF82 /* TodoList.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TodoList.m; sourceTree = ""; }; 36 | 01CDB16C160F53E800B929AD /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; 37 | 01CDB172160F5D4400B929AD /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; 38 | 01CDB1E316112B0100B929AD /* CryptoCoding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CryptoCoding.h; sourceTree = ""; }; 39 | 01CDB1E416112B0100B929AD /* CryptoCoding.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CryptoCoding.m; sourceTree = ""; }; 40 | 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 41 | 1D3623240D0F684500981E51 /* TodoListAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TodoListAppDelegate.h; sourceTree = ""; }; 42 | 1D3623250D0F684500981E51 /* TodoListAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TodoListAppDelegate.m; sourceTree = ""; }; 43 | 1D6058910D05DD3D006BFB54 /* CryptoToDoList.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CryptoToDoList.app; sourceTree = BUILT_PRODUCTS_DIR; }; 44 | 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 45 | 288765A40DF7441C002DB57D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 46 | 28AD733E0D9D9553002E5188 /* MainWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainWindow.xib; sourceTree = ""; }; 47 | 28D7ACF60DDB3853001CB0EB /* TodoListViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TodoListViewController.h; sourceTree = ""; }; 48 | 28D7ACF70DDB3853001CB0EB /* TodoListViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TodoListViewController.m; sourceTree = ""; }; 49 | 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 50 | 32CA4F630368D1EE00C91783 /* CryptoToDoList_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CryptoToDoList_Prefix.pch; sourceTree = ""; }; 51 | 8D1107310486CEB800E47090 /* CryptoToDoList-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "CryptoToDoList-Info.plist"; plistStructureDefinitionIdentifier = "com.apple.xcode.plist.structure-definition.iphone.info-plist"; sourceTree = ""; }; 52 | B2E4C05A155145E600219D16 /* TodoListViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = TodoListViewController.xib; path = Classes/TodoListViewController.xib; sourceTree = ""; }; 53 | B2E4C065155149FF00219D16 /* TodoList.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = TodoList.plist; sourceTree = ""; }; 54 | /* End PBXFileReference section */ 55 | 56 | /* Begin PBXFrameworksBuildPhase section */ 57 | 1D60588F0D05DD3D006BFB54 /* Frameworks */ = { 58 | isa = PBXFrameworksBuildPhase; 59 | buildActionMask = 2147483647; 60 | files = ( 61 | 01CDB173160F5D4400B929AD /* Security.framework in Frameworks */, 62 | 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */, 63 | 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */, 64 | 288765A50DF7441C002DB57D /* CoreGraphics.framework in Frameworks */, 65 | ); 66 | runOnlyForDeploymentPostprocessing = 0; 67 | }; 68 | /* End PBXFrameworksBuildPhase section */ 69 | 70 | /* Begin PBXGroup section */ 71 | 01457AF311772690005BBF82 /* View Controllers */ = { 72 | isa = PBXGroup; 73 | children = ( 74 | 1D3623240D0F684500981E51 /* TodoListAppDelegate.h */, 75 | 1D3623250D0F684500981E51 /* TodoListAppDelegate.m */, 76 | 28D7ACF60DDB3853001CB0EB /* TodoListViewController.h */, 77 | 28D7ACF70DDB3853001CB0EB /* TodoListViewController.m */, 78 | 01457AE8117723E2005BBF82 /* NewItemViewController.h */, 79 | 01457AE9117723E2005BBF82 /* NewItemViewController.m */, 80 | ); 81 | name = "View Controllers"; 82 | sourceTree = ""; 83 | }; 84 | 01457AF41177269B005BBF82 /* Model */ = { 85 | isa = PBXGroup; 86 | children = ( 87 | 012EAFC2116E25680023862F /* TodoItem.h */, 88 | 012EAFC3116E25680023862F /* TodoItem.m */, 89 | 01457AF0117724D1005BBF82 /* TodoList.h */, 90 | 01457AF1117724D1005BBF82 /* TodoList.m */, 91 | ); 92 | name = Model; 93 | sourceTree = ""; 94 | }; 95 | 01CDB1E216112B0100B929AD /* CryptoCoding */ = { 96 | isa = PBXGroup; 97 | children = ( 98 | 01CDB1E316112B0100B929AD /* CryptoCoding.h */, 99 | 01CDB1E416112B0100B929AD /* CryptoCoding.m */, 100 | ); 101 | name = CryptoCoding; 102 | path = ../../CryptoCoding; 103 | sourceTree = ""; 104 | }; 105 | 080E96DDFE201D6D7F000001 /* Classes */ = { 106 | isa = PBXGroup; 107 | children = ( 108 | 01457AF311772690005BBF82 /* View Controllers */, 109 | 01457AF41177269B005BBF82 /* Model */, 110 | ); 111 | path = Classes; 112 | sourceTree = ""; 113 | }; 114 | 19C28FACFE9D520D11CA2CBB /* Products */ = { 115 | isa = PBXGroup; 116 | children = ( 117 | 1D6058910D05DD3D006BFB54 /* CryptoToDoList.app */, 118 | ); 119 | name = Products; 120 | sourceTree = ""; 121 | }; 122 | 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = { 123 | isa = PBXGroup; 124 | children = ( 125 | 01CDB1E216112B0100B929AD /* CryptoCoding */, 126 | 080E96DDFE201D6D7F000001 /* Classes */, 127 | 29B97315FDCFA39411CA2CEA /* Other Sources */, 128 | 29B97317FDCFA39411CA2CEA /* Resources */, 129 | 29B97323FDCFA39411CA2CEA /* Frameworks */, 130 | 19C28FACFE9D520D11CA2CBB /* Products */, 131 | ); 132 | name = CustomTemplate; 133 | sourceTree = ""; 134 | }; 135 | 29B97315FDCFA39411CA2CEA /* Other Sources */ = { 136 | isa = PBXGroup; 137 | children = ( 138 | 32CA4F630368D1EE00C91783 /* CryptoToDoList_Prefix.pch */, 139 | 29B97316FDCFA39411CA2CEA /* main.m */, 140 | ); 141 | name = "Other Sources"; 142 | sourceTree = ""; 143 | }; 144 | 29B97317FDCFA39411CA2CEA /* Resources */ = { 145 | isa = PBXGroup; 146 | children = ( 147 | 01CDB16C160F53E800B929AD /* Default-568h@2x.png */, 148 | B2E4C05A155145E600219D16 /* TodoListViewController.xib */, 149 | 01457AEA117723E2005BBF82 /* NewItemViewController.xib */, 150 | 28AD733E0D9D9553002E5188 /* MainWindow.xib */, 151 | 8D1107310486CEB800E47090 /* CryptoToDoList-Info.plist */, 152 | B2E4C065155149FF00219D16 /* TodoList.plist */, 153 | ); 154 | name = Resources; 155 | sourceTree = ""; 156 | }; 157 | 29B97323FDCFA39411CA2CEA /* Frameworks */ = { 158 | isa = PBXGroup; 159 | children = ( 160 | 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */, 161 | 1D30AB110D05D00D00671497 /* Foundation.framework */, 162 | 288765A40DF7441C002DB57D /* CoreGraphics.framework */, 163 | 01CDB172160F5D4400B929AD /* Security.framework */, 164 | ); 165 | name = Frameworks; 166 | sourceTree = ""; 167 | }; 168 | /* End PBXGroup section */ 169 | 170 | /* Begin PBXNativeTarget section */ 171 | 1D6058900D05DD3D006BFB54 /* CryptoCoder */ = { 172 | isa = PBXNativeTarget; 173 | buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "CryptoCoder" */; 174 | buildPhases = ( 175 | 1D60588D0D05DD3D006BFB54 /* Resources */, 176 | 1D60588E0D05DD3D006BFB54 /* Sources */, 177 | 1D60588F0D05DD3D006BFB54 /* Frameworks */, 178 | ); 179 | buildRules = ( 180 | ); 181 | dependencies = ( 182 | ); 183 | name = CryptoCoder; 184 | productName = HRTodoList; 185 | productReference = 1D6058910D05DD3D006BFB54 /* CryptoToDoList.app */; 186 | productType = "com.apple.product-type.application"; 187 | }; 188 | /* End PBXNativeTarget section */ 189 | 190 | /* Begin PBXProject section */ 191 | 29B97313FDCFA39411CA2CEA /* Project object */ = { 192 | isa = PBXProject; 193 | attributes = { 194 | LastUpgradeCheck = 0900; 195 | }; 196 | buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "CryptoToDoList" */; 197 | compatibilityVersion = "Xcode 3.2"; 198 | developmentRegion = English; 199 | hasScannedForEncodings = 1; 200 | knownRegions = ( 201 | English, 202 | Japanese, 203 | French, 204 | German, 205 | ); 206 | mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; 207 | projectDirPath = ""; 208 | projectRoot = ""; 209 | targets = ( 210 | 1D6058900D05DD3D006BFB54 /* CryptoCoder */, 211 | ); 212 | }; 213 | /* End PBXProject section */ 214 | 215 | /* Begin PBXResourcesBuildPhase section */ 216 | 1D60588D0D05DD3D006BFB54 /* Resources */ = { 217 | isa = PBXResourcesBuildPhase; 218 | buildActionMask = 2147483647; 219 | files = ( 220 | 28AD733F0D9D9553002E5188 /* MainWindow.xib in Resources */, 221 | 01457AEC117723E2005BBF82 /* NewItemViewController.xib in Resources */, 222 | B2E4C05B155145E600219D16 /* TodoListViewController.xib in Resources */, 223 | B2E4C066155149FF00219D16 /* TodoList.plist in Resources */, 224 | 01CDB16D160F53E800B929AD /* Default-568h@2x.png in Resources */, 225 | ); 226 | runOnlyForDeploymentPostprocessing = 0; 227 | }; 228 | /* End PBXResourcesBuildPhase section */ 229 | 230 | /* Begin PBXSourcesBuildPhase section */ 231 | 1D60588E0D05DD3D006BFB54 /* Sources */ = { 232 | isa = PBXSourcesBuildPhase; 233 | buildActionMask = 2147483647; 234 | files = ( 235 | 1D60589B0D05DD56006BFB54 /* main.m in Sources */, 236 | 1D3623260D0F684500981E51 /* TodoListAppDelegate.m in Sources */, 237 | 28D7ACF80DDB3853001CB0EB /* TodoListViewController.m in Sources */, 238 | 012EAFC4116E25680023862F /* TodoItem.m in Sources */, 239 | 01457AEB117723E2005BBF82 /* NewItemViewController.m in Sources */, 240 | 01457AF2117724D1005BBF82 /* TodoList.m in Sources */, 241 | 01CDB1E516112B0100B929AD /* CryptoCoding.m in Sources */, 242 | ); 243 | runOnlyForDeploymentPostprocessing = 0; 244 | }; 245 | /* End PBXSourcesBuildPhase section */ 246 | 247 | /* Begin XCBuildConfiguration section */ 248 | 1D6058940D05DD3E006BFB54 /* Debug */ = { 249 | isa = XCBuildConfiguration; 250 | buildSettings = { 251 | ALWAYS_SEARCH_USER_PATHS = NO; 252 | CLANG_ENABLE_OBJC_ARC = YES; 253 | COPY_PHASE_STRIP = NO; 254 | GCC_DYNAMIC_NO_PIC = NO; 255 | GCC_OPTIMIZATION_LEVEL = 0; 256 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 257 | GCC_PREFIX_HEADER = CryptoToDoList_Prefix.pch; 258 | INFOPLIST_FILE = "CryptoToDoList-Info.plist"; 259 | PRODUCT_BUNDLE_IDENTIFIER = "com.yourcompany.${PRODUCT_NAME:rfc1034identifier}"; 260 | PRODUCT_NAME = CryptoToDoList; 261 | SDKROOT = iphoneos; 262 | }; 263 | name = Debug; 264 | }; 265 | 1D6058950D05DD3E006BFB54 /* Release */ = { 266 | isa = XCBuildConfiguration; 267 | buildSettings = { 268 | ALWAYS_SEARCH_USER_PATHS = NO; 269 | CLANG_ENABLE_OBJC_ARC = YES; 270 | COPY_PHASE_STRIP = YES; 271 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 272 | GCC_PREFIX_HEADER = CryptoToDoList_Prefix.pch; 273 | INFOPLIST_FILE = "CryptoToDoList-Info.plist"; 274 | PRODUCT_BUNDLE_IDENTIFIER = "com.yourcompany.${PRODUCT_NAME:rfc1034identifier}"; 275 | PRODUCT_NAME = CryptoToDoList; 276 | SDKROOT = iphoneos; 277 | }; 278 | name = Release; 279 | }; 280 | C01FCF4F08A954540054247B /* Debug */ = { 281 | isa = XCBuildConfiguration; 282 | buildSettings = { 283 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 284 | CLANG_WARN_ASSIGN_ENUM = YES; 285 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 286 | CLANG_WARN_COMMA = YES; 287 | CLANG_WARN_CXX0X_EXTENSIONS = YES; 288 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 289 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 290 | CLANG_WARN_EMPTY_BODY = YES; 291 | CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES; 292 | CLANG_WARN_INFINITE_RECURSION = YES; 293 | CLANG_WARN_OBJC_EXPLICIT_OWNERSHIP_TYPE = YES; 294 | CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES; 295 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 296 | CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = YES; 297 | CLANG_WARN_OBJC_RECEIVER_WEAK = YES; 298 | CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES; 299 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 300 | CLANG_WARN_STRICT_PROTOTYPES = YES; 301 | CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; 302 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 303 | CLANG_WARN_UNREACHABLE_CODE = YES; 304 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 305 | CLANG_WARN__EXIT_TIME_DESTRUCTORS = YES; 306 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 307 | ENABLE_STRICT_OBJC_MSGSEND = YES; 308 | ENABLE_TESTABILITY = YES; 309 | GCC_C_LANGUAGE_STANDARD = c99; 310 | GCC_NO_COMMON_BLOCKS = YES; 311 | GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; 312 | GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES; 313 | GCC_TREAT_WARNINGS_AS_ERRORS = YES; 314 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 315 | GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; 316 | GCC_WARN_ABOUT_MISSING_NEWLINE = YES; 317 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 318 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 319 | GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES; 320 | GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES; 321 | GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; 322 | GCC_WARN_MULTIPLE_DEFINITION_TYPES_FOR_SELECTOR = YES; 323 | GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES; 324 | GCC_WARN_PEDANTIC = YES; 325 | GCC_WARN_SHADOW = YES; 326 | GCC_WARN_SIGN_COMPARE = YES; 327 | GCC_WARN_STRICT_SELECTOR_MATCH = YES; 328 | GCC_WARN_UNDECLARED_SELECTOR = YES; 329 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 330 | GCC_WARN_UNKNOWN_PRAGMAS = YES; 331 | GCC_WARN_UNUSED_FUNCTION = YES; 332 | GCC_WARN_UNUSED_LABEL = YES; 333 | GCC_WARN_UNUSED_PARAMETER = YES; 334 | GCC_WARN_UNUSED_VARIABLE = YES; 335 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 336 | ONLY_ACTIVE_ARCH = YES; 337 | SDKROOT = iphoneos; 338 | WARNING_CFLAGS = ( 339 | "-Weverything", 340 | "-Wno-partial-availability", 341 | ); 342 | }; 343 | name = Debug; 344 | }; 345 | C01FCF5008A954540054247B /* Release */ = { 346 | isa = XCBuildConfiguration; 347 | buildSettings = { 348 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 349 | CLANG_WARN_ASSIGN_ENUM = YES; 350 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 351 | CLANG_WARN_COMMA = YES; 352 | CLANG_WARN_CXX0X_EXTENSIONS = YES; 353 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 354 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 355 | CLANG_WARN_EMPTY_BODY = YES; 356 | CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES; 357 | CLANG_WARN_INFINITE_RECURSION = YES; 358 | CLANG_WARN_OBJC_EXPLICIT_OWNERSHIP_TYPE = YES; 359 | CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES; 360 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 361 | CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = YES; 362 | CLANG_WARN_OBJC_RECEIVER_WEAK = YES; 363 | CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES; 364 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 365 | CLANG_WARN_STRICT_PROTOTYPES = YES; 366 | CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; 367 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 368 | CLANG_WARN_UNREACHABLE_CODE = YES; 369 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 370 | CLANG_WARN__EXIT_TIME_DESTRUCTORS = YES; 371 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 372 | ENABLE_STRICT_OBJC_MSGSEND = YES; 373 | GCC_C_LANGUAGE_STANDARD = c99; 374 | GCC_NO_COMMON_BLOCKS = YES; 375 | GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; 376 | GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES; 377 | GCC_TREAT_WARNINGS_AS_ERRORS = YES; 378 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 379 | GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; 380 | GCC_WARN_ABOUT_MISSING_NEWLINE = YES; 381 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 382 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 383 | GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES; 384 | GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES; 385 | GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; 386 | GCC_WARN_MULTIPLE_DEFINITION_TYPES_FOR_SELECTOR = YES; 387 | GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES; 388 | GCC_WARN_PEDANTIC = YES; 389 | GCC_WARN_SHADOW = YES; 390 | GCC_WARN_SIGN_COMPARE = YES; 391 | GCC_WARN_STRICT_SELECTOR_MATCH = YES; 392 | GCC_WARN_UNDECLARED_SELECTOR = YES; 393 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 394 | GCC_WARN_UNKNOWN_PRAGMAS = YES; 395 | GCC_WARN_UNUSED_FUNCTION = YES; 396 | GCC_WARN_UNUSED_LABEL = YES; 397 | GCC_WARN_UNUSED_PARAMETER = YES; 398 | GCC_WARN_UNUSED_VARIABLE = YES; 399 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 400 | SDKROOT = iphoneos; 401 | WARNING_CFLAGS = ( 402 | "-Weverything", 403 | "-Wno-partial-availability", 404 | ); 405 | }; 406 | name = Release; 407 | }; 408 | /* End XCBuildConfiguration section */ 409 | 410 | /* Begin XCConfigurationList section */ 411 | 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "CryptoCoder" */ = { 412 | isa = XCConfigurationList; 413 | buildConfigurations = ( 414 | 1D6058940D05DD3E006BFB54 /* Debug */, 415 | 1D6058950D05DD3E006BFB54 /* Release */, 416 | ); 417 | defaultConfigurationIsVisible = 0; 418 | defaultConfigurationName = Release; 419 | }; 420 | C01FCF4E08A954540054247B /* Build configuration list for PBXProject "CryptoToDoList" */ = { 421 | isa = XCConfigurationList; 422 | buildConfigurations = ( 423 | C01FCF4F08A954540054247B /* Debug */, 424 | C01FCF5008A954540054247B /* Release */, 425 | ); 426 | defaultConfigurationIsVisible = 0; 427 | defaultConfigurationName = Release; 428 | }; 429 | /* End XCConfigurationList section */ 430 | }; 431 | rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; 432 | } 433 | -------------------------------------------------------------------------------- /Examples/TodoList/CryptoToDoList.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Examples/TodoList/CryptoToDoList.xcodeproj/xcshareddata/xcschemes/CryptoCoder.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 33 | 34 | 40 | 41 | 42 | 43 | 44 | 45 | 56 | 58 | 64 | 65 | 66 | 67 | 68 | 69 | 75 | 77 | 83 | 84 | 85 | 86 | 88 | 89 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /Examples/TodoList/CryptoToDoList_Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'TodoList1' target in the 'TodoList1' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #import 8 | #endif 9 | -------------------------------------------------------------------------------- /Examples/TodoList/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nicklockwood/CryptoCoding/9821a8b0079cf954f041f0e866475f4500037074/Examples/TodoList/Default-568h@2x.png -------------------------------------------------------------------------------- /Examples/TodoList/MainWindow.xib: -------------------------------------------------------------------------------- 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 | 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 | 52 | -------------------------------------------------------------------------------- /Examples/TodoList/TodoList.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Do washing 6 | Mow lawn 7 | Write an open source library 8 | Feed the cat 9 | 10 | 11 | -------------------------------------------------------------------------------- /Examples/TodoList/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // TodoList 4 | // 5 | // Created by Nick Lockwood on 08/04/2010. 6 | // Copyright AKQA 2010. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | @autoreleasepool { 14 | int retVal = UIApplicationMain(argc, argv, nil, nil); 15 | return retVal; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /LICENCE.md: -------------------------------------------------------------------------------- 1 | CryptoCoding 2 | 3 | Copyright (C) 2012 Charcoal Design 4 | 5 | This software is provided 'as-is', without any express or implied 6 | warranty. In no event will the authors be held liable for any damages 7 | arising from the use of this software. 8 | 9 | Permission is granted to anyone to use this software for any purpose, 10 | including commercial applications, and to alter it and redistribute it 11 | freely, subject to the following restrictions: 12 | 13 | 1. The origin of this software must not be misrepresented; you must not 14 | claim that you wrote the original software. If you use this software 15 | in a product, an acknowledgment in the product documentation would be 16 | appreciated but is not required. 17 | 18 | 2. Altered source versions must be plainly marked as such, and must not be 19 | misrepresented as being the original software. 20 | 21 | 3. This notice may not be removed or altered from any source distribution. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Purpose 2 | -------------- 3 | 4 | CryptoCoding is a superset of the NSCoding protocol that allows for simple, seamless encryption of any NSCoding-compatible object. 5 | 6 | CryptoCoding is designed to work with the AutoCoding library (https://github.com/nicklockwood/AutoCoding), which can automatically write the `initWithCoder:` and `encodeWithCoder:` methods for your classes. 7 | 8 | CryptoCoding is also designed to work hand-in-hand with the BaseModel library (https://github.com/nicklockwood/BaseModel) which forms the basis for building a powerful model hierarchy for your project with minimal effort. Check the *CryptoTodoList* example included in the BaseModel repository for an example of how these libraries can work together. 9 | 10 | 11 | Supported OS & SDK Versions 12 | ----------------------------- 13 | 14 | * Supported build target - iOS 11.0 / Mac OS 10.12 (Xcode 9.0) 15 | * Earliest supported deployment target - iOS 9.0 / Mac OS 10.10 16 | * Earliest compatible deployment target - iOS 4.0 / Mac OS 10.7 17 | 18 | NOTE: 'Supported' means that the library has been tested with this version. 'Compatible' means that the library should work on this OS version (i.e. it doesn't rely on any unavailable SDK features) but is no longer being tested for compatibility and may require tweaking or bug fixes to run correctly. 19 | 20 | 21 | ARC Compatibility 22 | ------------------ 23 | 24 | As of version 1.0.2, CryptoCoding requires ARC. If you wish to use CryptoCoding in a non-ARC project, just add the -fobjc-arc compiler flag to the CryptoCoding.m file. To do this, go to the Build Phases tab in your target settings, open the Compile Sources group, double-click CryptoCoding.m in the list and type -fobjc-arc into the popover. 25 | 26 | If you wish to convert your whole project to CryptoCoding, comment out the #error line in CryptoCoding.m, then run the Edit > Refactor > Convert to Objective-C ARC... tool in Xcode and make sure all files that you wish to use ARC for (including CryptoCoding.m) are checked. 27 | 28 | 29 | Thread Safety 30 | -------------- 31 | 32 | CryptoCoding is fully thread-safe. 33 | 34 | 35 | Installation 36 | -------------- 37 | 38 | To use CryptoCoding, just drag the CryptoCoding class files into your project and add the Apple Security framework. 39 | 40 | 41 | Usage 42 | -------------- 43 | 44 | The simplest way to use CryptoCoding is as follows: 45 | 46 | 1) Add NSCoding to your classes as normal, either by manually adding the `initWithCoder:` and `encodeWithCoder:` methods manually, or by using the AutoCoding library (https://github.com/nicklockwood/AutoCoding) to add NSCoding support automatically. 47 | 48 | 2) Implement the CryptoCoding protocol for the root object in your object graph (the one that will be saved/loaded from a file). This protocol consists of a single method, `CCPassword` that returns the password used to encrypt and decrypt the arhive. The password can be hard-coded, or retrieved from user input or the Keychain. 49 | 50 | 3) Save the root object using the `archiveRootObject:toFile:` method of the CryptoCoder class. You can then load the object later using the `unarchiveObjectWithFile:` method. 51 | 52 | 53 | CryptoCoding classes 54 | ----------------------------- 55 | 56 | CryptoCoding provides the following class interfaces: 57 | 58 | * A category on NSData for AES encrypting/decrypting raw data 59 | * CryptoArchive - an NSCodable class for encrypting objects 60 | * CryptoCoder - an NSKeyedArchiver/Unarchiver replacement for encrypted object serialisation and deserialisation 61 | 62 | 63 | NSData (CryptoCoding) methods 64 | ------------------------------- 65 | 66 | The CryptoCoding category extends NSData with the following methods: 67 | 68 | - (NSData *)AESEncryptedDataWithPassword:(NSString *)password IV:(NSData **)IV salt:(NSData **)salt error:(NSError **)error version:(float)version; 69 | 70 | This method takes a password and returns an encrypted copy of the data using the AES128 algorithm. Note the IV (Initialization Vector) and salt arguments. These arguments are pointers to values that will be returned by the method. It is important to preserve the salt and IV values as you will need them to decrypt the data later. Only the password is secret - the salt and IV values can be stored in cleartext along with the encrypted data. Pass 0 for the version parameter to use the default encryption version. If you need to provide legacy support, use 1.0. 71 | 72 | - (NSData *)AESDecryptedDataWithPassword:(NSString *)password IV:(NSData *)IV salt:(NSData *)salt error:(NSError **)error version:(float)version; 73 | 74 | This method takes a password, salt and IV value and returns an unencrypted copy of the data. The password, salt and IV must all match those used to originally create the data. The version value should match the version used to encrypt the data originally (either 1.0 or 2.0). 75 | 76 | 77 | CryptoArchive methods 78 | ----------------------- 79 | 80 | The CryptoArchive class is used to wrap the encrypted data along with the salt and IV values and some other useful information. You will not normally need to use this class directly unless you wish to encode and object that does not conform to the CryptoCoding protocol. 81 | 82 | - (id)initWithRootObject:(id)rootObject password:(NSString *)password; 83 | 84 | This creates a new CryptoArchive from an NSCodable object and a password. Unlike the CryptoCoder methods, the object being encoded is not required to conform to the CryptoCoding protocol (although it does still need to conform to NSCoding). This may be useful if you wish to encode a generic collection object such as an NSArray or NSDictionary. 85 | 86 | - (id)unarchiveRootObjectWithPassword:(NSString *)password; 87 | 88 | This decodes the original object from a CryptoArchive and returns it. CryptoArchives are versioned. If the inetegr part of the archive version is greater than the `CryptoCodingVersion` of the currently installed version of the library, the decryption process will fail and the method will return nil. The same applies if the password doesn't match the one used to create the archive. 89 | 90 | 91 | CryptoCoder methods 92 | ----------------------------- 93 | 94 | CryptoCoder implements the following methods, which mirror those of the NSKeyedArchiver and NSKeyedUnarchiver classes. Note that all of CryptoCoder's methods are static - you do not need to instantiate the CryptoCoder class. 95 | 96 | + (id)unarchiveObjectWithData:(NSData *)data; 97 | 98 | This method decodes a CryptoCoded data object and unarchives the stored object. The password to decrypt the file will be retrieved by calling the `CCPassword` method on the class contained in the file. If the class doesn't implement this method, or the value returned doesn't match the password used to decrypt the file, the unarchiving process will fail. If the archive is not encrypted then the unencrypted object will be silently returned, so this method can be used to load either encrypted or unencrypted archives seamlessly. 99 | 100 | + (id)unarchiveObjectWithFile:(NSString *)path; 101 | 102 | As above, except that this method takes a path to a serialised data file instead of a raw NSData object. 103 | 104 | + (NSData *)archivedDataWithRootObject:(id)rootObject; 105 | 106 | This method archives the rootObject using the NSCoding protocol, and then encrypts it using the AES128 algorithm. The password for encrypting the object is retrieved by calling the `CCPassword` method on the rootObject class. If rootObject doesn't implement the `CCPassword` method, this method will throw an exception. 107 | 108 | + (BOOL)archiveRootObject:(id)rootObject toFile:(NSString *)path; 109 | 110 | As above, except that the resulting encypted data will be written directly to the file specified by the path parameter. 111 | 112 | + (void)setClassName:(NSString *)codedName forClass:(Class)cls; 113 | + (NSString *)classNameForClass:(Class)cls; 114 | + (void)setClass:(Class)cls forClassName:(NSString *)codedName; 115 | + (Class)classForClassName:(NSString *)codedName; 116 | 117 | These methods are used to specify class name substitutions when encoding or decoding objects, and can be useful when managing upgrades between app releases where classes may have been renamed. These methods wrap the equivalent methods of NSKeyedArchiver/Unarchiver respectively, so it makes no difference whether you call them on CryptoCoder or NSKeyedArchiver/Unarchiver. 118 | 119 | 120 | Release notes 121 | ----------------- 122 | 123 | Version 1.1.1 124 | 125 | - Uodated for Xcode 9 126 | 127 | Version 1.1 128 | 129 | - Now requires ARC 130 | - Implemented new key generation mechanism for iOS 5 / Mac OS 10.7 and above 131 | - Now conforms to -Weverything warning level 132 | 133 | Version 1.0.1 134 | 135 | - Dropped support for Mac OS 10.6 136 | 137 | Version 1.0 138 | 139 | - Initial release 140 | --------------------------------------------------------------------------------