summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordrebs <drebs@leap.se>2013-06-04 15:47:11 -0300
committerdrebs <drebs@leap.se>2013-06-05 10:58:50 -0300
commit248f50d4a2d1586265eb70de200be271488442e1 (patch)
treefdbb2919dada861db0907972b6b58232334c0edf
parentfbbb1f1cb315a0d4ada2db5b9455582327b75038 (diff)
Use scrypt to derive key for local encryption.
-rw-r--r--changes/feature_use-raw-sqlcipher-key-with-scrypt-as-kdf1
-rw-r--r--src/leap/soledad/__init__.py33
-rw-r--r--src/leap/soledad/backends/sqlcipher.py2
3 files changed, 28 insertions, 8 deletions
diff --git a/changes/feature_use-raw-sqlcipher-key-with-scrypt-as-kdf b/changes/feature_use-raw-sqlcipher-key-with-scrypt-as-kdf
new file mode 100644
index 00000000..385c1c84
--- /dev/null
+++ b/changes/feature_use-raw-sqlcipher-key-with-scrypt-as-kdf
@@ -0,0 +1 @@
+ o Use scrypt to derive the key for local encryption.
diff --git a/src/leap/soledad/__init__.py b/src/leap/soledad/__init__.py
index c7f8cff3..fba275e3 100644
--- a/src/leap/soledad/__init__.py
+++ b/src/leap/soledad/__init__.py
@@ -301,17 +301,36 @@ class Soledad(object):
"""
Initialize the U1DB SQLCipher database for local storage.
- The local storage passphrase is hexlified version of the last
- C{LOCAL_STORAGE_SECRET_LENGTH} bytes of the storage secret.
- """
+ Currently, Soledad uses the default SQLCipher cipher, i.e.
+ 'aes-256-cbc'. We use scrypt to derive a 256-bit encryption key and
+ uses the 'raw PRAGMA key' format to handle the key to SQLCipher.
+
+ The first C{self.REMOTE_STORAGE_SECRET_LENGTH} bytes of the storage
+ secret are used for remote storage encryption. We use the next
+ C{self.LOCAL_STORAGE_SECRET} bytes to derive a key for local storage.
+ From these bytes, the first C{self.SALT_LENGTH} are used as the salt
+ and the rest as the password for the scrypt hashing.
+ """
+ # salt indexes
+ salt_start = self.REMOTE_STORAGE_SECRET_LENGTH
+ salt_end = salt_start + self.SALT_LENGTH
+ # password indexes
+ pwd_start = salt_end
+ pwd_end = salt_start + self.LOCAL_STORAGE_SECRET_LENGTH
+ # calculate the key for local encryption
+ secret = self._get_storage_secret()
+ key = scrypt.hash(
+ secret[pwd_start:pwd_end], # the password
+ secret[salt_start:salt_end], # the salt
+ buflen=32, # we need a key with 256 bits (32 bytes)
+ )
self._db = sqlcipher.open(
self._local_db_path,
- # storage secret is binary but sqlcipher passphrase must be string
- binascii.b2a_hex(
- self._get_storage_secret()[self.LOCAL_STORAGE_SECRET_LENGTH:]),
+ binascii.b2a_hex(key), # sqlcipher only accepts the hex version
create=True,
document_factory=LeapDocument,
- crypto=self._crypto)
+ crypto=self._crypto,
+ raw_key=True)
def close(self):
"""
diff --git a/src/leap/soledad/backends/sqlcipher.py b/src/leap/soledad/backends/sqlcipher.py
index 5825b844..d6d62f21 100644
--- a/src/leap/soledad/backends/sqlcipher.py
+++ b/src/leap/soledad/backends/sqlcipher.py
@@ -483,7 +483,7 @@ class SQLCipherDatabase(sqlite_backend.SQLitePartialExpandDatabase):
"""
if not all(c in string.hexdigits for c in key):
raise NotAnHexString(key)
- db_handle.cursor().execute('PRAGMA key = "x\'%s"' % passphrase)
+ db_handle.cursor().execute('PRAGMA key = "x\'%s"' % key)
@classmethod
def _pragma_cipher(cls, db_handle, cipher='aes-256-cbc'):