[guardian-dev] CacheWord Key Derivation

Abel Luck abel at guardianproject.info
Tue Mar 18 07:27:25 EDT 2014

Hans-Christoph Steiner:
> On 03/17/2014 08:38 AM, Abel Luck wrote:
>> Daniel McCarney:
>>> On 16/03, Nathan of Guardian wrote:
>>>> On 03/13/2014 10:46 PM, Stephen Lombardo wrote:
>>>>> I do have one concern with the key derivation implementation. From the
>>>>> code in PassphraseSecrets.java and Constants.java, CacheWord seems to be
>>>>> using only 100 PBKDF2 iterations on the user provided key and a raw key
>>>>> with SQLCipher. This seems lower than it should be to support production
>>>>> applications using the library on real data, weakening the default
>>>>> protections that SQLCipher provides and users have come to expect.
>>>> I know the 100 iterations value was a decision made by Abel early on,
>>>> though we also wanted it to be configurable. I am hoping he will respond
>>>> to this thread shortly, though he is in transit at the moment.
>>> I believe the concern is with older devices. Increasing the PBKDF2
>>> iterations will create noticeable lag on devices with lower end
>>> processors. I agree that 100 iterations is probably overly conservative
>>> to be the default across the board.
>>> Maybe we should solicit some test data from a range of devices?
>> Indeed. This was the original concern. I adopted the 100 iteration value from TextSecure,
>> and tested the value on several very low end android phones bought in Turkey and found
>> that the lag was unbearable.
>> However, since then we've questioned whether its worth supporting such devices at all.
>>>>> Has there been any thought given to increasing the key derivation
>>>>> iterations? It would be great to see something equivalent to the
>>>>> SQLCipher default of 64K in the near future. That would make it easier
>>>>> to recommend CacheWord without caveats about weakening overall
>>>>> solution security.
>>>> It seems quit easy to make the option configurable, and then the
>>>> developer could tune the user experience, as they wish. Any thoughts on
>>>> the performance impact that might have?
>>> Long term I think the best bet is making it adaptive and set during the
>>> initial passphrase registration. Abel identified that as one of the
>>> project TODOs[0].
>>> On first run the lib could perform measured PBKDF2 runs with the
>>> iterations increasing from the default. When the PBKDF2 wallclock
>>> runtime reaches a threshold that we think is an unacceptable delay (1s?
>>> 2s?) the iteration count would be fixed and used for user key
>>> derivation.
>> Exactly. Work on an adaptive iteration count has been started already, with a POC by
>> another dev [1]. But the code quality is poor and needs to be entirely rewritten for more
>> general application. This approach while ideal, is fraught with complications, namely that
>> there is a large variance in calculated values due to existing system load. Of course any
>> value is liable to be larger and better than 100.
>> An alternative to the live-adaptive algorithm would be to use one of those android cloud
>> mass-device testing services like appthwack.com or testdroid.com and include
>> per-calcualted values for various devices with either a hardcoded or adaptive fallback.
>> Anyways, to address this issue immediately I'll assume we're targeting a decently powerful
>> device, and bump the value to 64,000, while making the value configurable for the dev and
>> provide a migration route to rekey existing databases.
>> ~abel
>> [1] https://github.com/abeluck/PBEKeyTester
> Hey Abel,
> Good to see you back on this list!
> How is the iteration count stored as part of the data?  Its a field in the
> cacheword key file, right?  I think we need to be careful about tying the
> database too much to the current config, that will only be available on that
> device.  This is necessary for backups, moving to new devices, upgrading to
> new versions of cacheword, sqlcipher, etc.

This is definitely a concern.

As for the what data is stored and the structure of that data, see the inner class
SerializedSecretsV1 in PassphraseSecrets.java:265. The current layout is:

{ int      version     // currently == 0
  byte[16] salt;
  byte[12] iv
  byte[?]  ciphertext

As you can see we already need to store a few values to decrypt the payload. Adding an
iteration count to this would result in:

{ int      version        // ++current
  int      iteration_count
  byte[16] salt;
  byte[12] iv
  byte[?]  ciphertext

> We do want to be able to support as old and weak devices as possible, in
> general.  Most of the world is on such devices.  Something like Storymaker or
> InformaCam do only target high end devices, but ChatSecure, NoteCipher, etc.
> work on a wide range of devices.

This was the reason I left the initial iteration count at 100, which was obviously a bad
choice. We shouldn't just pick some value like 100 or 64k and hope for the best, hence my
idea to get empirical data using one of those cloud services.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: OpenPGP digital signature
URL: <http://lists.mayfirst.org/pipermail/guardian-dev/attachments/20140318/59801fbd/attachment.pgp>

More information about the Guardian-dev mailing list