Browse Source

Fixes #1527: Replace deprecated pycrypto library with pycryptodome

Jeremy Stretch 7 years ago
parent
commit
c300879995
4 changed files with 14 additions and 15 deletions
  1. 7 14
      netbox/secrets/models.py
  2. 1 0
      old_requirements.txt
  3. 1 1
      requirements.txt
  4. 5 0
      upgrade.sh

+ 7 - 14
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):

+ 1 - 0
old_requirements.txt

@@ -0,0 +1 @@
+pycrypto

+ 1 - 1
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

+ 5 - 0
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)..."