Ejemplo n.º 1
0
def encrypt_sym(data, key):
    """
    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 data (must be 256 bits long).
    :type key: str

    :return: A tuple with the initialization vector and the encrypted data.
    :rtype: (long, str)
    """
    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))

    iv = os.urandom(16)
    backend = MultiBackend([OpenSSLBackend()])
    cipher = Cipher(algorithms.AES(key), modes.CTR(iv), backend=backend)
    encryptor = cipher.encryptor()
    ciphertext = encryptor.update(data) + encryptor.finalize()

    return binascii.b2a_base64(iv), ciphertext
Ejemplo n.º 2
0
def decrypt_sym(data, key, iv):
    """
    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 symmetric key used to decrypt data (must be 256 bits
                long).
    :type key: str
    :param iv: The initialization vector.
    :type iv: long

    :return: The decrypted data.
    :rtype: str
    """
    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))
    backend = MultiBackend([OpenSSLBackend()])
    iv = binascii.a2b_base64(iv)
    cipher = Cipher(algorithms.AES(key), modes.CTR(iv), backend=backend)
    decryptor = cipher.decryptor()
    return decryptor.update(data) + decryptor.finalize()
Ejemplo n.º 3
0
def decrypt_sym(data, key, method, **kwargs):
    """
    Decrypt data using symmetric secret.

    Currently, the only encryption method supported is AES-256 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).
    :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

    :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)
Ejemplo n.º 4
0
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.

    :param data: The data to be encrypted.
    :type data: str
    :param key: The key used to encrypt C{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.
    :rtype: (long, str)
    """
    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))
    iv = None
    # AES-256 in CTR mode
    if method == EncryptionMethods.AES_256_CTR:
        iv = os.urandom(16)
        ciphertext = AES(key=key, iv=iv).process(data)
    # XSalsa20
    elif method == EncryptionMethods.XSALSA20:
        iv = os.urandom(24)
        ciphertext = XSalsa20(key=key, iv=iv).process(data)
    else:
        # raise if method is unknown
        raise UnknownEncryptionMethod('Unkwnown method: %s' % method)
    return binascii.b2a_base64(iv), ciphertext
