summaryrefslogtreecommitdiffstats
path: root/contrib/python
diff options
context:
space:
mode:
authorrobot-piglet <[email protected]>2026-07-12 16:29:08 +0300
committerrobot-piglet <[email protected]>2026-07-12 16:43:51 +0300
commit63aff3789e8f93814a0d9f4068981b7397f70232 (patch)
treed8e05dd1dea8bfb10148a53c2e61703fdea706f9 /contrib/python
parent63c45db5cce8b82897f37967cd4af196de67e1e7 (diff)
Intermediate changes
commit_hash:28321331c1969bd72d182c9fadb787e0b1601554
Diffstat (limited to 'contrib/python')
-rw-r--r--contrib/python/scramp/.dist-info/METADATA12
-rw-r--r--contrib/python/scramp/README.md10
-rw-r--r--contrib/python/scramp/scramp/core.py25
-rw-r--r--contrib/python/scramp/scramp/utils.py2
-rw-r--r--contrib/python/scramp/ya.make2
5 files changed, 41 insertions, 10 deletions
diff --git a/contrib/python/scramp/.dist-info/METADATA b/contrib/python/scramp/.dist-info/METADATA
index d3b2cda4342..eb6b3e790f8 100644
--- a/contrib/python/scramp/.dist-info/METADATA
+++ b/contrib/python/scramp/.dist-info/METADATA
@@ -1,6 +1,6 @@
Metadata-Version: 2.4
Name: scramp
-Version: 1.4.9
+Version: 1.4.10
Summary: An implementation of the SCRAM protocol.
Project-URL: Homepage, https://codeberg.org/tlocke/scramp
Author: The Contributors
@@ -54,6 +54,7 @@ Scramp supports the following mechanisms:
* [OpenSSF Scorecard](#openssf-scorecard)
* [Doing A Release Of Scramp](#doing-a-release-of-scramp)
* [Release Notes](#release-notes)
+ * [Version 1.4.10, 2026-06-27](#version-1410-2026-06-27)
* [Version 1.4.9, 2026-06-19](#version-149-2026-06-19)
* [Version 1.4.8, 2026-01-06](#version-148-2026-01-06)
* [Version 1.4.7, 2026-01-04](#version-147-2026-01-04)
@@ -384,6 +385,15 @@ Run `tox` to make sure all tests pass, then update the release notes, then do:
## Release Notes
+### Version 1.4.10, 2026-06-27
+
+- Implement max and min guards for iteration count.
+- The xor() function should fail if the two values are of unequal lengths
+- Handle the case of an error in first server message
+- Fix formatting in channel binding error message
+- SHA3-512 didn't work, but it should do now
+
+
### Version 1.4.9, 2026-06-19
- Fix typo in error message.
diff --git a/contrib/python/scramp/README.md b/contrib/python/scramp/README.md
index 1ccdd745c56..652f8f590d0 100644
--- a/contrib/python/scramp/README.md
+++ b/contrib/python/scramp/README.md
@@ -33,6 +33,7 @@ Scramp supports the following mechanisms:
* [OpenSSF Scorecard](#openssf-scorecard)
* [Doing A Release Of Scramp](#doing-a-release-of-scramp)
* [Release Notes](#release-notes)
+ * [Version 1.4.10, 2026-06-27](#version-1410-2026-06-27)
* [Version 1.4.9, 2026-06-19](#version-149-2026-06-19)
* [Version 1.4.8, 2026-01-06](#version-148-2026-01-06)
* [Version 1.4.7, 2026-01-04](#version-147-2026-01-04)
@@ -363,6 +364,15 @@ Run `tox` to make sure all tests pass, then update the release notes, then do:
## Release Notes
+### Version 1.4.10, 2026-06-27
+
+- Implement max and min guards for iteration count.
+- The xor() function should fail if the two values are of unequal lengths
+- Handle the case of an error in first server message
+- Fix formatting in channel binding error message
+- SHA3-512 didn't work, but it should do now
+
+
### Version 1.4.9, 2026-06-19
- Fix typo in error message.
diff --git a/contrib/python/scramp/scramp/core.py b/contrib/python/scramp/scramp/core.py
index 7bfd362914a..7ab1a5703a7 100644
--- a/contrib/python/scramp/scramp/core.py
+++ b/contrib/python/scramp/scramp/core.py
@@ -77,6 +77,8 @@ CHANNEL_TYPES = (
"tls-unique-for-telnet",
)
+MAX_ITERATION_COUNT = 10_000_000 # DoS guard
+
def _make_cb_data(name, ssl_socket):
if name == "tls-unique":
@@ -137,6 +139,10 @@ class ScramMechanism:
def make_auth_info(self, password, iteration_count=None, salt=None):
if iteration_count is None:
iteration_count = self.iteration_count
+ if iteration_count < self.iteration_count:
+ raise ScramException(
+ f"The iteration count must be at least {self.iteration_count}"
+ )
salt, stored_key, server_key = _make_auth_info(
self.hf, password, iteration_count, salt=salt
)
@@ -175,8 +181,8 @@ def _validate_channel_binding(channel_binding):
channel_type, channel_data = channel_binding
if channel_type not in CHANNEL_TYPES:
raise ScramException(
- "The channel_binding parameter must either be None or a tuple with the "
- "first element a str specifying one of the channel types {CHANNEL_TYPES}."
+ f"The channel_binding parameter must either be None or a tuple with the "
+ f"first element a str specifying one of the channel types {CHANNEL_TYPES}."
)
if not isinstance(channel_data, bytes):
@@ -207,6 +213,7 @@ class ScramClient:
mech = sorted(mechs, key=attrgetter("strength"))[-1]
self.hf, self.use_binding = mech.hf, mech.use_binding
self.mechanism_name = mech.name
+ self.iterations = mech.iteration_count
self.c_nonce = _make_nonce() if c_nonce is None else c_nonce
self.username = username
@@ -229,7 +236,7 @@ class ScramClient:
self._set_stage(ClientStage.set_server_first)
self.server_first = message
self.nonce, self.salt, self.iterations = _set_server_first(
- message, self.c_nonce
+ message, self.c_nonce, self.iterations
)
def get_client_final(self):
@@ -351,8 +358,7 @@ def _make_auth_message(client_first_bare, server_first, client_final_without_pro
def _make_salted_password(hf, password, salt, iterations):
- hash_name = hf.__name__.split("_")[-1]
- return hashlib.pbkdf2_hmac(hash_name, uenc(saslprep(password)), salt, iterations)
+ return hashlib.pbkdf2_hmac(hf().name, uenc(saslprep(password)), salt, iterations)
def _c_key_stored_key_s_key(hf, salted_password):
@@ -518,14 +524,19 @@ def _get_server_first(nonce, salt, iterations):
return ",".join((f"r={nonce}", f"s={salt}", f"i={iterations}"))
-def _set_server_first(server_first, c_nonce):
- msg = _parse_message(server_first, "server first", {"r", "s", "i"})
+def _set_server_first(server_first, c_nonce, min_iteration_count):
+ msg = _parse_message(server_first, "server first", {"r", "s", "i"}, {"e"})
if "e" in msg:
raise ScramException(f"The server returned the error: {msg['e']}")
nonce = msg["r"]
salt = msg["s"]
iterations = int(msg["i"])
+ if not (min_iteration_count <= iterations <= MAX_ITERATION_COUNT):
+ raise ScramException(
+ f"Server iteration count must be between {min_iteration_count} "
+ f"and {MAX_ITERATION_COUNT} inclusive"
+ )
if not nonce.startswith(c_nonce):
raise ScramException("Client nonce doesn't match.", SERVER_ERROR_OTHER_ERROR)
diff --git a/contrib/python/scramp/scramp/utils.py b/contrib/python/scramp/scramp/utils.py
index da864d2fe2f..da991644090 100644
--- a/contrib/python/scramp/scramp/utils.py
+++ b/contrib/python/scramp/scramp/utils.py
@@ -14,7 +14,7 @@ def h(hf, msg):
def xor(bytes1, bytes2):
- return bytes(a ^ b for a, b in zip(bytes1, bytes2))
+ return bytes(a ^ b for a, b in zip(bytes1, bytes2, strict=True))
def b64enc(binary):
diff --git a/contrib/python/scramp/ya.make b/contrib/python/scramp/ya.make
index 9453f63f0af..f5d6699f70a 100644
--- a/contrib/python/scramp/ya.make
+++ b/contrib/python/scramp/ya.make
@@ -2,7 +2,7 @@
PY3_LIBRARY()
-VERSION(1.4.9)
+VERSION(1.4.10)
LICENSE(MIT-0)