switch to cryptography
Fernet could not be used as it is not a streaming cipher. CFB mode does not require padding, so removed padding code. Depends-On: https://review.openstack.org/c/575199/ Change-Id: I14f58d9d473c20ce7863baa0b2adadbfda268b7a
This commit is contained in:
parent
10814141a4
commit
7c16877195
|
@ -124,7 +124,7 @@ Linux Requirements
|
||||||
- libffi-dev
|
- libffi-dev
|
||||||
- libssl-dev
|
- libssl-dev
|
||||||
- python-dev
|
- python-dev
|
||||||
- pycrypto
|
- cryptography
|
||||||
- At least 128 MB of memory reserved for Freezer
|
- At least 128 MB of memory reserved for Freezer
|
||||||
|
|
||||||
Windows Requirements
|
Windows Requirements
|
||||||
|
@ -587,7 +587,7 @@ Freezer architectural components are the following:
|
||||||
- freezer client running on the node where the backups and restores are to be executed
|
- freezer client running on the node where the backups and restores are to be executed
|
||||||
|
|
||||||
Freezer uses GNU Tar or Rsync algorithm under the hood to execute incremental backup and
|
Freezer uses GNU Tar or Rsync algorithm under the hood to execute incremental backup and
|
||||||
restore. When a key is provided, it uses OpenSSL or pycrypto module (OpenSSL compatible)
|
restore. When a key is provided, it uses OpenSSL or cryptography module (OpenSSL compatible)
|
||||||
to encrypt data. (AES-256-CFB)
|
to encrypt data. (AES-256-CFB)
|
||||||
|
|
||||||
=============
|
=============
|
||||||
|
|
|
@ -145,7 +145,6 @@ class Rsyncv2Engine(engine.BackupEngine):
|
||||||
flushed_data += compressor.flush()
|
flushed_data += compressor.flush()
|
||||||
if flushed_data and cipher:
|
if flushed_data and cipher:
|
||||||
flushed_data = cipher.encrypt(flushed_data)
|
flushed_data = cipher.encrypt(flushed_data)
|
||||||
flushed_data += cipher.flush()
|
|
||||||
|
|
||||||
return flushed_data
|
return flushed_data
|
||||||
|
|
||||||
|
|
|
@ -14,12 +14,15 @@
|
||||||
|
|
||||||
import hashlib
|
import hashlib
|
||||||
|
|
||||||
from Crypto.Cipher import AES
|
from cryptography.hazmat.backends import default_backend
|
||||||
from Crypto import Random
|
from cryptography.hazmat.primitives.ciphers import algorithms
|
||||||
|
from cryptography.hazmat.primitives.ciphers import Cipher
|
||||||
|
from cryptography.hazmat.primitives.ciphers import modes
|
||||||
|
from os import urandom
|
||||||
|
|
||||||
SALT_HEADER = 'Salted__'
|
SALT_HEADER = 'Salted__'
|
||||||
AES256_KEY_LENGTH = 32
|
AES256_KEY_LENGTH = 32
|
||||||
BS = AES.block_size
|
BS = 16 # static 16 bytes, 128 bits for AES
|
||||||
|
|
||||||
|
|
||||||
class AESCipher(object):
|
class AESCipher(object):
|
||||||
|
@ -56,40 +59,21 @@ class AESEncrypt(AESCipher):
|
||||||
|
|
||||||
def __init__(self, pass_file):
|
def __init__(self, pass_file):
|
||||||
super(AESEncrypt, self).__init__(pass_file)
|
super(AESEncrypt, self).__init__(pass_file)
|
||||||
self._salt = Random.new().read(BS - len(SALT_HEADER))
|
self._salt = urandom(BS - len(SALT_HEADER))
|
||||||
key, iv = self._derive_key_and_iv(self._password,
|
key, iv = self._derive_key_and_iv(self._password,
|
||||||
self._salt,
|
self._salt,
|
||||||
AES256_KEY_LENGTH,
|
AES256_KEY_LENGTH,
|
||||||
BS)
|
BS)
|
||||||
self.cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=BS * 8)
|
self.cipher = Cipher(algorithms.AES(key),
|
||||||
self.remain = None
|
modes.CFB(iv),
|
||||||
|
backend=default_backend())
|
||||||
|
|
||||||
def generate_header(self):
|
def generate_header(self):
|
||||||
return SALT_HEADER + self._salt
|
return SALT_HEADER + self._salt
|
||||||
|
|
||||||
def encrypt(self, data):
|
def encrypt(self, data):
|
||||||
remain = self.remain
|
encryptor = self.cipher.encryptor()
|
||||||
if remain:
|
return encryptor.update(data) + encryptor.finalize()
|
||||||
data = remain + data
|
|
||||||
remain = None
|
|
||||||
|
|
||||||
extra_bytes = len(data) % BS
|
|
||||||
if extra_bytes:
|
|
||||||
remain = data[-extra_bytes:]
|
|
||||||
data = data[:-extra_bytes]
|
|
||||||
|
|
||||||
self.remain = remain
|
|
||||||
return self.cipher.encrypt(data)
|
|
||||||
|
|
||||||
def flush(self):
|
|
||||||
def pad(s):
|
|
||||||
return s + (BS - len(s) % BS) * chr(BS - len(s) % BS)
|
|
||||||
|
|
||||||
buff = self.remain
|
|
||||||
if buff:
|
|
||||||
return self.cipher.encrypt(pad(buff))
|
|
||||||
|
|
||||||
return b''
|
|
||||||
|
|
||||||
|
|
||||||
class AESDecrypt(AESCipher):
|
class AESDecrypt(AESCipher):
|
||||||
|
@ -105,17 +89,14 @@ class AESDecrypt(AESCipher):
|
||||||
self._salt,
|
self._salt,
|
||||||
AES256_KEY_LENGTH,
|
AES256_KEY_LENGTH,
|
||||||
BS)
|
BS)
|
||||||
self.cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=BS * 8)
|
self.cipher = Cipher(algorithms.AES(key),
|
||||||
|
modes.CFB(iv),
|
||||||
|
backend=default_backend())
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _prepare_salt(salt):
|
def _prepare_salt(salt):
|
||||||
return salt[len(SALT_HEADER):]
|
return salt[len(SALT_HEADER):]
|
||||||
|
|
||||||
def decrypt(self, data):
|
def decrypt(self, data):
|
||||||
# def unpad(s):
|
decryptor = self.cipher.decryptor()
|
||||||
# return s[0:-ord(s[-1])]
|
return decryptor.update(data) + decryptor.finalize()
|
||||||
#
|
|
||||||
# if last_block:
|
|
||||||
# return unpad(self.cipher.decrypt(data))
|
|
||||||
# else:
|
|
||||||
return self.cipher.decrypt(data)
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ chardet==3.0.4
|
||||||
cliff==2.11.0
|
cliff==2.11.0
|
||||||
cmd2==0.8.1
|
cmd2==0.8.1
|
||||||
coverage==4.0
|
coverage==4.0
|
||||||
cryptography==2.1.4
|
cryptography==2.1
|
||||||
ddt==1.0.1
|
ddt==1.0.1
|
||||||
debtcollector==1.19.0
|
debtcollector==1.19.0
|
||||||
decorator==4.2.1
|
decorator==4.2.1
|
||||||
|
@ -74,7 +74,6 @@ prettytable==0.7.2
|
||||||
psutil==3.2.2
|
psutil==3.2.2
|
||||||
pyasn1==0.4.2
|
pyasn1==0.4.2
|
||||||
pycparser==2.18
|
pycparser==2.18
|
||||||
pycrypto==2.6
|
|
||||||
pyflakes==1.0.0
|
pyflakes==1.0.0
|
||||||
Pygments==2.2.0
|
Pygments==2.2.0
|
||||||
pyinotify==0.9.6
|
pyinotify==0.9.6
|
||||||
|
|
|
@ -18,7 +18,7 @@ keystoneauth1>=3.4.0 # Apache-2.0
|
||||||
os-brick>=2.2.0 # Apache-2.0
|
os-brick>=2.2.0 # Apache-2.0
|
||||||
oslo.service!=1.28.1,>=1.24.0 # Apache-2.0
|
oslo.service!=1.28.1,>=1.24.0 # Apache-2.0
|
||||||
|
|
||||||
pycrypto>=2.6 # Public Domain
|
cryptography>=2.1 # Apache-2.0
|
||||||
PyMySQL>=0.7.6 # MIT License
|
PyMySQL>=0.7.6 # MIT License
|
||||||
pymongo!=3.1,>=3.0.2 # Apache-2.0
|
pymongo!=3.1,>=3.0.2 # Apache-2.0
|
||||||
paramiko>=2.0.0 # LGPLv2.1+
|
paramiko>=2.0.0 # LGPLv2.1+
|
||||||
|
|
Loading…
Reference in New Issue