summaryrefslogtreecommitdiff
path: root/client/src/leap/soledad/client/crypto.py
diff options
context:
space:
mode:
Diffstat (limited to 'client/src/leap/soledad/client/crypto.py')
-rw-r--r--client/src/leap/soledad/client/crypto.py180
1 files changed, 54 insertions, 126 deletions
diff --git a/client/src/leap/soledad/client/crypto.py b/client/src/leap/soledad/client/crypto.py
index 6328fd2b..90ad656e 100644
--- a/client/src/leap/soledad/client/crypto.py
+++ b/client/src/leap/soledad/client/crypto.py
@@ -25,7 +25,6 @@ import json
import logging
from pycryptopp.cipher.aes import AES
-from pycryptopp.cipher.xsalsa20 import XSalsa20
from leap.soledad.common import soledad_assert
from leap.soledad.common import soledad_assert_type
@@ -38,100 +37,52 @@ logger = logging.getLogger(__name__)
MAC_KEY_LENGTH = 64
-def _assert_known_encryption_method(method):
+def encrypt_sym(data, key):
"""
- Assert that we can encrypt/decrypt the given C{method}
-
- :param method: The encryption method to assert.
- :type method: str
-
- :raise UnknownEncryptionMethodError: Raised when C{method} is unknown.
- """
- valid_methods = [
- crypto.EncryptionMethods.AES_256_CTR,
- crypto.EncryptionMethods.XSALSA20,
- ]
- try:
- soledad_assert(method in valid_methods)
- except AssertionError:
- raise crypto.UnknownEncryptionMethodError
-
-
-def encrypt_sym(data, key, method):
- """
- Encrypt C{data} using a {password}.
-
- Currently, the only encryption methods supported are AES-256 in CTR
- mode and XSalsa20.
+ Encrypt data using AES-256 cipher in CTR mode.
:param data: The data to be encrypted.
:type data: str
- :param key: The key used to encrypt C{data} (must be 256 bits long).
+ :param key: The key used to encrypt data (must be 256 bits long).
:type key: str
- :param method: The encryption method to use.
- :type method: str
- :return: A tuple with the initial value and the encrypted data.
+ :return: A tuple with the initialization vector and the encrypted data.
:rtype: (long, str)
-
- :raise AssertionError: Raised if C{method} is unknown.
"""
soledad_assert_type(key, str)
soledad_assert(
len(key) == 32, # 32 x 8 = 256 bits.
'Wrong key size: %s bits (must be 256 bits long).' %
(len(key) * 8))
- _assert_known_encryption_method(method)
-
- iv = None
- # AES-256 in CTR mode
- if method == crypto.EncryptionMethods.AES_256_CTR:
- iv = os.urandom(16)
- ciphertext = AES(key=key, iv=iv).process(data)
- # XSalsa20
- elif method == crypto.EncryptionMethods.XSALSA20:
- iv = os.urandom(24)
- ciphertext = XSalsa20(key=key, iv=iv).process(data)
+
+ iv = os.urandom(16)
+ ciphertext = AES(key=key, iv=iv).process(data)
return binascii.b2a_base64(iv), ciphertext
-def decrypt_sym(data, key, method, **kwargs):
+def decrypt_sym(data, key, iv):
"""
- Decrypt data using symmetric secret.
-
- Currently, the only encryption method supported is AES-256 CTR mode.
+ Decrypt some data previously encrypted using AES-256 cipher in CTR mode.
:param data: The data to be decrypted.
:type data: str
- :param key: The key used to decrypt C{data} (must be 256 bits long).
+ :param key: The symmetric key used to decrypt data (must be 256 bits
+ long).
:type key: str
- :param method: The encryption method to use.
- :type method: str
- :param kwargs: Other parameters specific to each encryption method.
- :type kwargs: dict
+ :param iv: The initialization vector.
+ :type iv: long
:return: The decrypted data.
:rtype: str
-
- :raise UnknownEncryptionMethodError: Raised when C{method} is unknown.
"""
soledad_assert_type(key, str)
# assert params
soledad_assert(
len(key) == 32, # 32 x 8 = 256 bits.
'Wrong key size: %s (must be 256 bits long).' % len(key))
- soledad_assert(
- 'iv' in kwargs,
- '%s needs an initial value.' % method)
- _assert_known_encryption_method(method)
- # AES-256 in CTR mode
- if method == crypto.EncryptionMethods.AES_256_CTR:
- return AES(
- key=key, iv=binascii.a2b_base64(kwargs['iv'])).process(data)
- elif method == crypto.EncryptionMethods.XSALSA20:
- return XSalsa20(
- key=key, iv=binascii.a2b_base64(kwargs['iv'])).process(data)
+ return AES(
+ key=key, iv=binascii.a2b_base64(iv)).process(data)
def doc_mac_key(doc_id, secret):
@@ -164,25 +115,17 @@ class SoledadCrypto(object):
General cryptographic functionality encapsulated in a
object that can be passed along.
"""
- def __init__(self, soledad):
+ def __init__(self, secret):
"""
Initialize the crypto object.
- :param soledad: A Soledad instance for key lookup.
- :type soledad: leap.soledad.Soledad
+ :param secret: The Soledad remote storage secret.
+ :type secret: str
"""
- self._soledad = soledad
-
- def encrypt_sym(self, data, key,
- method=crypto.EncryptionMethods.AES_256_CTR):
- return encrypt_sym(data, key, method)
-
- def decrypt_sym(self, data, key,
- method=crypto.EncryptionMethods.AES_256_CTR, **kwargs):
- return decrypt_sym(data, key, method, **kwargs)
+ self._secret = secret
- def doc_mac_key(self, doc_id, secret):
- return doc_mac_key(doc_id, self.secret)
+ def doc_mac_key(self, doc_id):
+ return doc_mac_key(doc_id, self._secret)
def doc_passphrase(self, doc_id):
"""
@@ -201,21 +144,41 @@ class SoledadCrypto(object):
:return: The passphrase.
:rtype: str
"""
- soledad_assert(self.secret is not None)
+ soledad_assert(self._secret is not None)
return hmac.new(
- self.secret[MAC_KEY_LENGTH:],
+ self._secret[MAC_KEY_LENGTH:],
doc_id,
hashlib.sha256).digest()
- #
- # secret setters/getters
- #
+ def encrypt_doc(self, doc):
+ """
+ Wrapper around encrypt_docstr that accepts the document as argument.
- def _get_secret(self):
- return self._soledad.secrets.remote_storage_secret
+ :param doc: the document.
+ :type doc: SoledadDocument
+ """
+ key = self.doc_passphrase(doc.doc_id)
- secret = property(
- _get_secret, doc='The secret used for symmetric encryption')
+ return encrypt_docstr(
+ doc.get_json(), doc.doc_id, doc.rev, key, self._secret)
+
+ def decrypt_doc(self, doc):
+ """
+ Wrapper around decrypt_doc_dict that accepts the document as argument.
+
+ :param doc: the document.
+ :type doc: SoledadDocument
+
+ :return: json string with the decrypted document
+ :rtype: str
+ """
+ key = self.doc_passphrase(doc.doc_id)
+ return decrypt_doc_dict(
+ doc.content, doc.doc_id, doc.rev, key, self._secret)
+
+ @property
+ def secret(self):
+ return self._secret
#
@@ -273,23 +236,6 @@ def mac_doc(doc_id, doc_rev, ciphertext, enc_scheme, enc_method, enc_iv,
hashlib.sha256).digest()
-def encrypt_doc(crypto, doc):
- """
- Wrapper around encrypt_docstr that accepts a crypto object and the document
- as arguments.
-
- :param crypto: a soledad crypto object.
- :type crypto: SoledadCrypto
- :param doc: the document.
- :type doc: SoledadDocument
- """
- key = crypto.doc_passphrase(doc.doc_id)
- secret = crypto.secret
-
- return encrypt_docstr(
- doc.get_json(), doc.doc_id, doc.rev, key, secret)
-
-
def encrypt_docstr(docstr, doc_id, doc_rev, key, secret):
"""
Encrypt C{doc}'s content.
@@ -330,7 +276,7 @@ def encrypt_docstr(docstr, doc_id, doc_rev, key, secret):
mac_method = crypto.MacMethods.HMAC
enc_iv, ciphertext = encrypt_sym(
str(docstr), # encryption/decryption routines expect str
- key, method=enc_method)
+ key)
mac = binascii.b2a_hex( # store the mac as hex.
mac_doc(
doc_id,
@@ -356,24 +302,6 @@ def encrypt_docstr(docstr, doc_id, doc_rev, key, secret):
})
-def decrypt_doc(crypto, doc):
- """
- Wrapper around decrypt_doc_dict that accepts a crypto object and the
- document as arguments.
-
- :param crypto: a soledad crypto object.
- :type crypto: SoledadCrypto
- :param doc: the document.
- :type doc: SoledadDocument
-
- :return: json string with the decrypted document
- :rtype: str
- """
- key = crypto.doc_passphrase(doc.doc_id)
- secret = crypto.secret
- return decrypt_doc_dict(doc.content, doc.doc_id, doc.rev, key, secret)
-
-
def _verify_doc_mac(doc_id, doc_rev, ciphertext, enc_scheme, enc_method,
enc_iv, mac_method, secret, doc_mac):
"""
@@ -458,8 +386,8 @@ def decrypt_doc_dict(doc_dict, doc_id, doc_rev, key, secret):
:param key: The key used to encrypt ``data`` (must be 256 bits long).
:type key: str
- :param secret:
- :type secret:
+ :param secret: The Soledad storage secret.
+ :type secret: str
:return: The JSON serialization of the decrypted content.
:rtype: str
@@ -491,7 +419,7 @@ def decrypt_doc_dict(doc_dict, doc_id, doc_rev, key, secret):
doc_id, doc_rev, ciphertext, enc_scheme, enc_method,
enc_iv, mac_method, secret, doc_mac)
- return decrypt_sym(ciphertext, key, method=enc_method, iv=enc_iv)
+ return decrypt_sym(ciphertext, key, enc_iv)
def is_symmetrically_encrypted(doc):