diff --git a/netbox/secrets/hashers.py b/netbox/secrets/hashers.py new file mode 100644 index 000000000..fc5066fc6 --- /dev/null +++ b/netbox/secrets/hashers.py @@ -0,0 +1,9 @@ +from django.contrib.auth.hashers import PBKDF2PasswordHasher + + +class SecretValidationHasher(PBKDF2PasswordHasher): + """ + We're using Django's stock SHA256 hasher with a low iteration count to avoid introducing excessive delay when + retrieving a large number of Secrets (the plaintext of each Secret is validated against its hash upon decryption). + """ + iterations = 1000 diff --git a/netbox/secrets/models.py b/netbox/secrets/models.py index 6bcc5995a..270f93501 100644 --- a/netbox/secrets/models.py +++ b/netbox/secrets/models.py @@ -11,6 +11,7 @@ from django.db import models from django.utils.encoding import force_bytes from dcim.models import Device +from .hashers import SecretValidationHasher def generate_master_key(): @@ -245,7 +246,7 @@ class Secret(models.Model): self.ciphertext = iv + aes.encrypt(self._pad(self.plaintext)) # Generate SHA256 using Django's built-in password hashing mechanism - self.hash = make_password(self.plaintext, hasher='pbkdf2_sha256') + self.hash = make_password(self.plaintext, hasher=SecretValidationHasher()) self.plaintext = None @@ -277,4 +278,4 @@ class Secret(models.Model): """ if not self.hash: raise Exception("Hash has not been generated for this secret.") - return check_password(plaintext, self.hash) + return check_password(plaintext, self.hash, preferred=SecretValidationHasher())