Statistics
| Branch: | Tag: | Revision:

cacheword / README.md @ 09e56b5b

History | View | Annotate | Download (17.5 KB)

1
CacheWord
2
=========
3

    
4
CacheWord is an Android library project for passphrase caching and management.
5
It helps app developers securely generate, store, and access secrets derived
6
from a user's passphrase.
7

    
8
**CacheWord is still under development. Proceed with caution**
9

    
10
Broadly speaking this library assists developers with two related problems:
11

    
12
1. Secrets Management: how the secret key material for your app is generated,
13
   stored, and accessed
14
2. Passphrase Caching: store the passphrase in memory to avoid constantly
15
   prompting the user
16

    
17
CacheWord manages key derivation, verification, persistence, passphrase
18
resetting, and caching secret key material in memory.
19

    
20
**Features:**
21

    
22
* Strong key derivation (PBKDF2)
23
* Secure secret storage (AES-256 GCM)
24
* Persistent notification: informs the user the app data is unlocked
25
* Configurable timeout: after a specified time of inactivity the app locks itself
26
* Manual clearing: the user can forcibly lock the application
27
* Uses Android's Keystore on 4.x if available - *Not Yet Implemented*
28

    
29
CacheWord requires at least SDK version 2.3.1 (API level 9)
30

    
31
**Issues & Support**
32

    
33
* Bug? Please report any issues at [our project issue tracker][issues], no
34
account required!
35
* Questions? Find us on [IRC or our mailing list](https://guardianproject.info/contact)
36

    
37

    
38
# Table of Contents
39

    
40
- [CacheWord](#user-content-cacheword)
41
- [Table of Contents](#user-content-table-of-contents)
42
- [Setup](#user-content-setup)
43
	- [Dependencies](#user-content-dependencies)
44
- [Integration](#user-content-integration)
45
	- [Implementing ICacheWordSubscriber](#user-content-implementing-icachewordsubscriber)
46
	- [Instantiate CacheWordHandler and propagate lifecycle Changes](#user-content-instantiate-cachewordhandler-and-propagate-lifecycle-changes)
47
- [Common Usage Questions](#user-content-common-usage-questions)
48
	- [How do I configure CacheWord?](#user-content-how-do-i-configure-cacheword)
49
	- [How do I use CW with SQLCipher & IOCipher?](#user-content-how-do-i-use-cw-with-sqlcipher--iocipher)
50
	- [What Are These Cached Secrets?](#user-content-what-are-these-cached-secrets)
51
	- [How does CacheWord work with background services?](#user-content-how-does-cacheword-work-with-background-services)
52
- [Security Design Notes](#user-content-security-design-notes)
53
	- [Threat Model](#user-content-threat-model)
54
	- [Key Derivation and Encryption Key Generation](#user-content-key-derivation-and-encryption-key-generation)
55
	- [Managing Key Material Securely in Memory](#user-content-managing-key-material-securely-in-memory)
56
	- [Official Authorities On The Use of String](#user-content-official-authorities-on-the-use-of-string)
57

    
58

    
59
# Setup
60

    
61
**add to your gradle build**
62

    
63
CacheWord now is distributed as a pure JAR file.  You can add it using gradle:
64

    
65
    compile 'info.guardianproject.cacheword:cachewordlib:0.1'
66

    
67

    
68
**(Eclipse) Import into your workspace**
69

    
70
Before we begin, download CacheWord and import it into your Eclipse workspace.
71
Then add it as a library project to your project in eclipse.
72

    
73
    Project Properties > Android > (Library) Add
74

    
75
**(Ant) Add the library project to your project.properties**
76

    
77
To add this to you project, include something like this in your
78
`project.properties`:
79

    
80
```
81
android.library.reference.1=../CacheWord/cachewordlib
82
```
83

    
84
To build with ant, you need to run `./setup-ant` inside the `CacheWord/`
85
folder.  For more information please see the
86
[Android developer guide][libguide] for referencing library projects.
87

    
88
**Edit your `AndroidManifest.xml`**
89

    
90
You can use the the "manifest merging" feature of recent Android ADT releases
91
to get the required meta data into your project.  That is done by adding this
92
to your project's `project.properties`:
93

    
94
```
95
manifestmerger.enabled=true
96
```
97

    
98
Otherwise, you can manually add the metadata by copying and pasting the
99
relevant bits from `cachewordlib/AndroidManifest.xml`.
100

    
101

    
102
## Dependencies
103

    
104
* Android support library v4 (`android-support-v4.jar`; included)
105
* [SQLCipher for Android >= v3.0.2][sqlcipher] (included)
106

    
107
CacheWord provides a support class for SQLCipher for Android. You probably want
108
to use this.
109

    
110
Download the [SQLCipher for Android v3.0.2 release][sqlcipher] and copy the `libs/`
111
and `assets/` dir into your Android project dir.
112

    
113

    
114
# Integration
115

    
116
A CacheWordSubscriber is any component in your application interested in the
117
secrets managed by CacheWord. Such components may be:
118

    
119
* Initialization Activity
120
* Login Activity
121
* Any Activity that handles sensitive data
122
* Encryption/Decryption wrappers
123
* SQLCipher Database Helper
124
* IOCipher Virtual File System
125
* etc.
126

    
127
For each of these interested components you *must* implement two things
128

    
129
1. Implement the `ICacheWordSubscriber` interface
130
2. Instantiate a `CacheWordHandler` to assist the component
131

    
132
## Implementing `ICacheWordSubscriber`
133

    
134
The `ICacheWordSubscriber` interface consists of three event methods.
135

    
136
These event methods are similar to the Android lifecycle methods onResume,
137
onPause, etc. The appropriate event is guaranteed to be called for every
138
CacheWord enhanced Activity during the onResume method when then lifecycle
139
change is propagated correctly (see below). This ensures your Activities will
140
always be aware of the current status of CacheWord.
141

    
142
In most applications, your state and view handling code that usually goes
143
in `onResume` and `onPause` should instead go in one of the CacheWord event
144
methods.
145

    
146
1. **onCacheWordUninitialized**
147

    
148
    This event is called when CacheWord determines there is no saved state.
149
    Usually this occurs the first time the user runs your app. At this point there
150
    should be no sensitive data stored, because there is no secret to encrypt it
151
    with.
152

    
153
    In this event you should prompt the user to create a password and the pass the
154
    new password to CacheWord with `setCachedSecrets()`.
155

    
156
    This event could also be triggered after the Application's data is cleared or reset.
157

    
158
2. **onCacheWordLocked**
159

    
160
    This event signifies the secrets are unavailable or have become unavailable.
161
    It is triggered when the secrets expiration timeout is reached, or the user
162
    manually locks CacheWord.
163

    
164
    You should clear all UI components and data structures containing sensitive
165
    information and perhaps show a dedicated lock screen.
166

    
167
    At this stage your app should prompt the user for the passphrase and give
168
    it to CacheWord with `setCachedSecrets()`
169

    
170
3. **onCacheWordOpened**
171

    
172
    This event is triggered when CacheWord has received *valid* credentials via the
173
    `setCachedSecrets()` method.
174

    
175
    At this stage in your app you may call `getCachedSecrets()` to retrieve the
176
    unencrypted secrets from CacheWord.
177

    
178
**Example:**
179

    
180
```java
181
public class MyActivity extends Activity implements ICacheWordSubscriber
182
{
183

    
184
    ...
185

    
186
    @Override
187
    public void onCacheWordUninitialized() {
188
        startCreatePassphraseActivity();
189
    }
190

    
191

    
192
    @Override
193
    public void onCacheWordLocked() {
194
        clearUi();
195
        startPassphrasePromptActivity();
196
    }
197

    
198
    @Override
199
    public void onCacheWordOpened() {
200
        decryptDataAndPopulateUi(mCacheWord.getEncryptionKey());
201
    }
202

    
203
    ...
204
}
205

    
206
```
207

    
208
## Instantiate CacheWordHandler and propagate lifecycle Changes
209

    
210
`CacheWordHandler` is the class instantiated by any object interested in
211
receiving CacheWord events. It does the heavy lifting of starting, connecting,
212
and communicating with the `CacheWordService`. Each object that wants to be aware
213
of CacheWord events should instantiate its own `CacheWordHandler`.
214

    
215
It is your object's responsibility to call
216
`CacheWordHandler.connectToService()` and `CacheWordHandler.disconnectFromService()` when
217
your object wants to register and unregister from event notifications.
218

    
219
Disconnecting is important, because CacheWord maintains a list of connected
220
clients and will not initiate the automatic timeout until all the connected
221
clients have disconnected.
222

    
223
```java
224

    
225
class YourClass implements ICacheWordSubscriber
226
{
227
        ...
228
        private CacheWordHandler mCacheWord;
229
        ...
230
        public YourClass() {
231
            ...
232
            mCacheWord = new CacheWordHandler(mContext, this);
233
            mCacheWord.connectToService()
234
            ...
235
        }
236

    
237
        // Called when your object no longer wants to be notified of CacheWord events
238
        public goodbyeYourClass() {
239
            mCacheWord.disconnect()
240
        }
241
        ...
242
}
243
```
244

    
245

    
246
# Common Usage Questions
247

    
248
## How do I configure CacheWord?
249

    
250
Configuration is entirely optional as sane defaults are provided for every
251
option.
252

    
253
For compile time configuration options, define the resources in XML (see
254
[`res/values/cacheword.xml`](cachewordlib/res/values/cacheword.xml) for the
255
available options).
256

    
257
To configure the XML resources, simply copy cacheword.xml into your own
258
`res/values` directory and edit the settings as you like.
259

    
260
Runtime configuration options can be set via the CacheWordSettings object.
261

    
262
Configurable options are:
263

    
264
* Whether to show a persistent unlocked notification
265
* Display options for the notification (title, message, icon, etc)
266
* Intent executed when the notification is clicked
267
* Timeout length after your app leaves the foreground
268
* Vibration on successful unlock
269
* PBKDF2 Calibration settings and minimum iteration count
270

    
271
## How do I use CW with SQLCipher & IOCipher?
272

    
273
If you use SQLCipher for encrypted database storage you should use CacheWord's
274
`SQLCipherOpenHelper`. See the [NoteCipher application][notecipher] for an
275
example of how to use it.
276

    
277
Likewise if you use IOCipher for encrypted file storage you should use CacheWord's `IOCipherHelper`.
278

    
279
TODO: make example of IOCipherHelper
280

    
281
## What Are These Cached Secrets?
282

    
283
The sensitive data that is cached by CacheWord can be specified by the user as
284
a class implementing `ICachedSecrets`.
285

    
286
The default implementation of this class (`PassphraseSecrets`) attempts to
287
provide for most use cases. It generates a 256 bit encryption key that can be
288
used by other libraries like [SQLCipher][sqlcipher] or [IOCipher][iocipher]
289

    
290
In this case the user's password is used to encrypt (after being hashed of
291
course) the generated encryption key, and is never written to disk.
292

    
293
## How does CacheWord work with background services?
294

    
295
Many apps will perform operations in the background that require access to
296
sensitive data, even though the user may not be actively using the app. These
297
services will require access to the cached secrets in order to write to the
298
database, update internal structure, etc.
299

    
300
For example, a chat application will run a service in the background to check
301
for new messages on the wire, and then write them to the database.
302

    
303
Since the background service needs access to the cached secrets, the app must
304
remain unlocked. If the configured timeout occurs, the CacheWord will lock, and
305
the background service will be unable to do its job.
306

    
307
If the user closes the app, they may well expect it to be locked, after all
308
they aren't using it and they want to protect their data, but, in the case of
309
the messenger app, they will still want to be notified when a new message arrives.
310

    
311
The results in inconsistent expectations, you can't lock the app without
312
shutting down the background service, but you need the background service
313
running to provide some basic functionality.
314

    
315
How this is handled in your app depends on what your background service is
316
doing.
317

    
318
If the user expects your app to do something in the background and notify them,
319
then you will need to disable the auto-timeout in CacheWord. Likewise, if the
320
user locks the app, they should be aware that they will be disabling any
321
background functionality.
322

    
323
You might be tempted to cache the secrets yourself, in an global variable or
324
singleton, so that your app can appear to be locked (the user has to enter a
325
passphrase), but the background service can still work. *This is a bad idea!*
326
By doing this you lose the secure memory handling CacheWord employs, and negate
327
much of the benefit derived from using CW.
328

    
329
The `CacheWordHandler.detach()` and `reattach()` methods are available, which
330
will allow your background service to receive CW events but not be counted
331
among the connected clients when the automatic lock timeout occurs. In other
332
words, the background service won't prevent the lock timeout from happening if
333
it is still running. Your service should properly handle Lock events, even if
334
it is in the middle of a running operation.
335

    
336

    
337

    
338
# Security Design Notes
339

    
340
The goal of CacheWord is to provide easy and secure "secrets" protection for
341
Android developers. By "secrets" we mean sensitive key material such as
342
passwords and encryption keys. We specifically exclude sensitive application
343
data (such as the data encrypted by said keys) from secrets we aim to protect.
344

    
345
## Threat Model
346

    
347
CacheWord assumes three distinct adversaries.
348

    
349
1. **The Developer**
350

    
351
  If the developer has malicious intentions, everything we do is bust. Instead,
352
  we aim to mitigate weaknesses posed by a careless or ignorant developer.
353
  
354
  Tactics:
355
  * Hide all crypto decisions
356
  * Use secure defaults
357
  * Provide support classes for commonly used libraries that consume secret key material (e.g., SQLCipher)
358

    
359
2. **The User**
360

    
361
  Once again the if user is intentionally trying to disclose secret key material,
362
  it is unlikely we can stop her. We do not think this is a common case however.
363
  Most users will unintentionally harm their security due to usability issues.
364
  
365
  For example, typing a password with *sufficient* entropy on a smartphone's soft
366
  keyboard is a severe pain in the ass for all but the most proficient of tween
367
  txtrs. Even this speedy group will grow weary when their phone prompts them for
368
  the password every time they pull it out of their pocket. Unsurprisingly, users
369
  choose short, low entropy passwords.
370
  
371
  Users often reuse passwords, so the protection of their password should be
372
  considered more important than an application specific encryption key.
373
  
374
  Tactics:
375
  * Sane cache timeouts
376
  * Password hashing using a strong KDF (PBKDF2, and hopefully scrypt soon)
377
  * Adaptive KDF iterations
378

    
379
3. **The Bad Guys**
380

    
381
  The Bad Guys consist of a number of potential adversaries, such as forensic analysts,
382
  cops or border agents with [plug-n-pwn data suckers][cellibrite], and malware.
383
  
384
  Their common capability in our case is access to our application's binary,
385
  memory and disk. They probably have root access too. Strictly speaking, given
386
  an attacker with sufficient patient and skill, our secrets will become theirs.
387
  
388
  That said, we strive to make key recovery from memory as difficult as possible.
389
  
390
  When it comes to non-memory based attacks, such as brute force attacks on our
391
  persisted data, we employ strong authenticated encryption and reasonable KDF
392
  parameters.
393
  
394
  Tactics:
395
  * Aggressive zeroizing
396
  * Using native memory (non-VM) when possible to void the GC (?)
397
  * Never store the password in any form on disk (even a hash)
398

    
399

    
400
## Key Derivation and Encryption Key Generation
401

    
402
The sensitive data that is cached by CacheWord can be specified by the developer as
403
a class implementing ICachedSecrets.
404

    
405
The default implementation of this class (PassphraseSecrets) attempts to
406
provide for most use cases. It generates a 256 bit encryption key that can be
407
used by other libraries like SQLCipher or IOCipher.
408

    
409
To initialize the secret we do the following:
410

    
411
1. Run the password through PBKDF2 with a random 16 byte salt
412
2. Generate a random 256 bit AES key with a random 96 bit IV
413
3. Use the derived key to encrypt the generated key in GCM mode
414
4. Write the ciphertext, iv, salt, and a version tag to disk ([SharedPreferences][sharedprefs])
415

    
416
Password verification and decryption of the AES key follows the same procedure:
417

    
418
1. Read the ciphertext, iv, salt, and version tag from disk
419
2. Run the password through PBKDF2 with the salt
420
3. Attempt to decrypt the ciphertext with the derived key and read iv
421

    
422
If the GCM operation succeeds, the password is verified and the encryption key
423
can be read. If the operation fails, either the password is incorrect or the
424
ciphertext has been modified.
425

    
426
TODO number of PBKDF iterations
427

    
428
## Managing Key Material Securely in Memory
429

    
430
TODO: write some bits about secrets in memory
431

    
432
## Official Authorities On The Use of `String`
433

    
434
The [Java Cryptography Architecture guide][java-crypto-arch] states,
435

    
436
> It would seem logical to collect and store the password in an object of type
437
> java.lang.String. However, here's the caveat: Objects of type String are
438
> immutable, i.e., there are no methods defined that allow you to change
439
> (overwrite) or zero out the contents of a String after usage. This feature
440
> makes String objects unsuitable for storing security sensitive information such
441
> as user passwords. You should always collect and store security sensitive
442
> information in a char array instead.
443

    
444
Yet, the [Secure Coding Guidelines for the Java Programming Language][java-secure-coding] counters,
445

    
446
> [...]Some transient data may be kept in mutable data structures, such as char
447
> arrays, and cleared immediately after use. Clearing data structures **has reduced
448
> effectiveness** on typical Java runtime systems *as objects are moved in memory
449
> transparently to the programmer.*
450

    
451
**Conclusion:** In Java, even char[] arrays aren't a good storage primitive.
452

    
453

    
454

    
455
[notecipher]: https://github.com/guardianproject/notecipher/
456
[sqlcipher]: https://www.zetetic.net/sqlcipher/open-source
457
[iocipher]: https://guardianproject.info/code/IOCipher
458
[issues]: https://dev.guardianproject.info/projects/cacheword/issues/new
459
[libguide]: http://developer.android.com/guide/developing/projects/projects-cmdline.html#ReferencingLibraryProject
460
[sharedprefs]: https://developer.android.com/guide/topics/data/data-storage.html#pref
461
[java-crypto-arch]: http://docs.oracle.com/javase/6/docs/technotes/guides/security/crypto/CryptoSpec.html#PBEEx
462
[java-secure-coding]: http://www.oracle.com/technetwork/java/seccodeguide-139067.html#2
463
[cellibrite]: http://www.cellebrite.com