diff --git a/awx/conf/migrations/_reencrypt.py b/awx/conf/migrations/_reencrypt.py index 899d085f74..e46f550c07 100644 --- a/awx/conf/migrations/_reencrypt.py +++ b/awx/conf/migrations/_reencrypt.py @@ -3,7 +3,11 @@ import hashlib import six from django.utils.encoding import smart_str -from Crypto.Cipher import AES + +from cryptography.hazmat.backends import default_backend +from cryptography.hazmat.primitives.ciphers import Cipher +from cryptography.hazmat.primitives.ciphers.algorithms import AES +from cryptography.hazmat.primitives.ciphers.modes import ECB from awx.conf import settings_registry @@ -52,8 +56,8 @@ def decrypt_value(encryption_key, value): if algo != 'AES': raise ValueError('unsupported algorithm: %s' % algo) encrypted = base64.b64decode(b64data) - cipher = AES.new(encryption_key, AES.MODE_ECB) - value = cipher.decrypt(encrypted) + decryptor = Cipher(AES(encryption_key), ECB(), default_backend()).decryptor() + value = decryptor.update(encrypted) + decryptor.finalize() value = value.rstrip('\x00') # If the encrypted string contained a UTF8 marker, decode the data if utf8: @@ -90,10 +94,11 @@ def encrypt_field(instance, field_name, ask=False, subfield=None, skip_utf8=Fals utf8 = type(value) == six.text_type value = smart_str(value) key = get_encryption_key(field_name, getattr(instance, 'pk', None)) - cipher = AES.new(key, AES.MODE_ECB) - while len(value) % cipher.block_size != 0: + encryptor = Cipher(AES(key), ECB(), default_backend()).encryptor() + block_size = 16 + while len(value) % block_size != 0: value += '\x00' - encrypted = cipher.encrypt(value) + encrypted = encryptor.update(value) + encryptor.finalize() b64data = base64.b64encode(encrypted) tokens = ['$encrypted', 'AES', b64data] if utf8: diff --git a/awx/main/tests/unit/isolated/test_expect.py b/awx/main/tests/unit/isolated/test_expect.py index 0f7e18abc9..9f2d81d40a 100644 --- a/awx/main/tests/unit/isolated/test_expect.py +++ b/awx/main/tests/unit/isolated/test_expect.py @@ -9,8 +9,9 @@ import tempfile import time from collections import OrderedDict -from Crypto.PublicKey import RSA -from Crypto import Random +from cryptography.hazmat.primitives.asymmetric import rsa +from cryptography.hazmat.backends import default_backend +from cryptography.hazmat.primitives import serialization from awx.main.isolated import run, isolated_manager @@ -22,8 +23,19 @@ HERE, FILENAME = os.path.split(__file__) @pytest.fixture(scope='function') def rsa_key(request): passphrase = 'passme' - key = RSA.generate(1024, Random.new().read) - return (key.exportKey('PEM', passphrase, pkcs=1), passphrase) + key = rsa.generate_private_key( + public_exponent=65537, + key_size=1024, + backend=default_backend() + ) + return ( + key.private_bytes( + encoding=serialization.Encoding.PEM, + format=serialization.PrivateFormat.TraditionalOpenSSL, + encryption_algorithm=serialization.BestAvailableEncryption(passphrase) + ), + passphrase + ) @pytest.fixture(scope='function') diff --git a/tox.ini b/tox.ini index 53178e1a4b..f1ddaaeb8b 100644 --- a/tox.ini +++ b/tox.ini @@ -11,8 +11,6 @@ envlist = basepython = python2.7 setenv = DJANGO_SETTINGS_MODULE = awx.settings.development_quiet - # For OS X to be able to install pycrypto. - # CFLAGS = -I/opt/local/include SWIG_FEATURES = -cpperraswarn -includeall -I/usr/include/openssl HOME = {homedir} USERPROFILE = {homedir}