Wednesday, October 27, 2010

UINavigationBar Back Button with images



Your Ad Here


This is a topic that I have noticed on numerous iPhone development forums and since I’ve had to address this in multiple apps that I’ve worked on in the past, I thought it would be a good topic to share some info on.  The default behavior of the navigation controller is to provide a back button with the title of the previous view controller.  This is fine and dandy if you have short titles and that’s the behavior your looking for but what if you wanted to create a home button similar to the Facebook app or for that matter, an image that acts like a button but doesn’t look like one.
We will start with the Facebook style Home button.  To reproduce the following:



In the view controller that you want to add the home button to, your going to need to add a cancel method to pop your view controller:

-(IBAction)cancel:(id)sender{
 [self.navigationController popViewControllerAnimated:YES];
}
Next you will need to add your custom home button with some sort of  image, in this case we are using an image called “home-button.png”:

- (void)viewDidLoad {
 [super viewDidLoad];

 // Add Home Button
 UIBarButtonItem *cancelButton = [[[UIBarButtonItem alloc]
       initWithImage:[UIImage imageNamed:@"home-button.png"]
       style:UIBarButtonItemStylePlain
       target:self
       action:@selector(cancel:)] autorelease];
 self.navigationItem.leftBarButtonItem = cancelButton;
}
And that’s it.  You’ll need this in each view controller that is on top of your home view controller.
Next we will recreate the following:



In this case, we are using an image as the leftbarbuttonitem. We do so by creating our cancel method in the view controller that you want to add the home or back image to.

-(IBAction)cancel:(id)sender{
 [self.navigationController popViewControllerAnimated:YES];
}
Next we will add the image “back-image.png” as our back button and size up the button:

- (void)viewDidLoad {
 [super viewDidLoad];

 // Add Back Bar Button
 UIButton *home = [UIButton buttonWithType:UIButtonTypeCustom];
 UIImage *homeImage = [[UIImage imageNamed:@"back-image.png"]
      stretchableImageWithLeftCapWidth:10 topCapHeight:10];
 [home setBackgroundImage:homeImage forState:UIControlStateNormal];
 [home addTarget:self action:@selector(cancel:)
    forControlEvents:UIControlEventTouchUpInside];
 home.frame = CGRectMake(0, 0, 99, 35);
 UIBarButtonItem *cancelButton = [[[UIBarButtonItem alloc]
      initWithCustomView:home] autorelease];
 self.navigationItem.leftBarButtonItem = cancelButton;
}
And that’s it!  One nice benefit to this is that you can perform  additional processing in the cancel method if needed prior to popping to  the previous controller.
One last item to add is if you just want to change the text of the back button so that it’s different than the previous view controller’s title:

UIBarButtonItem *backButton = [[UIBarButtonItem alloc]
                                      initWithTitle:@"Back"
                                      style:UIBarButtonItemStylePlain
                                      target:nil action:nil];
     self.navigationItem.backBarButtonItem = backButton;
     [backButton release];

Tutorial: iPhone SQLite Encryption With SQLCipher



Your Ad Here



Mobile devices are notoriously difficult to secure. With a small footprint it is dangerously easy to leave your phone in the back of a taxi, or forget to pick it up from a table after dinner at a restaurant. iPhone and iPod Touch devices are no exception – most applications store their data in an easily readable format. Anyone with access to your device can browse through your personal information. Even worse, since the devices back up to your computer, any knowledgeable person with access to your workstation can read your data as well.
This is balanced by immense convenience. An iPhone makes a perfect digital wallet: a single device with all your important information literally at your fingertips. When we set out to write Strip, our iPhone Password Manager and Data Vault, we wanted to build a system that we could trust to store Passwords, Credit Card Numbers, Passport Identifiers, SSNs and bank account information. Most of the other applications in the App store used undocumented encryption or weaker field level security. We wanted to encrypt EVERY bit of Strip’s data on the device. Naturally the ideal approach would be to have the encryption managed transparently, so Strip didn’t need to know about the details.
Enter SQLCipher, a specialized build of the excellent SQLite database that performs transparent and on-the-fly encryption. Using SQLCipher, an application uses the standard SQLite API to manipulate tables using SQL. Behind the scenes the library silently manages the security aspects, making sure that data pages are encrypted and decrypted as they are written to and read from storage. SQLCipher uses the widely trusted and peer-reviewed OpenSSL library for all cryptographic functions.
SQLite is already the predominant API for persistent data storage on the iPhone so the upside for development is obvious. As a programmer you work with a stable and well documented API. All security concerns are cleanly decoupled from application code and managed by the underlying framework. The framework code of the SQLCipher and OpenSSL projects are both open source, so users can be confident that an application isn’t using insecure or proprietary security code.
Using SQLCipher in an iPhone application is straightforward once you setup your project properly. The easiest way to integrate SQLCipher into an application is to use XCode project references as described here.

