Monday, November 25, 2013

Keep it secret!

With the latest release, AeroGear iOS 1.3.0 comes with more enhanced security features. Latest adding is encryption. In this release we deal with symmetric encryption.

Symmetric encryption: what is it?


Sometime talking about security topics might seem a bit overwhelming. But no worries, let's get the right vocabulary. When talking about encryption, there are actually two basic techniques for encrypting information: symmetric encryption (also called secret key encryption) and asymmetric encryption (also called public key encryption).

Today, we're going to delve into symmetric encryption as asymmetric one will be included in next AeroGear release. As said, symmetric encryption is when the same key is used to encrypt and decrypt data. Again, let's get the right jargon. Private key encryption is best defined with the following concepts:
  • Encryption key is a block of bytes of a _specific length_. Key can be derived from password using for example, PBKDF2 algorithm. Key must be kept secret.
  • IV (Initialisation Vector) is a random value that is used to encrypt data. Encryption algorithms usually work on fixed-size blocks, IV defines the first encrypted block.
You can derive the encryption key using a password or phassphrase and salt with AGPBKDF2.
  • Password is easy to remember and usually defined by user and must be kept secret. A password is not a key.
  • Salt is a random value that is used together with a password to derive an encryption key. A salt value does not need to be kept secret.
AeroGear-Crypto symmetric encryption provides you an easy way to encrypt your sensitive data. No need to be a security expert to use the library. See by yourself.

An example please: Xmas


Christmas is coming, it's all around us. Papillotes (french Christmas chocolate) and clementine is in the air. Surrounded by nephews and friends, it's time to organize your Santa Claus list. But you don't want your secret list to leak. Here comes into the scene your aerogear-crypto libraries.

In Xmas, we want to achieve local encryption of the present description but keep information like to whom the present is for, clear and searchable. The flow is simple you add a present to the list with an associated password and you saved it. It is first encrypted and then locally saved.

The list of present is displayed with a generic picture. If you want to remember what the item is. just click on it entered the password used for encryption, and the card will be flipped to show you the content description in clear.



Show me the code


Derive Key


First of all, to encrypt your data you need an encryption key. Your key can be derived from your password using PBKDF2 algorithms.
 -(NSData*) getKeyFromPassword:(NSString*)password {
     AGPBKDF2* derivator = [[AGPBKDF2 alloc] init];
     
     return [derivator deriveKey:password salt:_salt];
 }
To derive you key from your password you need to introduce some randomness (remember we talked about salt). For random generation of salt or IV, use AGRandomGenerator. By default, AGRandomGenerator generates 16 bytes key, but you can also specify the length if you wish.
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    
    _salt = [defaults objectForKey:@"xmas.salt"];
    
    if(!_salt) { // if first launch, initialize params for subsequent reads
        _salt = [AGRandomGenerator randomBytes];
        [defaults setObject:_salt forKey:@"xmas.salt"];
        [defaults synchronize];
    }

You need to store your salt to be able to regenerate the exact same key when you want to decrypt this description information. In this example, we've chosen to store this information in NSUserDefaults.

Encrypt


Once you've got your encryption key, use AGCryptoBox to do the actual encryption. With AGCryptoBox, you can encrypt/decrypt data using your encryption key and a randomly generated IV as shown below:
 -(void) saveAndEncryptData:(id)gift withPassword:password {
     // Generate key from password
     NSData* key = [self getKeyFromPassword:password];
     
     // Use CryptoBox to encrypt/decrypt data
     AGCryptoBox* cryptoBox = [[AGCryptoBox alloc] initWithKey:key];
     
     // transform string to data
     NSData* dataToEncrypt = [gift[@"description"] dataUsingEncoding:NSUTF8StringEncoding];
     
     // encrypt data
     gift[@"description"] = [cryptoBox encrypt:dataToEncrypt IV:_IV];
     
     // Store data with encrypted description
     [_store save:gift error:nil];
     
     [self.gifts addObject:gift];
 }
Same as for the salt, IV need to be store to be able to decrypt the encrypted data. We'll put it into NSUserDefaults too.

Decrypt