Ejemplo n.º 5
0
def decrypt_sym(data, key, method, **kwargs):
    """
    Decrypt data using symmetric secret.

    Currently, the only encryption method supported is AES-256 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).
    :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

    :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, "Wrong key size: %s (must be 256 bits long)." % len(key))  # 32 x 8 = 256 bits.
    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)
Ejemplo n.º 6
0
def decrypt_sym(data, key, iv):
    """
    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 symmetric key used to decrypt data (must be 256 bits
                long).
    :type key: str
    :param iv: The initialization vector.
    :type iv: long

    :return: The decrypted data.
    :rtype: str
    """
    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))
    backend = MultiBackend([OpenSSLBackend()])
    iv = binascii.a2b_base64(iv)
    cipher = Cipher(algorithms.AES(key), modes.CTR(iv), backend=backend)
    decryptor = cipher.decryptor()
    return decryptor.update(data) + decryptor.finalize()
Ejemplo n.º 7
0
Archivo: api.py Proyecto: rdoh/soledad
    def _init_config_with_defaults(self):
        """
        Initialize configuration using default values for missing params.
        """
        soledad_assert_type(self._passphrase, unicode)
        initialize = lambda attr, val: getattr(self, attr, None) is None and setattr(self, attr, val)

        initialize("_secrets_path", os.path.join(self.default_prefix, self.secrets_file_name))
        initialize("_local_db_path", os.path.join(self.default_prefix, self.local_db_file_name))
        # initialize server_url
        soledad_assert(self._server_url is not None, "Missing URL for Soledad server.")
Ejemplo n.º 8
0
    def _init_config_with_defaults(self):
        """
        Initialize configuration using default values for missing params.
        """
        soledad_assert_type(self.passphrase, unicode)

        def initialize(attr, val):
            return ((getattr(self, attr, None) is None)
                    and setattr(self, attr, val))

        initialize("_secrets_path",
                   os.path.join(self.default_prefix, self.secrets_file_name))
        initialize("_local_db_path",
                   os.path.join(self.default_prefix, self.local_db_file_name))
Ejemplo n.º 9
0
    def _init_config_with_defaults(self):
        """
        Initialize configuration using default values for missing params.
        """
        soledad_assert_type(self._passphrase, unicode)
        initialize = lambda attr, val: getattr(
            self, attr, None) is None and setattr(self, attr, val)

        initialize("_secrets_path",
                   os.path.join(self.default_prefix, self.secrets_file_name))
        initialize("_local_db_path",
                   os.path.join(self.default_prefix, self.local_db_file_name))
        # initialize server_url
        soledad_assert(self._server_url is not None,
                       'Missing URL for Soledad server.')
Ejemplo n.º 10
0
    def change_passphrase(self, new_passphrase):
        """
        Change the passphrase that encrypts the storage secret.

        :param new_passphrase: The new passphrase.
        :type new_passphrase: unicode

        :raise NoStorageSecret: Raised if there's no storage secret available.
        """
        # maybe we want to add more checks to guarantee passphrase is
        # reasonable?
        soledad_assert_type(new_passphrase, unicode)
        if len(new_passphrase) < self.MINIMUM_PASSPHRASE_LENGTH:
            raise PassphraseTooShort(
                'Passphrase must be at least %d characters long!' %
                self.MINIMUM_PASSPHRASE_LENGTH)
        # ensure there's a secret for which the passphrase will be changed.
        if not self._has_secret():
            raise NoStorageSecret()
        secret = self._get_storage_secret()
        # generate random salt
        new_salt = os.urandom(self.SALT_LENGTH)
        # get a 256-bit key
        key = scrypt.hash(new_passphrase.encode('utf-8'), new_salt, buflen=32)
        iv, ciphertext = self._crypto.encrypt_sym(secret, key)
        # XXX update all secrets in the dict
        self._secrets[self._secret_id] = {
            # leap.soledad.crypto submodule uses AES256 for symmetric
            # encryption.
            self.KDF_KEY:
            self.KDF_SCRYPT,  # TODO: remove hard coded kdf
            self.KDF_SALT_KEY:
            binascii.b2a_base64(new_salt),
            self.KDF_LENGTH_KEY:
            len(key),
            self.CIPHER_KEY:
            self.CIPHER_AES256,
            self.LENGTH_KEY:
            len(secret),
            self.SECRET_KEY:
            '%s%s%s' %
            (str(iv), self.IV_SEPARATOR, binascii.b2a_base64(ciphertext)),
        }
        self._passphrase = new_passphrase
        self._store_secrets()
        self._put_secrets_in_shared_db()
Ejemplo n.º 11
0
def encrypt_sym(data, key):
    """
    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 data (must be 256 bits long).
    :type key: str

    :return: A tuple with the initialization vector and the encrypted data.
    :rtype: (long, str)
    """
    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))

    iv = os.urandom(16)
    ciphertext = AES(key=key, iv=iv).process(data)

    return binascii.b2a_base64(iv), ciphertext
Ejemplo n.º 12
0
def decrypt_sym(data, key, iv):
    """
    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 symmetric key used to decrypt data (must be 256 bits
                long).
    :type key: str
    :param iv: The initialization vector.
    :type iv: long

    :return: The decrypted data.
    :rtype: str
    """
    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))
    return AES(key=key, iv=binascii.a2b_base64(iv)).process(data)
Ejemplo n.º 13
0
    def change_passphrase(self, new_passphrase):
        """
        Change the passphrase that encrypts the storage secret.

        :param new_passphrase: The new passphrase.
        :type new_passphrase: unicode

        :raise NoStorageSecret: Raised if there's no storage secret available.
        """
        # maybe we want to add more checks to guarantee passphrase is
        # reasonable?
        soledad_assert_type(new_passphrase, unicode)
        if len(new_passphrase) < self.MINIMUM_PASSPHRASE_LENGTH:
            raise PassphraseTooShort(
                'Passphrase must be at least %d characters long!' %
                self.MINIMUM_PASSPHRASE_LENGTH)
        # ensure there's a secret for which the passphrase will be changed.
        if not self._has_secret():
            raise NoStorageSecret()
        secret = self._get_storage_secret()
        # generate random salt
        new_salt = os.urandom(self.SALT_LENGTH)
        # get a 256-bit key
        key = scrypt.hash(new_passphrase.encode('utf-8'), new_salt, buflen=32)
        iv, ciphertext = self._crypto.encrypt_sym(secret, key)
        # XXX update all secrets in the dict
        self._secrets[self._secret_id] = {
            # leap.soledad.crypto submodule uses AES256 for symmetric
            # encryption.
            self.KDF_KEY: self.KDF_SCRYPT,  # TODO: remove hard coded kdf
            self.KDF_SALT_KEY: binascii.b2a_base64(new_salt),
            self.KDF_LENGTH_KEY: len(key),
            self.CIPHER_KEY: self.CIPHER_AES256,
            self.LENGTH_KEY: len(secret),
            self.SECRET_KEY: '%s%s%s' % (
                str(iv), self.IV_SEPARATOR, binascii.b2a_base64(ciphertext)),
        }
        self._passphrase = new_passphrase
        self._store_secrets()
        self._put_secrets_in_shared_db()
Ejemplo n.º 14
0
def decrypt_sym(data, key, iv):
    """
    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 symmetric key used to decrypt data (must be 256 bits
                long).
    :type key: str
    :param iv: The initialization vector.
    :type iv: long

    :return: The decrypted data.
    :rtype: str
    """
    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))
    return AES(
        key=key, iv=binascii.a2b_base64(iv)).process(data)
Ejemplo n.º 15
0
def encrypt_sym(data, key):
    """
    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 data (must be 256 bits long).
    :type key: str

    :return: A tuple with the initialization vector and the encrypted data.
    :rtype: (long, str)
    """
    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))

    iv = os.urandom(16)
    ciphertext = AES(key=key, iv=iv).process(data)

    return binascii.b2a_base64(iv), ciphertext
Ejemplo n.º 16
0
    def change_passphrase(self, new_passphrase):
        """
        Change the passphrase that encrypts the storage secret.

        :param new_passphrase: The new passphrase.
        :type new_passphrase: unicode

        :raise NoStorageSecret: Raised if there's no storage secret available.
        """
        # TODO: maybe we want to add more checks to guarantee passphrase is
        # reasonable?
        soledad_assert_type(new_passphrase, unicode)
        if len(new_passphrase) < self.MINIMUM_PASSPHRASE_LENGTH:
            raise PassphraseTooShort(
                'Passphrase must be at least %d characters long!' %
                self.MINIMUM_PASSPHRASE_LENGTH)
        # ensure there's a secret for which the passphrase will be changed.
        if not self._has_secret():
            raise NoStorageSecret()
        self._passphrase = new_passphrase
        self._store_secrets()
        self._put_secrets_in_shared_db()
Ejemplo n.º 17
0
    def change_passphrase(self, new_passphrase):
        """
        Change the passphrase that encrypts the storage secret.

        :param new_passphrase: The new passphrase.
        :type new_passphrase: unicode

        :raise NoStorageSecret: Raised if there's no storage secret available.
        """
        # TODO: maybe we want to add more checks to guarantee passphrase is
        # reasonable?
        soledad_assert_type(new_passphrase, unicode)
        if len(new_passphrase) < self.MINIMUM_PASSPHRASE_LENGTH:
            raise PassphraseTooShort(
                'Passphrase must be at least %d characters long!' %
                self.MINIMUM_PASSPHRASE_LENGTH)
        # ensure there's a secret for which the passphrase will be changed.
        if not self._has_secret():
            raise NoStorageSecret()
        self._passphrase = new_passphrase
        self._store_secrets()
        self._put_secrets_in_shared_db()
Ejemplo n.º 18
0
def encrypt_sym(data, key):
    """
    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 data (must be 256 bits long).
    :type key: str

    :return: A tuple with the initialization vector and the encrypted data.
    :rtype: (long, str)
    """
    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))

    iv = os.urandom(16)
    cipher = Cipher(algorithms.AES(key), modes.CTR(iv), backend=crypto_backend)
    encryptor = cipher.encryptor()
    ciphertext = encryptor.update(data) + encryptor.finalize()

    return binascii.b2a_base64(iv), ciphertext
Ejemplo n.º 19
0
    def decrypt_sym(self, data, key,
                    method=EncryptionMethods.AES_256_CTR, **kwargs):
        """
        Decrypt data using symmetric secret.

        Currently, the only encryption method supported is AES-256 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).
        :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

        :return: The decrypted data.
        :rtype: str
        """
        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)
        # AES-256 in CTR mode
        if method == EncryptionMethods.AES_256_CTR:
            return AES(
                key=key, iv=binascii.a2b_base64(kwargs['iv'])).process(data)
        elif method == EncryptionMethods.XSALSA20:
            return XSalsa20(
                key=key, iv=binascii.a2b_base64(kwargs['iv'])).process(data)

        # raise if method is unknown
        raise UnknownEncryptionMethod('Unkwnown method: %s' % method)
Ejemplo n.º 20
0
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.

    :param data: The data to be encrypted.
    :type data: str
    :param key: The key used to encrypt C{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.
    :rtype: (long, str)
    """
    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))
    iv = None
    # AES-256 in CTR mode
    if method == EncryptionMethods.AES_256_CTR:
        iv = os.urandom(16)
        ciphertext = AES(key=key, iv=iv).process(data)
    # XSalsa20
    elif method == EncryptionMethods.XSALSA20:
        iv = os.urandom(24)
        ciphertext = XSalsa20(key=key, iv=iv).process(data)
    else:
        # raise if method is unknown
        raise UnknownEncryptionMethod('Unkwnown method: %s' % method)
    return binascii.b2a_base64(iv), ciphertext