Get OpenSSL
SQLCipher relies on OpenSSL for several encryption requirements including the AES-256 algorithm, pseudo random number generation, and PBKDF2 key derivation. OpenSSL isn’t a framework that is usable directly on the iPhone so we will setup our project to build and link against it as a static library.
Navigate to the OpenSSL download page. Download the source file of the latest stable version (0.9.8k as of this writing) and extract it to a folder on your system. Make a note of the source directory path for later.
OpenSSL can be a tricky system to compile properly from source. It’s even more complex when you’re dealing with multiple target architectures, targeting i386 for the simulator but armv6 for a device. Luckily we’ve built a handy XCode project template to make it easy called openssl-xcode. The project actually relies on the OpenSSL configure and make system to build the libraries. However, it automatically detects the appropriate build settings for architecture (i386, ppc, arv6), build tools, and SDK. This makes it ideal for inclusion in an iPhone project. Just git clone or download openssl-xcode from GitHub and move the openssl.xcodeproj file into the OpenSSL source directory.

Get SQLCipher
SQLCipher is a standalone package that includes the entire SQLite source distribution. You can git clone or download the latest version from the SQLCipher repository on GitHub. Again, make note of the source directory path you use for later in the setup process.

XCode Setup
SQLCipher uses project references to manage build dependencies and static linking. In order to allow linking you must setup your XCode environment to use a central build location. We will also need to configure Source Trees OpenSSL and SQLCipher respectively.
  1. Open XCode, Choose the XCode Menu, and then Preferences.
  2. On the Building tab, Change the “Place Build Products In” to “Customized location” and pick a location for the build directory.

  1. Switch to the Source Tree tab.
  2. Add a SQLCIPHER_SRC that references the path to the SQLCipher sourcecode
  3. Add a OPENSSL_SRC to reference the path to the OpenSSL sourcecode


Project Setup
Now that we have XCode global preferences setup we will move on to the project configuration.

Open your XCode application project, and click on the top level Project item. Hit option-command-a to add a resource. Navigate to the OpenSSL directory and choose the openssl.xcodeproj to add the reference. When the add resource window comes up make sure that “Copy items” is not checked, and add it to the appropriate target. Repeat the same, this time choose the sqlcipher.xcodeproj file in SQLCipher source directory.
Let’s change the Path Types as a convenience to multi-developer teams. Using paths relative to the Source Trees we defined will allow each developer to place the SQLCipher and OpenSSL in any locations and the build will still work.

  1. Hit option-i on the sqlcipher.xcodeproj reference and change the Path Type to “Relative to SQLCIPHER_SRC”.
  2. Hit option-i on the openssl.xcodeproj reference and change the Path Type to “Relative to OPENSSL_SRC”
  3. Hit option-command-a to add another resource
Now we will add build dependencies to ensure that the SQLCipher is compiled before the application code. Open the Info panel for your Application Target and Choose the General Tab. We will add two dependencies, one for OpenSSL crypto, and one for SQLCipher.

Then switch to the Build tab to add our source paths to the include directories to make relevant header files available. Make sure that the Configuration is set to “All Configurations”. Look for the “Header Search Paths” setting and add references to $(SQLCIPHER_SRC) and $(OPENSSL_SRC). Check “recursive” on both.

Finally, we will tell XCode to link against the built libraries. Expand the sqlcipher and openssl .xcodeproj references and select libsqlcipher.a and libcrypto.a. Drag and drop them on “Link Binary With Libraries” under your application target.


Building SQLCipher
At this point you should be able to build your XCode project without errors. Note that the first time you build your application for a particular architecture (Simulator for instance), it will take much longer than usual. This is because SQLCipher and OpenSSL are compiled from source for the specific architecture. You can keep track of the status under Build Results. Subsequent builds for the same platform will be much quicker since the libraries don’t need to be recompiled.

In Code
Now that you’ve incorporated the SQLCipher library into your project you can start using the system immediately. Telling SQLCipher to encrypt a database is as easy as opening a database and using “PRAGMA key” or the sqlite3_key function.
#import 

