From b7e71eba77b71cb74661253547edd1083cd08fe4 Mon Sep 17 00:00:00 2001 From: Matt Anderson Date: Mon, 23 Sep 2024 20:44:29 +0000 Subject: [PATCH 1/9] Pad short secrets to 254 bytes --- splunksecrets.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/splunksecrets.py b/splunksecrets.py index 9865019..7c5f0aa 100644 --- a/splunksecrets.py +++ b/splunksecrets.py @@ -63,7 +63,8 @@ def decrypt(secret, ciphertext, nosalt=False): plaintext = "".join([six.unichr(c) for c in chars]) elif ciphertext.startswith("$7$"): if len(secret) < 254: - raise ValueError(f"secret too short, need 254 bytes, got {len(secret)}") + print(f'secret too short ({len(secret)} bytes), padding to 254 bytes with nulls') + secret = secret.ljust(254, b'\0') ciphertext = b64decode(ciphertext[3:]) kdf = PBKDF2HMAC( @@ -120,7 +121,8 @@ def encrypt(secret, plaintext, nosalt=False): def encrypt_new(secret, plaintext, iv=None): # pylint: disable=invalid-name """Use the new AES 256 GCM encryption in Splunk 7.2""" if len(secret) < 254: - raise ValueError(f"secret too short, need 254 bytes, got {len(secret)}") + print(f'secret too short ({len(secret)} bytes), padding to 254 bytes with nulls') + secret = secret.ljust(254, b'\0') kdf = PBKDF2HMAC( algorithm=hashes.SHA256(), From d86167cd7243f6860d56971cb01fa5b2a4a9a78c Mon Sep 17 00:00:00 2001 From: Matt Anderson Date: Mon, 23 Sep 2024 20:45:09 +0000 Subject: [PATCH 2/9] Add note about key padding --- README.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 6a330e9..c7b41ed 100644 --- a/README.rst +++ b/README.rst @@ -98,7 +98,8 @@ for AES256-GCM, with a 16-byte randomly generated initialization vector. The encryption produces both the ciphertext as well as a "tag" that is used as part of integrity verification. The iv, ciphertext, and tag (in that order) are concatenated, base64-encoded, and prepended with ``$7$`` -to produce the encrypted password seen in the configuration files. +to produce the encrypted password seen in the configuration files. If +the key is less than 254-bytes it is padded with null bytes. Phantom ~~~~~~~ From 490d69312d85382af511e5b044ca838341cc3521 Mon Sep 17 00:00:00 2001 From: Matt Anderson Date: Mon, 23 Sep 2024 20:53:28 +0000 Subject: [PATCH 3/9] Use double quotes (Q000) --- splunksecrets.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/splunksecrets.py b/splunksecrets.py index 7c5f0aa..faedd0d 100644 --- a/splunksecrets.py +++ b/splunksecrets.py @@ -63,8 +63,8 @@ def decrypt(secret, ciphertext, nosalt=False): plaintext = "".join([six.unichr(c) for c in chars]) elif ciphertext.startswith("$7$"): if len(secret) < 254: - print(f'secret too short ({len(secret)} bytes), padding to 254 bytes with nulls') - secret = secret.ljust(254, b'\0') + print(f"secret too short ({len(secret)} bytes), padding to 254 bytes with nulls") + secret = secret.ljust(254, b"\0") ciphertext = b64decode(ciphertext[3:]) kdf = PBKDF2HMAC( @@ -121,8 +121,8 @@ def encrypt(secret, plaintext, nosalt=False): def encrypt_new(secret, plaintext, iv=None): # pylint: disable=invalid-name """Use the new AES 256 GCM encryption in Splunk 7.2""" if len(secret) < 254: - print(f'secret too short ({len(secret)} bytes), padding to 254 bytes with nulls') - secret = secret.ljust(254, b'\0') + print(f"secret too short ({len(secret)} bytes), padding to 254 bytes with nulls") + secret = secret.ljust(254, b"\0") kdf = PBKDF2HMAC( algorithm=hashes.SHA256(), From 6ca16389fe4955efe06d4fb0ce81548da642c954 Mon Sep 17 00:00:00 2001 From: Matt Anderson Date: Mon, 23 Sep 2024 20:55:46 +0000 Subject: [PATCH 4/9] Test short secret padding --- tests.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tests.py b/tests.py index 1052486..cdc5653 100644 --- a/tests.py +++ b/tests.py @@ -105,10 +105,13 @@ def test_encrypt_new(self): ) self.assertEqual(ciphertext, "$7$aTVkS01HYVNJUk5wSnR5NKR+EdOfT4t84WSiXvPFHGHsfHtbgPIL3g==") - def test_encrypt_new_raises_value_error_short_secret(self): - with self.assertRaises(ValueError): - splunk_secret = base64.b64encode(os.urandom(255))[:253] - splunksecrets.encrypt_new(splunk_secret, "temp1234") + def test_encrypt_new_pads_short_secret(self): + ciphertext = splunksecrets.encrypt_new( + splunk_secret[:30], + "short123", + iv=six.b("4KK0Ra8LWBKxUFQ8") + ) + self.assertEqual(ciphertext, "$7$NEtLMFJhOExXQkt4VUZROK9vm0tDLbJn2jxESMRbs7MTdiHuTtBz8g==") def test_encrypt_character_matches_salt1(self): ciphertext = splunksecrets.encrypt(splunk_secret, "A" * 8) From 1a10366d9f963724eb96c727b025c6186436880f Mon Sep 17 00:00:00 2001 From: Matt Anderson Date: Thu, 26 Sep 2024 13:16:25 +0000 Subject: [PATCH 5/9] Remove short secret print --- splunksecrets.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/splunksecrets.py b/splunksecrets.py index faedd0d..1107fca 100644 --- a/splunksecrets.py +++ b/splunksecrets.py @@ -62,9 +62,9 @@ def decrypt(secret, ciphertext, nosalt=False): plaintext = "".join([six.unichr(c) for c in chars]) elif ciphertext.startswith("$7$"): - if len(secret) < 254: - print(f"secret too short ({len(secret)} bytes), padding to 254 bytes with nulls") - secret = secret.ljust(254, b"\0") + # pad secret to 254 bytes with nulls + secret = secret.ljust(254, b"\0") + ciphertext = b64decode(ciphertext[3:]) kdf = PBKDF2HMAC( @@ -120,9 +120,8 @@ def encrypt(secret, plaintext, nosalt=False): def encrypt_new(secret, plaintext, iv=None): # pylint: disable=invalid-name """Use the new AES 256 GCM encryption in Splunk 7.2""" - if len(secret) < 254: - print(f"secret too short ({len(secret)} bytes), padding to 254 bytes with nulls") - secret = secret.ljust(254, b"\0") + # pad secret to 254 bytes with nulls + secret = secret.ljust(254, b"\0") kdf = PBKDF2HMAC( algorithm=hashes.SHA256(), From 1cebe08d5eb04e2c992650426d4507b06d74cdc7 Mon Sep 17 00:00:00 2001 From: Cameron Schmidt Date: Thu, 26 Sep 2024 21:37:37 -0400 Subject: [PATCH 6/9] Update short secret decrypt test Was failing due to the function now padding the secret --- tests.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests.py b/tests.py index cdc5653..f025cab 100644 --- a/tests.py +++ b/tests.py @@ -134,13 +134,13 @@ def test_decrypt_raises_value_error_short_secret1(self): splunk_secret = base64.b64encode(os.urandom(255))[:15] splunksecrets.decrypt(splunk_secret, "$1$n6g0W7F51ZAK") - def test_decrypt_raises_value_error_short_secret2(self): - with self.assertRaises(ValueError): - splunk_secret = base64.b64encode(os.urandom(255))[:253] - splunksecrets.decrypt( - splunk_secret, - "$7$aTVkS01HYVNJUk5wSnR5NKR+EdOfT4t84WSiXvPFHGHsfHtbgPIL3g==" - ) + def test_decrypt_pads_short_secret2(self): + plaintext = splunksecrets.decrypt( + splunk_secret[:30], + "$7$NEtLMFJhOExXQkt4VUZROK9vm0tDLbJn2jxESMRbs7MTdiHuTtBz8g==" + ) + self.assertEqual(plaintext, "short123") + def test_decrypt_nosalt(self): plaintext = splunksecrets.decrypt(splunk_secret, "$1$2+1yGuQ1gcMK", nosalt=True) From 275d7a102e501a8811aa379448a67820a2014ad5 Mon Sep 17 00:00:00 2001 From: Matt Anderson Date: Fri, 27 Sep 2024 15:33:16 +0000 Subject: [PATCH 7/9] Remove extra blank line (E303) --- tests.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests.py b/tests.py index f025cab..8471d3e 100644 --- a/tests.py +++ b/tests.py @@ -141,7 +141,6 @@ def test_decrypt_pads_short_secret2(self): ) self.assertEqual(plaintext, "short123") - def test_decrypt_nosalt(self): plaintext = splunksecrets.decrypt(splunk_secret, "$1$2+1yGuQ1gcMK", nosalt=True) self.assertEqual(plaintext, "temp1234") From 732d686a1cb15eec8cc16ed02844dd1ff462c515 Mon Sep 17 00:00:00 2001 From: Matt Anderson Date: Thu, 3 Oct 2024 20:08:57 +0000 Subject: [PATCH 8/9] Allow string secrets --- splunksecrets.py | 4 ++-- tests.py | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/splunksecrets.py b/splunksecrets.py index 1107fca..392b793 100644 --- a/splunksecrets.py +++ b/splunksecrets.py @@ -63,7 +63,7 @@ def decrypt(secret, ciphertext, nosalt=False): plaintext = "".join([six.unichr(c) for c in chars]) elif ciphertext.startswith("$7$"): # pad secret to 254 bytes with nulls - secret = secret.ljust(254, b"\0") + secret = six.ensure_binary(secret).ljust(254, b"\0") ciphertext = b64decode(ciphertext[3:]) @@ -121,7 +121,7 @@ def encrypt(secret, plaintext, nosalt=False): def encrypt_new(secret, plaintext, iv=None): # pylint: disable=invalid-name """Use the new AES 256 GCM encryption in Splunk 7.2""" # pad secret to 254 bytes with nulls - secret = secret.ljust(254, b"\0") + secret = six.ensure_binary(secret).ljust(254, b"\0") kdf = PBKDF2HMAC( algorithm=hashes.SHA256(), diff --git a/tests.py b/tests.py index 8471d3e..be87bc9 100644 --- a/tests.py +++ b/tests.py @@ -105,6 +105,14 @@ def test_encrypt_new(self): ) self.assertEqual(ciphertext, "$7$aTVkS01HYVNJUk5wSnR5NKR+EdOfT4t84WSiXvPFHGHsfHtbgPIL3g==") + def test_encrypt_new_str_secret(self): + ciphertext = splunksecrets.encrypt_new( + "abc123", # secret as a string (not bytes) + "strings are fine", + iv=six.b("zIDM0YmIgDQ2gMzk") + ) + self.assertEqual(ciphertext, "$7$eklETTBZbUlnRFEyZ016a+2HMVEtbCAJkNb7RkVHdqZwZkVJyZ+HmTWlYJedFdR4") + def test_encrypt_new_pads_short_secret(self): ciphertext = splunksecrets.encrypt_new( splunk_secret[:30], From 5d8b556925a05460a70ef5446c8c545a3f38861f Mon Sep 17 00:00:00 2001 From: Matt Anderson Date: Thu, 3 Oct 2024 20:09:22 +0000 Subject: [PATCH 9/9] Convert SPLUNK_SECRET to bytes --- splunksecrets.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/splunksecrets.py b/splunksecrets.py index 392b793..e212afb 100644 --- a/splunksecrets.py +++ b/splunksecrets.py @@ -357,6 +357,8 @@ def __load_splunk_secret(ctx, param, value): # pragma: no cover if ctx.get_parameter_source(param.name).name != "ENVIRONMENT": with open(value, "rb") as f: # pylint: disable=invalid-name value = f.read().strip() + elif isinstance(value, str): + value = bytes(value, encoding="utf-8") return value.strip()