Here’s the contents of the presentation i gave last night at cocoaheads sydney, for anyone who’s interested. Exclamation marks are slide separators, to suit my presentation app, Impromptu (

Also the source can be found here:

Skeleton Key

* Dropbox
* Cryptography
* Marketing



* Background sync
* Fully automatic
* Suppresses errors
* One folder, yaml files


Sync strategy

* Compare folders
* Both, same: nothing
* Both, different date: newer wins
* Different: depends on last sync state



If missing locally:

Present at last sync = it's been deleted locally, so delete remotely

Missing at last sync = it's been added remotely, so download.


Different 2

If missing remotely:

Present at last sync = it's been deleted remotely, so delete locally

Missing at last sync = it's been added locally, so upload.


Edge cases

Since the last sync data is only ever used to justify a
deletion, safe to clear it any time to avoid edge cases.

Eg clearing dropbox, linking, unlinking.



* Master password is validated using bCrypt
* All passwords are encrypted by AES
* The AES key is derived from the master pass using PBKDF2



Only used to verify the master pass, nothing else. One way
slow hash designed to not be GPU-able.

Uses JFBCrypt:

5 rounds takes ~0.1s on iPhone 4


Storing a password

    salt = [JFBCrypt generateSaltWithNumberOfRounds:5];
    hash = [JFBCrypt hashPassword:clearPassword withSalt:salt];

Store both the above strings



    test = [JFBCrypt hashPassword:clearPassword
    valid = [test isEqualToString:hash];



An industry-standard (eg OpenSSL) way to derive a key
from a passphrase/word.

Using Security framework, and CommonCrypto/CommonKeyDerivation.h

We're making a 32byte / 256bit key.



So that we know how many rounds to make it take ~0.1s:

    int rounds = CCCalibratePBKDF(kCCPBKDF2,
       clearPassword.length, keySalt.length,
       kCCPRFHmacAlgSHA256, 32, 100);



    - (NSData*)generateSalt256 {
        unsigned char salt[32];
        for (int i=0; i<32; i++) {
            salt[i] = (unsigned char)arc4random();
        return [NSData dataWithBytes:salt length:32];



    NSData* myPassData = [clearPassword

    unsigned char rawKey[32];
    CCKeyDerivationPBKDF(kCCPBKDF2, myPassData.bytes,
        myPassData.length, keySalt.bytes, keySalt.length,
        kCCPRFHmacAlgSHA256, rounds, rawKey, 32);
    return [NSMutableData dataWithBytes:rawKey length:32];



Also using Apple's Security framework's CommonCrypto

Using NSData+CommonCrypto helpers:



    - (NSString*)encrypt:(NSString*)clear {    
        NSData* clearData = [clear

        NSData* crypto = [clearData
            AES256EncryptedDataUsingKey:key error:nil];

        return [crypto base64EncodedString];



    - (NSString*)decrypt:(NSString*)crypto {
        NSData* cryptoData = [NSData

        NSData* clearData = [cryptoData

        return [[NSString alloc] initWithData:clearData



* Nobody responds to requests for reviews.
* Ads driving people to your promo-site costs more than income.
* Promo site with videos, screenshots, and features.
* Sells best when free!


So I got some advice..

Patio11 (HN)


Next time

* Find popular forum
* Working with them, make app
* Make placeholder page, collect emails, have shareables
* Determine if worth proceeding
* Attract via forums and ads
* Emails with updates
* Done
* Post launch, still interact, and email updates
* Emails link to forum for discussion


Please visit



Thanks for reading! And if you want to get in touch, I'd love to hear from you: chris.hulbert at gmail.

Chris Hulbert

(Comp Sci, Hons - UTS)

iOS Developer (Freelancer / Contractor) in Australia.

I have worked at places such as Google, Cochlear, Assembly Payments, News Corp, Fox Sports, NineMSN, FetchTV, Coles, Woolworths, Trust Bank, and Westpac, among others. If you're looking for help developing an iOS app, drop me a line!

Get in touch:
[email protected]

 Subscribe via RSS