Ejemplo n.º 21
0
    def __init__(self,
                 uuid,
                 passphrase,
                 secrets_path,
                 local_db_path,
                 server_url,
                 cert_file,
                 auth_token=None,
                 secret_id=None,
                 defer_encryption=False):
        """
        Initialize configuration, cryptographic keys and dbs.

        :param uuid: User's uuid.
        :type uuid: str

        :param passphrase: The passphrase for locking and unlocking encryption
                           secrets for local and remote storage.
        :type passphrase: unicode

        :param secrets_path: Path for storing encrypted key used for
                             symmetric encryption.
        :type secrets_path: str

        :param local_db_path: Path for local encrypted storage db.
        :type local_db_path: str

        :param server_url: URL for Soledad server. This is used either to sync
                           with the user's remote db and to interact with the
                           shared recovery database.
        :type server_url: str

        :param cert_file: Path to the certificate of the ca used
                          to validate the SSL certificate used by the remote
                          soledad server.
        :type cert_file: str

        :param auth_token: Authorization token for accessing remote databases.
        :type auth_token: str

        :param secret_id: The id of the storage secret to be used.
        :type secret_id: str

        :param defer_encryption: Whether to defer encryption/decryption of
                                 documents, or do it inline while syncing.
        :type defer_encryption: bool

        :raise BootstrapSequenceError: Raised when the secret generation and
                                       storage on server sequence has failed
                                       for some reason.
        """
        # get config params
        self._uuid = uuid
        soledad_assert_type(passphrase, unicode)
        self._passphrase = passphrase
        # init crypto variables
        self._secrets = {}
        self._secret_id = secret_id
        self._defer_encryption = defer_encryption

        self._init_config(secrets_path, local_db_path, server_url)

        self._set_token(auth_token)
        self._shared_db_instance = None
        # configure SSL certificate
        global SOLEDAD_CERT
        SOLEDAD_CERT = cert_file
        # initiate bootstrap sequence
        self._bootstrap()  # might raise BootstrapSequenceError()
