diff --git a/CHANGELOG.md b/CHANGELOG.md index 42bece984..88ef26a6a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +v2.4.8 (FUTURE) + +## Bug Fixes + +* [#2473](https://github.com/digitalocean/netbox/issues/2473) - Fix encoding of long (>127 character) secrets + +--- + v2.4.7 (2018-11-06) ## Enhancements diff --git a/netbox/secrets/models.py b/netbox/secrets/models.py index 8bbf3d14d..6beb86c9e 100644 --- a/netbox/secrets/models.py +++ b/netbox/secrets/models.py @@ -1,6 +1,7 @@ from __future__ import unicode_literals import os +import sys from Crypto.Cipher import AES, PKCS1_OAEP from Crypto.PublicKey import RSA @@ -392,6 +393,7 @@ class Secret(ChangeLoggedModel, CustomFieldModel): s = s.encode('utf8') if len(s) > 65535: raise ValueError("Maximum plaintext size is 65535 bytes.") + # Minimum ciphertext size is 64 bytes to conceal the length of short secrets. if len(s) <= 62: pad_length = 62 - len(s) @@ -399,12 +401,14 @@ class Secret(ChangeLoggedModel, CustomFieldModel): pad_length = 16 - ((len(s) + 2) % 16) else: pad_length = 0 - return ( - chr(len(s) >> 8).encode() + - chr(len(s) % 256).encode() + - s + - os.urandom(pad_length) - ) + + # Python 2 compatibility + if sys.version_info[0] < 3: + header = chr(len(s) >> 8) + chr(len(s) % 256) + else: + header = bytes([len(s) >> 8]) + bytes([len(s) % 256]) + + return header + s + os.urandom(pad_length) def _unpad(self, s): """ diff --git a/netbox/secrets/tests/test_models.py b/netbox/secrets/tests/test_models.py index 887c048bf..2fb7c3781 100644 --- a/netbox/secrets/tests/test_models.py +++ b/netbox/secrets/tests/test_models.py @@ -1,4 +1,5 @@ from __future__ import unicode_literals +import string from Crypto.PublicKey import RSA from django.conf import settings @@ -88,7 +89,7 @@ class SecretTestCase(TestCase): """ Test basic encryption and decryption functionality using a random master key. """ - plaintext = "FooBar123" + plaintext = string.printable * 2 secret_key = generate_random_key() s = Secret(plaintext=plaintext) s.encrypt(secret_key)