41
•
Input: The stable password including serves as the input secret for PBKDF2.
•
Salt: A randomly generated 256-bit value (via the platform's secure PRNG)
serves as the PBKDF2 salt. This meets the recommended minimum requirement of
128-bit salt as specified in NIST SP-800-132.
•
Rounds: PBKDF2 is executed with an enforced minimum of 40k rounds,
resulting in an approximately 1 second runtime on an iPhone 4S.
A future update to this specification may include support for automatic upwards
adjustment of PBKDF2 rounds based on the results of local device calibration, as to
help ensure that VDE password-based key derivation maintains pace with hardware
advances. This feature has been excluded from this release, as further consideration
must be given to the result of local calibration when sharing documents across
hardware with widely disparate performance profiles, such as a desktop computer
and mobile device.
Additionally, we plan to investigate the use of scrypt, which is designed to be both
computationally and memory intensive, increasing the costs involved in GPU or
specialized ASIC-based password cracking.
Implementation Note: Safely Deriving Two Keys
It is important to note that we intentionally do not derive more data than is "natively"
available via PBKDF2-HMAC's' block size; to do so would increase our total work
cost, but not necessarily that of an attacker. To understand why this is one must look
at PBKDF2.
To derive additional blocks, PBKDF2 runs the full key derivation with the block's
index (0, 1 ...) concatenated with the salt. Derivation of later blocks is not dependent
on the output of earlier derivations, which means that each block of output can be
derived independently of the others.
If we used PBKDF2-HMAC-SHA256 and requested 512-bit of output, PBKDF2 would
thus be run twice, concatenating the 256 bits generated from each block of output to
produce the final 512-bit result. This would double our work load by doubling the
number of key derivations that must be run, requiring that we decrease the total
number of PBKDF2 iterations to keep the CPU cost within acceptable bounds.
An attacker, however, does not necessarily need both of the keys. If we use only the
first 256 bits for an encryption key, and the latter 256 bits for an authentication key,
the attacker can simply ignore the second round used to derive the authentication
key, which is not needed to perform decryption. As a result, the attacker would be
able to do half as much work as a legitimate user -- a significant improvement in the
runtime of a brute-force password cracker.
Encryption Specification
144
40
As such, we're careful to request no more than the native block size when using
PBKDF2 key derivation in VDE.
2.2.2 Non-Password Key Derivation
Non-password key derivation is used to derive multiple keys from an existing source
of cryptographically strong keying material; appropriate source material includes
keys generated from a secure PRNG or derived from PBKDF2.
There are two mechanisms that may be used in VDE to derive multiple keys from an
existing source of cryptographically strong keying material:
•
Non-overlapping segments of an existing key may be used to derive 2 or
more keys, limited by the size of the original keying material.
•
HKDF may be used to derive any number of sub-keys.
Both mechanisms are used in different contexts; the use of non-overlapping
segments is primarily useful for allowing derivation of both an encryption key and an
HMAC secret for use with ETM-AEAD.
Extraction of Disjoint Key Material (DKM)
Given input key material of length n, two or more keys (or other types of secret
parameters, such as a secret IV) may be derived from the input key by extracting
disjoint (non-overlapping) segments of the key material, not to exceed n in total
length. This conforms to the recommendations in NIST SP-800-108 Section 7.3,
Converting Keying Material to Cryptographic Keys.
For example, to derive both an encryption and authentication key from an existing
512-bit key:
•
The first 256 bits may be used directly as a 256-bit symmetric encryption
key.
•
The latter 256 bits may be used directly as a 256-bit authentication (e.g.,
HMAC) secret.
Note the following requirements, as per NIST SP-800-108:
•
The segments from which keys are derived must not overlap; that is, no
element of the source keying material may be used for more than a single sub-key.
•
As implied by the first requirement, the total length of the derived sub-keys
must not exceed the total length of the source keying material.
HMAC-based Extract-and-Expand Key Derivation Function (HKDF)
Encryption Specification
145
44
HKDF may be used to derive an arbitrary number of sub-keys from existing
cryptographically strong keying material; appropriate source material includes keys
generated from a secure PRNG or derived from PBKDF2.
VDE extends the HKDF specification with the following implementation requirements:
•
A non-empty salt value is required; as per the recommendations in RFC
5869, the salt length MUST be equal to the HKDF hash function's output length, and
a single salt MAY be re-used deriving multiple keys from a single set of source keying
material. The salt value may either be randomly generated, in which case it may be
considered a public value, or it may be derived using a VDE-approved KDF.
•
The HKDF input key material must be generated using a VDE-approved key
generation or derivation mechanism. Additionally, any non-derived keys (such as
randomly generated keys) used as input key material must be protected using an
authenticated encryption scheme -- see also Section 2.2.3, Generated Random Keys.
•
A non-empty info parameter must be supplied to HKDF; this may be any
arbitrary set of octets, but the value MUST be unique for a given sub-key
instantiation as to guarantee that sub-key values are not re-used.
2.2.3 Generated Random Keys
A VDE key may be generated directly from a cryptographically strong (P)RNG; the
resulting key must be protected via an authenticated encryption scheme.
3. VDE Serialization
This section defines VDE's key and data serialization formats and on-disk storage
mechanisms. VDE item serialization is optimized for use in file-based storage of
atomically updated byte streams, in a manner suitable for use via VoodooPad's
existing document format. VDE serialization leverages the ETM-AEAD algorithm and
serialization mechanism as defined by the
ETM-AEAD v1 Specification.
VDE item serialization is designed such that:
•
When full document encryption is used, a new Data Protection Key (DPK)
must be generated randomly for every encryption operation; the DPK is to be
protected with a key securely derived from the document's current password. This
ensures that access to a previous version of a document does not expose
decryption keys that may be used to decrypt later versions of that document.
•
All data necessary to perform decryption and authentication of a file --
including the DPK -- is stored within that file; no interdependent state exists across
multiple files. This is necessary to support the use of asynchronous distributed file
synchronization systems, such as Dropbox, where atomicity is only guaranteed at
the level of individual files.
Encryption Specification
146
61
•
Any metadata that may require updating is appended to the serialized
output, ensuring that it can be replaced with additional metadata without requiring
rewriting of the entire file.
3.1 Full Document Encryption
To implement full encryption of all document data, it is necessary that encryption and
authentication be performed on all document resources. The following is an itemized
list of resource types within a VoodooPad document:
•
Document metadata, located at the top-level of the document bundle:
•
tags.plist
: Page tags.
•
properties.plist
: Document-level properties and preferences.
•
storeinfo.plist
: Document format metadata, including the
document's UUID, compatibility version, and legacy VoodooPad encryption
metadata.
•
vde.plist
: Encryption session and parameter information for full-
document cryptography (refer to section 3.1.1).
•
Page data, located in a pool of subdirectories within pages/[a-z0-9]/:
•
<page uuid>.plist
: Per-page metadata
•
<page uuid>
: Page data
The session data in
vde.plist
contains only non-private key derivation parameters,
and is both unencrypted and unauthenticated. All other resources are encrypted and
authenticated using the Item Encryption mechanism defined in Section 3.3.
PLAUSIBLE TODO: In the current document format,
storeinfo.plist
is left
unauthenticated and unencrypted. To resolve this -- and given that the new
cryptography necessarily breaks backwards compatibility anyway -- we need to
bump the VoodooPadBundleVersion (but only for encrypted documents) to allow
legacy releases to provide a useful error message, and use the DMK to perform
encryption/decryption/authentication of all other data in the plist.
Warning: Locally-generated unique resource identifiers (UUIDs) are exposed to
potential attackers via the document's page resource file names. While these
identifiers are randomly generated and should not expose significant information
about a document's contents, we still consider this an information leak to be
addressed in a future (and necessarily non-backwards-compatible) iteration of the
VoodooPad document format.
In addition to the document resources described above, VoodooPad maintains a
local cache of document data. This data is stored within a document-unique
subdirectory of
~/Library/Caches/com.flyingmeat.VoodooPad5
; the document-
unique cache directory name is derived using the mechanism specified in Appendix
B.
Encryption Specification
147
50
The document-specific cache directory contains:
•
sk.index
: A SearchKit-generated index over all pages within a VoodooPad
document.
•
store.vpsqlite
: An SQLite-based cache of document and page metadata.
The
sk.index
search index is encrypted and authenticated using the Item Encryption
mechanism defined in Section 3.3.
The
store.vpsqlite
index is encrypted and authenticated with SQLite SEE's
implementation of AES-128-CCM. For an overview of SQLite SEE, refer to
VoodooPad Crypto Overview, Appendix A.
3.1.1 Initial Keying and Encryption
To perform full document encryption, multiple keys are first derived from the user-
supplied document password:
•
A 512-bit Document Master Key (DMK) is derived from the user-supplied
password via PBKDF2-SHA512, using a randomly generated salt (see Section 2.2.1).
The DMK is only used as input to HKDF to generate additional subkeys.
•
Two sub-keys are generated from the DMK via HKDF-SHA256, using the
DMK as the HKDF input key material, a randomly generated salt (see Section 2.2.2),
and an ASCII, non-NUL-terminated HKDF info parameter:
•
Info 'MK-SUBKEY' - Used to encrypt and authenticate randomly
generated data protection sub-keys.
•
Info 'MK-SQLITE' - Used with SQLite SEE to encrypt and authenticate
the document data cache.
•
Data Protection Keys (DPK) are used to perform encryption and
authentication of document data (other than SQLite). These keys are randomly
generated, never re-used, and encrypted and authenticated using the MK-SUBKEY
key.
The public parameters necessary to perform key derivation of the DMK and its
subkeys are stored in an unencrypted and unauthenticated binary property list,
vde.plist
, located at the top-level of the VoodooPad document directory. This
property list contains a top-level dictionary, and the structure shall be defined as
follows (expressed in plist pseudo-code):
{
"compat_version" : NSNumber
"feature_version" : NSNumber
Encryption Specification
148
60
"kdf" : {
"pbkdf2_salt" : NSData
"pbkdf2_iterations" : NSNumber
"hkdf_salt" : NSData
}
}
•
The compatibility version is serialized as an NSNumber value with the key
crypto.compat_version
. The current compatibility version is
1
, and will be
incremented should an incompatible change to the
vde.plist
crypto serialization be
adopted. As such, implementations MUST reject unknown compatibility versions.
•
The feature version is serialized as an NSNumber value with a key of
crypto.feature_version
. The current feature version is
1
, and may be incremented
to denote the adoption of new features; implementations MUST reject feature
versions that are not equal to or greater than the specified compatibility version.
•
The DMK's PBKDF2 salt is serialized as an NSData value, with the key
crypto.kdf.pbkdf2_salt
•
The DMK's PBKDF2 iteration count will be serialized as an NSNumber value
with the key
crypto.kdf.pbkdf2_iterations
. If a document specifies an iteration
count of less than 40k, the document should be immediately re-keyed with a newly
derived MK, using a PBKDF2 iteration count of 40k or more. The minimum PBKDF2
iteration count may be increased in future updates.
•
The HKDF salt used to derive MK-SUBKEY and MK-SQLITE is serialized as
an NSData value, with the key
crypto.kdf.hkdf_salt
.
These keys and parameters are then used to perform encryption of all resource types
within the VoodoooPad Document:
•
A new, random DPK is generated for each resource to be encrypted (see
Section 2.2.3, Generated Random Keys). The DPK -- protected by the MK-SUBKEY
key -- is used as the VDE Item Encryption key (see Section 3.3) to perform
encryption and authentication of the document resource.
•
The MK-SQLITE
key is provided to SQLite, and is used to encrypt the
store.vpsqlite
document index.
3.1.2 Document Re-keying
Upon requesting a password change, a new set of keys are derived and the
parameters are saved to
vde.plist
, as documented in Section 3.1.1. These new
keys are then used to re-key or re-encrypt all document resources:
Encryption Specification
149
55
•
For each resource, the per-resource DPK is decrypted using the document's
previous MK-SUBKEY key, and then re-encrypted using the new MK-SUBKEY key.
The new DPK is written out to the encrypted resource file. Refer to Section 3.3, VDE
Item Encryption, for more information on the serialization mechanism.
•
The MK-SQLITE key is provided to SQLite, and is used to perform
immediate re-encryption of the
store.vpsqlite
document index.
The re-keying mechanism is intended to be resilient -- with additional user input -- to
early termination and file-based synchronization issues. Should a document resource
be found that cannot be decrypted with the current MK-SUBKEY key, the user must
be prompted for a previous password (or passwords) with which the item may have
been encrypted. If provided, the item can be immediately re-keyed as normal. If not
provided, the resource should be treated as temporarily unavailable.
3.2 Single Page Encryption
Single page encryption supports the use of a per-page (rather than per-document)
password, used to encrypt per-page resources within the document; the following is
an itemized list of per-page resource types within a VoodooPad documents, and their
usage and encryption requirements:
•
Page data, located in a pool of subdirectories within pages/[a-z0-9]/:
•
<page uuid>.plist
: Per-page metadata
•
<page uuid>
: Page data
In addition, locally cached data is stored within a document-unique subdirectory of
~/
Library/Caches/com.flyingmeat.VoodooPad5
. Each document stores cache files within a
directory stored in this location, keyed to the document. The document-specific
cache directory contains:
•
sk.index
: A SearchKit-generated index over all pages within a VoodooPad
document.
•
store.vpsqlite
: An SQLite-based cache of document and page metadata.
All page resources are encrypted using the Item Encryption mechanism defined in
Section 3.3, using a keying mechanism similar to that of full-document encryption:
•
A 512-bit Page Master Key (PMK) is derived from the user-supplied
password via PBKDF2-SHA512, using a randomly generated salt (see Section 2.2.1).
ThePMK is only used as input to HKDF to generate an additional subkey.
•
A single sub-key, MK-SUBKEY is generated from the PMK via HKDF-
SHA256, using the PMK as the HKDF input key material, a randomly generated salt
(see Section 2.2.2), and an ASCII, non-NUL-terminated HKDF info parameter of 'MK-
SUBKEY'.'
Encryption Specification
150
Documents you may be interested
Documents you may be interested