To be able to decrypt, fetch salt, prompt the user for password, regenerate the encryption key. Fetch IV data and decrypt!
 -(NSString*)decrypt:(NSData*)data {
     NSData* key = [self getKeyFromPassword:_password];
     AGCryptoBox* cryptoBox = [[AGCryptoBox alloc] initWithKey:key];

     return [[NSString alloc]
             initWithData:[cryptoBox decrypt:data IV:_IV] encoding:NSUTF8StringEncoding];
 }

That's all folks!
If you want to see it all in action, git clone cookbook, go to xmas app and pod install it :)

Saturday, November 23, 2013

Storyboard and unwind segue

With iOS 5, storyboards made their entrance, with iOS6 they went popular and with iOS7, there're well settled. I've sparely used storyboard in the past and when a friend of mine told me about unwind segue, I thought it was time to revisit it. Here's my story:

A bit of history


First there was Interface Builder


Interface Builder (IB) allows you to work on a graphical interface to define you app layout and components. Customising a table view cell through IB saves you tone of UI code that clutters your app.

Does IB generate code behind the scene? Not quite, it's not really code that is generated when you use storyboards or nibs. The views are encoded into a binary file (using NSCoder) and decoded at runtime. Think of it as the objects being created and frozen in Interface Builder, then defrosted during runtime.

Then came Storyboard


Storyboard goes one step further...

As the name said it all, it's about putting the story of your app on a board. With IB you can work with one view, with storyboard you can have multiple views on a same board. It introduces segues. Segues represent transitions between screens. Opening a storyboard and your have pretty good idea of the UI flow at a glance. In XCode 5, application templates scaffold storyboard by default (no check box to ask you). So when I switch to iOS7, I thought it was time to give storyboards another trial and I had a perfect use case for that.

On the AeroGear project, we have a great Android Cookbook where you demo the features of the libraries without being cluttered by too much UI code. I thought having a version for iOS will be wonderful.

Storyboard and its segue


So I settled on writing one and I thought it was a great use case for using storyboard. I was new to it, I already tried and actually blog about it here. Coding with storyboard I've discovered unwind segue and I love it. You can replace delegate with unwind segues. Making even less to write.

Let's see it with an example


Taken from iOS cookbook, Xmas is a short example where we have 2 view controllers: "Gifts list" controller (let's name it VC1) and "Add present" controller (VC2) as shown in XCode storyboard.



We are going to create a segue from scene one (list controller) to scene two (add present), implementing prepareForSegue:sender: in VC1.

Going from VC1 to VC2


In storyboard with the magic keys combinaison ctrl+drag from VC1 to VC2, choose the push segue. In the code implement prepareForSegue:sender: to move data from VC1 to VC2:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
 if ([segue.identifier isEqualToString:@"addPresent:"]) {
        // nothing to do
 }
    if ([segue.identifier isEqualToString:@"updatePresent:"]) {
        // pass selected gift from VC1 to VC2
        AGAddPresentViewController* destinationController = segue.destinationViewController;
        destinationController.toWhomTextField.text = [_store read:_currentGiftId];
 }
}
But what about transitioning and sending context back in the other direction? with iOS 6, we have a new technique named unwind segues...

Going back: VC2 to VC1


Now you add a new present and you want to be able to hist save and go back to the list controller. Prior to iOS6, going back was implemented using well known Delegate approach. With iOS6, we can do it with unwind segue. In you VC1 controller (the controller you want to unwind to), you have implement an IBAction method with one parameter segue, called it whatever you want. Then, from the story board ctrl+drag from ViewController to its exit icon. Xcode gives you a list of possible unwind methods (here we have implemented only one), choose it and you're done!
-(IBAction)unwindToRootVC:(UIStoryboardSegue *)segue {
    AGAddPresentViewController* source = segue.sourceViewController;
    
    // Get data from source
    NSMutableDictionary* dict = [[NSMutableDictionary alloc] init];
    dict[@"toWhom"] = source.toWhomTextField.text;
    dict[@"description"] = source.description.text;
    
    // save data in the list
    [self saveData:dict withPassword:source.password.text];
    [self.collectionView reloadData];
}
Elegantly in a few lines of code and some ctrl drag and drop magic we've got everything settled. You can find the complete code for this example in my github repository.