...
sqlite3 *db;
if (sqlite3_open(@"/path/to/database", &db) == SQLITE_OK) {
   sqlite3_exec(db, "PRAGMA key = 'BIGsecret', NULL, NULL, NULL);

   if (sqlite3_exec(db, (const char*) "SELECT count(*) FROM sqlite_master;", NULL, NULL, NULL) == SQLITE_OK) {
     // password is correct, or, database has been initialized
   } else {
     // incorrect password!
   }
}
The call to sqlite3_key or PRAGMA key should occur as the first operation after opening the database. In most cases SQLCipher uses PBKDF2, a salted and iterated key derivation function, to obtain the encryption key. Alternately, can tell SQLCipher to use a specific binary key in blob notation (note that you must provide exactly 256 bits of key material):
PRAGMA key = "x'2DD29CA851E7B56E4697B0E1F08507293D761A05CE4D1B628663F411A8086D99'";
Once the key is set SQLCipher will automatically encrypt all data in the database! If you don’t set a key then SQLCipher will operate identically to a standard SQLite database.
Note: In the interest of brevity and clarity this section demonstrates the use of the API to set a passphrase and an encryption key using a static value. In a real application the passphrase or key data should be collected from an external source, like a “Secure” UITextField, and then passed to SQLCipher. An application should never hard-code its key, as this would be very easy to crack.

Verify
After your application is wired up to use SQLCipher you should take a quick peek at the resulting data files to make sure everything is in order. An ordinary SQLite database will look something like the following under hexdump. Note that the file type, schema, and data are clearly readable.
new-host-2:sqlcipher sjlombardo$ hexdump -C plaintext.db
00000000  53 51 4c 69 74 65 20 66  6f 72 6d 61 74 20 33 00  |SQLite format 3.|
00000010  04 00 01 01 00 40 20 20  00 00 00 04 00 00 00 00  |.....@  ........|
...
000003b0  00 00 00 00 24 02 06 17  11 11 01 35 74 61 62 6c  |....$......5tabl|
000003c0  65 74 32 74 32 03 43 52  45 41 54 45 20 54 41 42  |et2t2.CREATE TAB|
000003d0  4c 45 20 74 32 28 61 2c  62 29 24 01 06 17 11 11  |LE t2(a,b)$.....|
000003e0  01 35 74 61 62 6c 65 74  31 74 31 02 43 52 45 41  |.5tablet1t1.CREA|
000003f0  54 45 20 54 41 42 4c 45  20 74 31 28 61 2c 62 29  |TE TABLE t1(a,b)|
...
000007d0  00 00 00 14 02 03 01 2d  02 74 77 6f 20 66 6f 72  |.......-.two for|
000007e0  20 74 68 65 20 73 68 6f  77 15 01 03 01 2f 01 6f  | the show..../.o|
000007f0  6e 65 20 66 6f 72 20 74  68 65 20 6d 6f 6e 65 79  |ne for the money|
Fire up your SQLCipher application in simulator you can look for your database files under /Users//Library/Application Support/iPhone Simulator/User/Applications//Documents. Try running hexdump on your application database. With SQLCipher you should get output that looks completely random, with no discerning characteristics at all:
new-host-2:Documents sjlombardo$ hexdump -C encrypted.db
00000000  84 d1 36 18 eb b5 82 90  c4 70 0d ee 43 cb 61 87  |.?6.?..?p.?C?a.|
00000010  91 42 3c cd 55 24 ab c6  c4 1d c6 67 b4 e3 96 bb  |.B00000020  8e df fa bc c3 9c 92 8a  4e 40 59 6f b5 95 f3 80  |.????...N@Yo?.?.|
...
00000bd0  91 16 9e 89 d9 4e ac f7  1c c9 d1 d7 aa bb a7 51  |....?N??.??ת??Q|
00000be0  dc 77 5c 6c de c6 d3 be  43 49 48 3e f3 02 94 a9  |?w\l??ӾCIH>?..?|
00000bf0  8e 99 ee 28 23 43 ab a4  97 cd 63 42 8a 8e 7c c6  |..?(#C??.?cB..|?|
00000c00
Conclusion
SQLCipher is an easy way to incorporate full database encryption into an iPhone application. For more information on SQLCipher and the underlying security features please check out the SQLCipher project site. To see it in action please try Strip and Strip Lite in the iTunes App Store!

Core Data and Enterprise iPhone Applications – Protecting Your Data



Your Ad Here


Introduction
NewsGator’s primary software offering is a product called Social Sites which basically adds social networking aspects to Microsoft SharePoint. My role in this product is to create the iOS device apps that interact with the server. My app is pulling in a lot of data that an enterprise customer considers *very* sensitive so data protection is the first thing many CIOs ask about when considering Social Sites. This post is to layout both how iOS protects data on the device so our prospective clients have a better idea about how it works, along with some additional steps developers can take to further protect their data.
Much of what I’ll discuss was covered in Session 209 at WWDC, but since that information is under NDA, I’ll stick to information that’s available in the public domain (including this post about iPhone 3GS and this post about iOS4). But if you have access to the WWDC videos, Session 209 is a great resource.

Data Encryption Starting with iPhone 3GS
Social Sites uses Core Data with a SQLite store type for storage and persistence. When the app first runs, it creates a Social_Sites.sqlite database file in its sand boxed documents directory on the device file system.
With the 3GS, any data written to the filesystem is encrypted using hardware encryption. By simply creating the Social_Sites.sqlite file on the file system, the data stored in it is already encrypted. This encryption also allows for the Social Sites data to be instantaneously unavailable when you use Remote Wipe. I say unavailable because the remote wipe doesn’t actually overwrite the encrypted data on the filesystem, but instead overwrites the hardware key used to encrypt/decrypt it. But still, the important thing is that the data on disk is encrypted.
This type of data encryption is also used on the current iPads.

Data Encryption on iOS 4

The way hardware encryption works on iOS4 has been greatly improved. I can’t find any public document from Apple that explains the improvements in detail, but their iOS 4: Understanding data protection support page gives a hint with “Data protection enhances the built-in hardware encryption by protecting the hardware encryption keys with your passcode.” I’ll just say that hardware data encryption on the 3GS and iPad use a single hardware encryption key. The WWDC session goes into great detail about the under the hood improvements. The main takeaway for a CIO though is that the Social Sites sqlite datafile on iOS4 has stronger encryption than it did in the past.

Further Protection – NSFileProtectionComplete

In iOS4, Apple introduced data protection. It gives you the ability to encrypt the hardware keys used to encrypt your files and to erase those keys when the system is locked – leaving your file unreadable until the phone is unlocked and the keys are regenerated.
This level of protection is not built in by default though. The user has to enable it (or an IT department can enable it and force users to have it on) and your code must set an attribute on your Core Data sqlite store as well.
Steps for the user to enable data protection are outlined on the iOS 4: Understanding data protection support page. You need to have the passcode turned on since this is what the system will use to generate the encryption for the keys.
As a developer, you need to set the NSFileProtection level of your sqlite store to NSFileProtectionComplete (by default it will be NSFileProtectionNone). You can do this right after you instantiate your persistent store coordinator:




- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
    if (persistentStoreCoordinator != nil) {
        return persistentStoreCoordinator;
    }

    NSString *storePath = [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"Social_Sites.sqlite"];
    NSURL *storeUrl = [NSURL fileURLWithPath:storePath ];

    NSError *error = nil;
    persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
    if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:nil error:&error]) {
        // Handle error
    }

    if(RSRunningOnOS4OrBetter())
    {
        NSDictionary *fileAttributes = [NSDictionary dictionaryWithObject:NSFileProtectionComplete forKey:NSFileProtectionKey];
        if (![[NSFileManager defaultManager] setAttributes:fileAttributes ofItemAtPath:storePath error:&error]) {
            // Handle error
        }
    }

    return persistentStoreCoordinator;
}

