Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Add encryption support, fix untrusted HTTPS connection issue in simul…

…ator
  • Loading branch information...
commit 70c6538a89bf79b2ada2cb1d82c2e6fd2d7a80da 1 parent 821fb90
Richard Moreland richard authored
15 Classes/Parsing/EditsFileParser.m
View
@@ -23,6 +23,7 @@
#import "EditsFileParser.h"
#import "EditEntity.h"
#import "DataUtils.h"
+#import "GlobalUtils.h"
@implementation EditsFileParser
@@ -44,15 +45,17 @@ - (void)parse {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- NSError *error = nil;
+ NSString *errorStr = nil;
NSString *entireFile;
// Read the entire file into memory (perhaps one day we'll do this line by line somehow?)
- if ([[NSFileManager defaultManager] fileExistsAtPath:editsFilename]) {
- entireFile = [NSString stringWithContentsOfFile:editsFilename encoding:NSUTF8StringEncoding error:&error];
- if (error) {
- //NSLog(@"Failed to read contents of file because: %@", [error description]);
+ if ([[NSFileManager defaultManager] fileExistsAtPath:editsFilename]) {
+ entireFile = ReadPossiblyEncryptedFile(editsFilename, &errorStr);
+ if (errorStr) {
+ entireFile = [NSString stringWithFormat:@"* Error: %@\n", errorStr];
+ } else if (!entireFile) {
entireFile = @"* Bad file encoding\n Unable to detect file encoding, please re-save this file using UTF-8.";
+ errorStr = [NSString stringWithString:@"Unknown encoding, re-save file as UTF-8"];
}
} else {
entireFile = @"";
@@ -79,7 +82,7 @@ - (void)parse {
bool awaitingBodyTextForNonEditNode = false;
lines = [entireFile componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"\r\n"]];
-
+
// Until we hit the end of the file
for (int i = 0; i < [lines count]; i++) {
2  Classes/Parsing/OrgFileParser.h
View
@@ -27,12 +27,14 @@
SEL completionSelector;
NSString *orgFilename;
NSString *localFilename;
+ NSString *errorStr;
}
@property (nonatomic, assign) id delegate;
@property (nonatomic) SEL completionSelector;
@property (nonatomic, copy) NSString *orgFilename;
@property (nonatomic, copy) NSString *localFilename;
+@property (nonatomic, copy) NSString *errorStr;
- (void)parse;
10 Classes/Parsing/OrgFileParser.m
View
@@ -32,6 +32,7 @@ @implementation OrgFileParser
@synthesize completionSelector;
@synthesize orgFilename;
@synthesize localFilename;
+@synthesize errorStr;
- (void)parse {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
@@ -63,10 +64,12 @@ - (void)parse {
}
// Read the entire file into memory (perhaps one day we'll do this line by line somehow?)
- entireFile = [NSString stringWithContentsOfFile:localFilename encoding:NSUTF8StringEncoding error:&error];
- if (error) {
- //NSLog(@"Failed to read contents of file because: %@ (%@)", [error description], [error userInfo]);
+ entireFile = ReadPossiblyEncryptedFile(localFilename, &errorStr);
+ if (errorStr) {
+ entireFile = [NSString stringWithFormat:@"* Error: %@\n", errorStr];
+ } else if (!entireFile) {
entireFile = @"* Bad file encoding\n Unable to detect file encoding, please re-save this file using UTF-8.";
+ errorStr = [NSString stringWithString:@"Unknown encoding, re-save file as UTF-8"];
}
// Maintain a stack of nodes for parenting use
@@ -482,6 +485,7 @@ - (void)parse {
}
- (void)dealloc {
+ [errorStr release];
[orgFilename release];
[localFilename release];
[super dealloc];
3  Classes/Settings/Settings.h
View
@@ -54,6 +54,8 @@ typedef enum {
NSString *dropboxEmail;
NSString *dropboxIndex;
+
+ NSString *encryptionPassword;
}
@property (nonatomic, copy) NSURL *indexUrl;
@@ -69,6 +71,7 @@ typedef enum {
@property (nonatomic) ServerMode serverMode;
@property (nonatomic, copy) NSString *dropboxEmail;
@property (nonatomic, copy) NSString *dropboxIndex;
+@property (nonatomic, copy) NSString *encryptionPassword;
+ (Settings*)instance;
- (void)resetPrimaryTagsAndTodoStates;
13 Classes/Settings/Settings.m
View
@@ -47,6 +47,7 @@
static NSString *kServerModeKey = @"ServerMode";
static NSString *kDropboxIndexKey = @"DropboxIndex";
static NSString *kDropboxEmailKey = @"DropboxEmail";
+static NSString *kEncryptionPassKey = @"EncryptionPassword";
@implementation Settings
@@ -63,6 +64,7 @@ @implementation Settings
@synthesize serverMode;
@synthesize dropboxEmail;
@synthesize dropboxIndex;
+@synthesize encryptionPassword;
+ (Settings*)instance {
@synchronized(self) {
@@ -87,6 +89,9 @@ - (id)init {
password = [[NSUserDefaults standardUserDefaults] objectForKey:kPasswordKey];
[password retain];
+ encryptionPassword = [[NSUserDefaults standardUserDefaults] objectForKey:kEncryptionPassKey];
+ [encryptionPassword retain];
+
lastSync = [[NSUserDefaults standardUserDefaults] objectForKey:kLastSyncKey];
[lastSync retain];
@@ -159,6 +164,13 @@ - (void)setPassword:(NSString*)aPassword {
[[NSUserDefaults standardUserDefaults] synchronize];
}
+- (void)setEncryptionPassword:(NSString *)aEncryptionPassword {
+ [encryptionPassword release];
+ encryptionPassword = [aEncryptionPassword copy];
+ [[NSUserDefaults standardUserDefaults] setObject:aEncryptionPassword forKey:kEncryptionPassKey];
+ [[NSUserDefaults standardUserDefaults] synchronize];
+}
+
- (void)setLastSync:(NSDate *)aLastSync {
[lastSync release];
lastSync = [aLastSync copy];
@@ -367,6 +379,7 @@ - (void)dealloc {
[todoStateGroups release];
[dropboxEmail release];
[dropboxIndex release];
+ [encryptionPassword release];
[super dealloc];
}
104 Classes/Settings/SettingsController.m
View
@@ -38,6 +38,16 @@
@implementation SettingsController
+enum {
+ ServerModeGroup,
+ ServerSettingsGroup,
+ AppInfoGroup,
+ SettingsGroup,
+ EncryptionGroup,
+ CreditsGroup,
+ NumGroups
+};
+
@synthesize dropboxPassword;
- (void)onSyncComplete {
@@ -79,25 +89,28 @@ - (void)viewDidUnload {
#pragma mark Table view methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
- return 5;
+ return NumGroups;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
NSString *title = nil;
switch (section) {
- case 0:
+ case ServerModeGroup:
title = NSLocalizedString(@"Server Config", @"Server configuration title");
break;
- case 1:
+ case ServerSettingsGroup:
break;
- case 2:
+ case AppInfoGroup:
title = NSLocalizedString(@"App Info", @"App info title");
break;
- case 3:
+ case SettingsGroup:
title = NSLocalizedString(@"Settings", @"App settings");
break;
- case 4:
+ case EncryptionGroup:
+ title = NSLocalizedString(@"Encryption", @"Encryption config");
+ break;
+ case CreditsGroup:
title = NSLocalizedString(@"Credits", @"Credits title");
break;
default:
@@ -109,10 +122,10 @@ - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInte
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
switch (section) {
- case 0:
+ case ServerModeGroup:
return 1;
break;
- case 1:
+ case ServerSettingsGroup:
if ([[Settings instance] serverMode] == ServerModeDropbox) {
if ([[DropboxTransferManager instance] isLinked]) {
return 2;
@@ -123,15 +136,18 @@ - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger
return 3;
}
break;
- case 2:
+ case AppInfoGroup:
return 2;
break;
- case 3:
+ case SettingsGroup:
return 1;
break;
- case 4:
- return 5;
+ case EncryptionGroup:
+ return 1;
break;
+ case CreditsGroup:
+ return 5;
+ break;
default:
break;
}
@@ -139,8 +155,10 @@ - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger
}
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section {
- if (section == 1) {
+ if (section == ServerSettingsGroup) {
return @"For help on configuration, visit http://mobileorg.ncogni.to";
+ } else if (section == EncryptionGroup) {
+ return @"If you have configured Org-mode to use encryption, enter your encryption password above.";
} else {
return @"";
}
@@ -162,7 +180,7 @@ - (NSArray*)entryFields {
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
- if (indexPath.section == 0) {
+ if (indexPath.section == ServerModeGroup) {
static NSString *CellIdentifier = @"ServerModeConfigurationSell";
@@ -198,7 +216,7 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N
return cell;
- } else if (indexPath.section == 1) {
+ } else if (indexPath.section == ServerSettingsGroup) {
if ([[Settings instance] serverMode] == ServerModeWebDav) {
@@ -342,7 +360,7 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N
return cell;
}
}
- } else if (indexPath.section == 2) {
+ } else if (indexPath.section == AppInfoGroup) {
static NSString *CellIdentifier = @"SettingsSimpleCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
@@ -378,7 +396,7 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N
return cell;
- } else if (indexPath.section == 3) {
+ } else if (indexPath.section == SettingsGroup) {
switch (indexPath.row) {
case 0:
@@ -410,7 +428,50 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N
break;
}
- } else if (indexPath.section == 4) {
+ } else if (indexPath.section == EncryptionGroup) {
+
+ switch (indexPath.row) {
+ case 0:
+ {
+ static NSString *CellIdentifier = @"SettingsEncPassKey";
+
+ UITextField *newLabel;
+ UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
+ if (cell == nil) {
+ cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue2 reuseIdentifier:CellIdentifier] autorelease];
+ if (IsIpad())
+ newLabel = [[[UITextField alloc] initWithFrame:CGRectMake(130,13,200,25)] autorelease];
+ else
+ newLabel = [[[UITextField alloc] initWithFrame:CGRectMake(100,13,200,25)] autorelease];
+ [newLabel setAdjustsFontSizeToFitWidth:YES];
+ [newLabel setAutoresizingMask:UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleRightMargin];
+ [newLabel setAutocorrectionType:UITextAutocorrectionTypeNo];
+ [newLabel setClearButtonMode:UITextFieldViewModeWhileEditing];
+ [newLabel setAutocapitalizationType:UITextAutocapitalizationTypeNone];
+ [cell addSubview:newLabel];
+ [cell setSelectionStyle:UITableViewCellSelectionStyleNone];
+
+ CGRect detailFrame = [[cell detailTextLabel] frame];
+ detailFrame.origin.y -= 1;
+ [[cell detailTextLabel] setFrame:detailFrame];
+ } else {
+ newLabel = (UITextField*)[cell.contentView viewWithTag:1];
+ }
+
+ [newLabel addTarget:self action:@selector(encryptionPasswordChanged:) forControlEvents:(UIControlEventValueChanged | UIControlEventEditingDidEnd)];
+ [newLabel setKeyboardType:UIKeyboardTypeDefault];
+ [newLabel setDelegate:self];
+ [newLabel setSecureTextEntry:YES];
+ [newLabel setTag:1];
+ [[cell textLabel] setText:@"Password"];
+ newLabel.text = [[Settings instance] encryptionPassword];
+ return cell;
+ }
+ default:
+ break;
+ }
+
+ } else if (indexPath.section == CreditsGroup) {
static NSString *CellIdentifier = @"SettingsCreditsCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
@@ -545,6 +606,11 @@ - (void)passwordChanged:(id)sender {
[[Settings instance] setPassword:textField.text];
}
+- (void)encryptionPasswordChanged:(id)sender {
+ UITextField *textField = (UITextField*)sender;
+ [[Settings instance] setEncryptionPassword:textField.text];
+}
+
- (void)dropboxIndexChanged:(id)sender {
UITextField *textField = (UITextField*)sender;
[[Settings instance] setDropboxIndex:textField.text];
@@ -588,7 +654,7 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath
// [self.navigationController pushViewController:anotherViewController];
// [anotherViewController release];
- if (indexPath.section == 1 && [[Settings instance] serverMode] == ServerModeDropbox) {
+ if (indexPath.section == ServerSettingsGroup && [[Settings instance] serverMode] == ServerModeDropbox) {
bool linked = [[DropboxTransferManager instance] isLinked];
if ((!linked && indexPath.row == 3) || (linked && indexPath.row == 1)) {
25 Classes/Sync/SyncManager.m
View
@@ -301,6 +301,12 @@ - (void)doneProcessingEditsFile {
[file closeFile];
[editsFileParser reset];
+
+ if (![[[Settings instance] encryptionPassword] isEqualToString:@""]) {
+ NSMutableData *data = [NSMutableData dataWithContentsOfFile:newEditsFilename];
+ NSData *encryptedData = [data AES256EncryptWithKey:[[Settings instance] encryptionPassword]];
+ [encryptedData writeToFile:newEditsFilename atomically:NO];
+ }
// Send the file back to the server
{
@@ -365,10 +371,17 @@ - (void)uploadEmptyEditsFile {
[f seekToEndOfFile];
NSData *data = [@"\n" dataUsingEncoding:NSUTF8StringEncoding];
- [f writeData:data];
+
+ if (![[[Settings instance] encryptionPassword] isEqualToString:@""]) {
+ NSData *encryptedData = [data AES256EncryptWithKey:[[Settings instance] encryptionPassword]];
+ [f writeData:encryptedData];
+ } else {
+ [f writeData:data];
+ }
+
[f closeFile];
}
-
+
currentState = SyncManagerTransferStateUploadingEmptyEditsFile;
TransferContext *context = [TransferContext new];
@@ -473,7 +486,7 @@ - (void)doneDownloadingOrgFiles {
for (Node *node in AllFileNodes()) {
CreateChecksumForFile(node.heading, [checksumParser.checksumPairs objectForKey:node.heading]);
}
-
+
// Clear downloaded list
[downloadedFiles removeAllObjects];
@@ -580,6 +593,12 @@ - (void)doneProcessingOrgFile {
// TODO: if success, do this. otherwise, abort then resume the transfer manager.
+ // If not success then remove the entry from the checksumpairs, we want to
+ // retry downloading it next sync.
+ if (orgFileParser.errorStr && ![orgFileParser.errorStr isEqualToString:@""]) {
+ [checksumParser.checksumPairs removeObjectForKey:NodeWithFilename([orgFileParser orgFilename]).heading];
+ }
+
// Save our database changes
Save();
24 Classes/Sync/WebDav/WebDavTransferManager.m
View
@@ -253,18 +253,30 @@ - (void)connection:(NSURLConnection*)aConnection didReceiveData:(NSData*)someDat
-(void)connection:(NSURLConnection*)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge*)challenge {
if ([challenge previousFailureCount] == 0) {
- NSURLCredential *newCredential;
- newCredential = [NSURLCredential credentialWithUser:[[Settings instance] username]
- password:[[Settings instance] password]
- persistence:NSURLCredentialPersistenceForSession];
- [[challenge sender] useCredential:newCredential
- forAuthenticationChallenge:challenge];
+ if ([[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodServerTrust) {
+ [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
+ }
+ else {
+ NSURLCredential *newCredential;
+ newCredential = [NSURLCredential credentialWithUser:[[Settings instance] username]
+ password:[[Settings instance] password]
+ persistence:NSURLCredentialPersistenceForSession];
+ [[challenge sender] useCredential:newCredential
+ forAuthenticationChallenge:challenge];
+ }
} else {
[[challenge sender] continueWithoutCredentialForAuthenticationChallenge:challenge];
activeTransfer.success = false;
}
}
+// From: http://stackoverflow.com/questions/2949640/nsurlconnection-nsurlrequest-untrusted-cert-and-user-authentication
+// In simulator on 4.x, the workaround for allowsAnyHTTPSCertificateForHost doesn't work,
+// so use this instead (along with the bit in didReceiveAuthenticationChallenge about NSURLAuthenticationMethodServerTrust.
+- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {
+ return YES;
+}
+
- (void)requestFinished:(TransferContext*)context {
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
4 Classes/Utilities/GlobalUtils.h
View
@@ -40,4 +40,6 @@ NSString *EscapeHeadings(NSString *original);
void UpdateAppBadge();
-BOOL IsIpad();
+BOOL IsIpad();
+
+NSString *ReadPossiblyEncryptedFile(NSString *filename, NSString **error);
178 Classes/Utilities/GlobalUtils.m
View
@@ -24,6 +24,8 @@
#import "Settings.h"
#import "MobileOrgAppDelegate.h"
#import "OutlineViewController.h"
+#import "CommonCrypto/CommonCryptor.h"
+#import "CommonCrypto/CommonDigest.h"
MobileOrgAppDelegate *AppInstance() {
return (MobileOrgAppDelegate*)[[UIApplication sharedApplication] delegate];
@@ -86,3 +88,179 @@ BOOL IsIpad() {
#endif
return NO;
}
+
+NSString *ReadPossiblyEncryptedFile(NSString *filename, NSString **error) {
+ *error = nil;
+
+ NSMutableData *data = [NSMutableData dataWithContentsOfFile:filename];
+ if (!data) {
+ *error = [NSString stringWithString:@"Unable to open file"];
+ return nil;
+ }
+
+ char buffer[16];
+ [data getBytes:buffer length:8];
+ if (!strncmp((const char*)buffer, "Salted__", 8)) {
+ NSData *decryptedData = [data AES256DecryptWithKey:[[Settings instance] encryptionPassword]];
+ if (decryptedData) {
+ if ([decryptedData length] > 0) {
+ return [NSString stringWithCString:[decryptedData bytes] encoding:NSUTF8StringEncoding];
+ } else {
+ return @"";
+ }
+ } else {
+ *error = [NSString stringWithString:@"Unable to decrypt file"];
+ return nil;
+ }
+ } else {
+ return [NSString stringWithCString:[data bytes] encoding:NSUTF8StringEncoding];
+ }
+}
+
+// From: http://stackoverflow.com/questions/652300/using-md5-hash-on-a-string-in-cocoa
+NSString *md5(unsigned char *bytes, size_t len) {
+ unsigned char result[16];
+ CC_MD5( bytes, len, result );
+ return [NSString stringWithFormat:
+ @"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
+ result[0], result[1], result[2], result[3],
+ result[4], result[5], result[6], result[7],
+ result[8], result[9], result[10], result[11],
+ result[12], result[13], result[14], result[15]
+ ];
+}
+
+static const int SaltPrefixLen = 8;
+static const int SaltLen = 8;
+
+void ExtractKeyAndIVFromPassphrase(const char *pass,
+ const unsigned char *salt,
+ unsigned char *key, unsigned char *iv)
+{
+ // http://deusty.blogspot.com/2009/04/decrypting-openssl-aes-files-in-c.html
+ // Link above was very helpful in determing how this should work.
+
+ //NSLog(@"salt: %@", [NSString stringWithFormat:
+ // @"%02X%02X%02X%02X%02X%02X%02X%02X",
+ // salt[0], salt[1], salt[2], salt[3],
+ // salt[4], salt[5], salt[6], salt[7]
+ // ]);
+
+ size_t passLen = strlen(pass);
+ unsigned char lastKey[kCCKeySizeAES128];
+ unsigned char tmpStr[kCCKeySizeAES128 + passLen + SaltLen];
+
+ memcpy(tmpStr, pass, passLen);
+ memcpy(tmpStr + passLen, &salt[0], SaltLen);
+ CC_MD5(tmpStr, passLen + SaltLen, lastKey);
+ memcpy(key, lastKey, kCCKeySizeAES128);
+ //NSLog(@"key1: %@", md5(tmpStr, passLen + SaltLen));
+
+ memcpy(tmpStr, key, kCCKeySizeAES128);
+ memcpy(tmpStr + kCCKeySizeAES128, pass, passLen);
+ memcpy(tmpStr + kCCKeySizeAES128 + passLen, &salt[0], SaltLen);
+ CC_MD5(tmpStr, kCCKeySizeAES128 + passLen + SaltLen, lastKey);
+ memcpy(key + kCCKeySizeAES128, lastKey, kCCKeySizeAES128);
+ //NSLog(@"key2: %@", md5(tmpStr, kCCKeySizeAES128 + passLen + SaltLen));
+
+ memcpy(tmpStr, lastKey, kCCKeySizeAES128);
+ memcpy(tmpStr + kCCKeySizeAES128, pass, passLen);
+ memcpy(tmpStr + kCCKeySizeAES128 + passLen, &salt[0], SaltLen);
+ CC_MD5(tmpStr, kCCKeySizeAES128 + passLen + SaltLen, iv);
+ //NSLog(@"iv: %@", md5(tmpStr, kCCKeySizeAES128 + passLen + SaltLen));
+}
+
+// From: http://pastie.org/426530
+@implementation NSData (AES256)
+
+- (NSData *)AES256EncryptWithKey:(NSString *)passphrase {
+
+ unsigned char key[kCCKeySizeAES256];
+ unsigned char iv[kCCKeySizeAES128];
+ unsigned char salt[SaltLen];
+ const unsigned char *bytes = [self bytes];
+ void *buffer;
+
+ size_t bytesLen = [self length];
+ size_t bufferSize = bytesLen + kCCBlockSizeAES128 + SaltPrefixLen + SaltLen;
+
+ // Generate the salt, prepend it to the buffer
+ time_t now = time(NULL);
+ memcpy(salt, &now, sizeof(time_t));
+
+ buffer = malloc(bufferSize);
+ bzero(buffer, bufferSize);
+ strcpy(buffer, "Salted__");
+ memcpy(buffer+SaltPrefixLen, salt, SaltLen);
+
+ ExtractKeyAndIVFromPassphrase([passphrase cStringUsingEncoding:NSASCIIStringEncoding], salt, key, iv);
+
+ size_t numBytesEncrypted = 0;
+ CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
+ key, kCCKeySizeAES256,
+ iv,
+ bytes, bytesLen,
+ buffer+SaltPrefixLen+SaltLen, bufferSize-SaltPrefixLen-SaltLen,
+ &numBytesEncrypted);
+
+ if (cryptStatus == kCCSuccess) {
+ //the returned NSData takes ownership of the buffer and will free it on deallocation
+ return [NSData dataWithBytesNoCopy:buffer length:(numBytesEncrypted+SaltPrefixLen+SaltLen)];
+ }
+ else {
+ // TODO: Unknown error
+ }
+
+ free(buffer);
+ return nil;
+}
+
+- (NSData *)AES256DecryptWithKey:(NSString *)passphrase {
+
+ unsigned char key[kCCKeySizeAES256];
+ unsigned char iv[kCCKeySizeAES128];
+ unsigned char salt[SaltLen];
+ const unsigned char *bytes = [self bytes];
+ void *buffer;
+
+ size_t bytesLen = [self length];
+ size_t bufferSize = bytesLen + kCCBlockSizeAES128 + 1;
+
+ // Extract the salt, advance the byte buffer
+ memcpy(salt, [self bytes] + SaltPrefixLen, SaltLen);
+ bytesLen -= (SaltPrefixLen + SaltLen);
+ bytes += (SaltPrefixLen + SaltLen);
+
+ ExtractKeyAndIVFromPassphrase([passphrase cStringUsingEncoding:NSASCIIStringEncoding], salt, key, iv);
+
+ buffer = malloc(bufferSize);
+ bzero(buffer, bufferSize);
+
+ size_t numBytesDecrypted = 0;
+ CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
+ key, kCCKeySizeAES256,
+ iv,
+ bytes, bytesLen,
+ buffer, bufferSize,
+ &numBytesDecrypted);
+
+ // Add a null character at the end to terminate the string
+ // FUTURE TODO: This obviously isn't a good idea if we're handling anything other than text!
+ ((char*)buffer)[numBytesDecrypted++] = '\0';
+
+ if (cryptStatus == kCCSuccess) {
+ //the returned NSData takes ownership of the buffer and will free it on deallocation
+ return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
+ }
+ else if (cryptStatus == kCCDecodeError) {
+ // TODO: Error, likely a bad password
+ }
+ else {
+ // TODO: Unknown error
+ }
+
+ free(buffer);
+ return nil;
+}
+
+@end
4 MobileOrg-Info-AdHoc.plist
View
@@ -19,11 +19,11 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
- <string>1.4</string>
+ <string>1.5</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
- <string>27</string>
+ <string>28</string>
<key>CFBundleIconFiles</key>
<array>
<string>Icon-beta-72.png</string>
4 MobileOrg-Info-Debug.plist
View
@@ -25,11 +25,11 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
- <string>1.4</string>
+ <string>1.5</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
- <string>27</string>
+ <string>28</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSMainNibFile</key>
4 MobileOrg-Info.plist
View
@@ -25,11 +25,11 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
- <string>1.4</string>
+ <string>1.5</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
- <string>27</string>
+ <string>28</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSMainNibFile</key>
10 MobileOrg.xcodeproj/project.pbxproj
View
@@ -907,7 +907,7 @@
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
COPY_PHASE_STRIP = NO;
- CURRENT_PROJECT_VERSION = 27;
+ CURRENT_PROJECT_VERSION = 28;
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
@@ -943,9 +943,9 @@
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
CODE_SIGN_ENTITLEMENTS = Entitlements.plist;
- "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer: Richard Moreland (6QN2535D24)";
COPY_PHASE_STRIP = YES;
- CURRENT_PROJECT_VERSION = 27;
+ CURRENT_PROJECT_VERSION = 28;
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = MobileOrg_Prefix.pch;
@@ -953,7 +953,7 @@
INFOPLIST_PREPROCESS = NO;
IPHONEOS_DEPLOYMENT_TARGET = 3.0;
PRODUCT_NAME = MobileOrg;
- "PROVISIONING_PROFILE[sdk=iphoneos*]" = "";
+ "PROVISIONING_PROFILE[sdk=iphoneos*]" = "48A13CA8-C59C-4CDF-838D-5F1A782AC691";
SDKROOT = iphoneos4.1;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
@@ -980,7 +980,7 @@
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution: Richard Moreland";
COPY_PHASE_STRIP = YES;
- CURRENT_PROJECT_VERSION = 27;
+ CURRENT_PROJECT_VERSION = 28;
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = MobileOrg_Prefix.pch;
Please sign in to comment.
Something went wrong with that request. Please try again.