diff --git a/netbox/secrets/models.py b/netbox/secrets/models.py index e8eb2ff45..b3dac91cb 100644 --- a/netbox/secrets/models.py +++ b/netbox/secrets/models.py @@ -1,8 +1,9 @@ from __future__ import unicode_literals import os -from Crypto.Cipher import AES, PKCS1_OAEP, XOR +from Crypto.Cipher import AES, PKCS1_OAEP from Crypto.PublicKey import RSA +from Crypto.Util import strxor from django.conf import settings from django.contrib.auth.hashers import make_password, check_password @@ -45,14 +46,6 @@ def decrypt_master_key(master_key_cipher, private_key): return cipher.decrypt(master_key_cipher) -def xor_keys(key_a, key_b): - """ - Return the binary XOR of two given keys. - """ - xor = XOR.new(key_a) - return xor.encrypt(key_b) - - class UserKeyQuerySet(models.QuerySet): def active(self): @@ -98,7 +91,7 @@ class UserKey(CreatedUpdatedModel): # Validate the public key format try: - pubkey = RSA.importKey(self.public_key) + pubkey = RSA.import_key(self.public_key) except ValueError: raise ValidationError({ 'public_key': "Invalid RSA key format." @@ -108,7 +101,7 @@ class UserKey(CreatedUpdatedModel): "uploading a valid RSA public key in PEM format (no SSH/PGP).") # Validate the public key length - pubkey_length = pubkey.size() + 1 # key.size() returns 1 less than the key modulus + pubkey_length = pubkey.size_in_bits() if pubkey_length < settings.SECRETS_MIN_PUBKEY_SIZE: raise ValidationError({ 'public_key': "Insufficient key length. Keys must be at least {} bits long.".format( @@ -214,7 +207,7 @@ class SessionKey(models.Model): self.hash = make_password(self.key) # Encrypt master key using the session key - self.cipher = xor_keys(self.key, master_key) + self.cipher = strxor.strxor(self.key, master_key) super(SessionKey, self).save(*args, **kwargs) @@ -225,14 +218,14 @@ class SessionKey(models.Model): raise InvalidKey("Invalid session key") # Decrypt master key using provided session key - master_key = xor_keys(session_key, bytes(self.cipher)) + master_key = strxor.strxor(session_key, bytes(self.cipher)) return master_key def get_session_key(self, master_key): # Recover session key using the master key - session_key = xor_keys(master_key, bytes(self.cipher)) + session_key = strxor.strxor(master_key, bytes(self.cipher)) # Validate the recovered session key if not check_password(session_key, self.hash): diff --git a/old_requirements.txt b/old_requirements.txt new file mode 100644 index 000000000..904545b4f --- /dev/null +++ b/old_requirements.txt @@ -0,0 +1 @@ +pycrypto diff --git a/requirements.txt b/requirements.txt index 82041879e..20c1dff27 100644 --- a/requirements.txt +++ b/requirements.txt @@ -17,6 +17,6 @@ paramiko>=2.0.0 Pillow>=4.0.0 psycopg2>=2.7.3 py-gfm>=0.1.3 -pycrypto>=2.6.1 +pycryptodome>=3.4.7 sqlparse>=0.2 xmltodict>=0.10.2 diff --git a/upgrade.sh b/upgrade.sh index 24189a424..a1930eb3d 100755 --- a/upgrade.sh +++ b/upgrade.sh @@ -39,6 +39,11 @@ COMMAND="${PREFIX}find . -name \"*.pyc\" -delete" echo "Cleaning up stale Python bytecode ($COMMAND)..." eval $COMMAND +# Uninstall any Python packages which are no longer needed +COMMAND="${PREFIX}${PIP} uninstall -r old_requirements.txt -y" +echo "Removing old Python packages ($COMMAND)..." +eval $COMMAND + # Install any new Python packages COMMAND="${PREFIX}${PIP} install -r requirements.txt --upgrade" echo "Updating required Python packages ($COMMAND)..."