BOOL RSRunningOnOS4OrBetter(void) {
    static BOOL didCheckIfOnOS4 = NO;
    static BOOL runningOnOS4OrBetter = NO;

    if (!didCheckIfOnOS4) {
        NSString *systemVersion = [UIDevice currentDevice].systemVersion;
        NSInteger majorSystemVersion = 3;

        if (systemVersion != nil && [systemVersion length] > 0) { //Can't imagine it would be empty, but.
            NSString *firstCharacter = [systemVersion substringToIndex:1];
            majorSystemVersion = [firstCharacter integerValue];   
        }

        runningOnOS4OrBetter = (majorSystemVersion >= 4);
        didCheckIfOnOS4 = YES;
    }
    return runningOnOS4OrBetter;
}
Considerations
If your application needs your Core Data store in any background processing, then you cannot use data protection. Any attempt to access files that are NSFileProtectionComplete will cause an exception.
There are application delegates applicationProtectedDataWillBecomeUnavailable and applicationProtectedDataDidBecomeAvailable as well as notifications UIApplicationProtectedDataWillBecomeUnavailable and UIApplicationProtectedDataWillBecomeAvailable that you can use to determine what state your protected data is in.
You could then in theory keep unprotected data in memory in your background processing then write it into your Core Data store when protected data becomes available again.
You can find more information in the iPhone Application Programming Guide.

Conclusions
My answer to any CIO asking would be to ensure any device using Social Sites be a 3GS, an iPad or an iPhone 4. I would also encourage enforcing passcode and data protection for any device running iOS4. These steps ensure that the SQLite data store for Social Sites is hardware encrypted with remote wipe capabilities and further protected with iOS4 and data protection.
UPDATE:
Here’s the link to the iPhone Configuration Utility 3.0 which can be used to “create, maintain, encrypt, and install configuration profiles, track and install provisioning profiles and authorized applications, and capture device information including console logs.”

 
Submit Express Inc.Search Engine Optimization Services