Ejemplo n.º 22
0
    def __init__(self, uuid, passphrase, secrets_path, local_db_path,
                 server_url, cert_file,
                 auth_token=None, secret_id=None, defer_encryption=False):
        """
        Initialize configuration, cryptographic keys and dbs.

        :param uuid: User's uuid.
        :type uuid: str

        :param passphrase: The passphrase for locking and unlocking encryption
                           secrets for local and remote storage.
        :type passphrase: unicode

        :param secrets_path: Path for storing encrypted key used for
                             symmetric encryption.
        :type secrets_path: str

        :param local_db_path: Path for local encrypted storage db.
        :type local_db_path: str

        :param server_url: URL for Soledad server. This is used either to sync
                           with the user's remote db and to interact with the
                           shared recovery database.
        :type server_url: str

        :param cert_file: Path to the certificate of the ca used
                          to validate the SSL certificate used by the remote
                          soledad server.
        :type cert_file: str

        :param auth_token: Authorization token for accessing remote databases.
        :type auth_token: str

        :param secret_id: The id of the storage secret to be used.
        :type secret_id: str

        :param defer_encryption: Whether to defer encryption/decryption of
                                 documents, or do it inline while syncing.
        :type defer_encryption: bool

        :raise BootstrapSequenceError: Raised when the secret generation and
                                       storage on server sequence has failed
                                       for some reason.
        """
        # get config params
        self._uuid = uuid
        soledad_assert_type(passphrase, unicode)
        self._passphrase = passphrase
        # init crypto variables
        self._secrets = {}
        self._secret_id = secret_id
        self._defer_encryption = defer_encryption

        self._init_config(secrets_path, local_db_path, server_url)

        self._set_token(auth_token)
        self._shared_db_instance = None
        # configure SSL certificate
        global SOLEDAD_CERT
        SOLEDAD_CERT = cert_file
        # initiate bootstrap sequence
        self._bootstrap()  # might raise BootstrapSequenceError()