Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-altcha for openSUSE:Factory checked in at 2026-02-17 16:47:40 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-altcha (Old) and /work/SRC/openSUSE:Factory/.python-altcha.new.1977 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-altcha" Tue Feb 17 16:47:40 2026 rev:5 rq:1333405 version:1.0.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-altcha/python-altcha.changes 2025-06-17 18:26:28.068899109 +0200 +++ /work/SRC/openSUSE:Factory/.python-altcha.new.1977/python-altcha.changes 2026-02-17 16:48:39.386715337 +0100 @@ -1,0 +2,7 @@ +Mon Feb 16 17:05:27 UTC 2026 - Dirk Müller <[email protected]> + +- update to 1.0.0: + * fix: expires with utc datetime + * fix: salt parameter splicing + +------------------------------------------------------------------- Old: ---- altcha-0.2.0.tar.gz New: ---- altcha-1.0.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-altcha.spec ++++++ --- /var/tmp/diff_new_pack.ac2OnH/_old 2026-02-17 16:48:42.182832177 +0100 +++ /var/tmp/diff_new_pack.ac2OnH/_new 2026-02-17 16:48:42.182832177 +0100 @@ -1,7 +1,7 @@ # # spec file for package python-altcha # -# Copyright (c) 2025 SUSE LLC +# Copyright (c) 2026 SUSE LLC and contributors # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,7 +17,7 @@ Name: python-altcha -Version: 0.2.0 +Version: 1.0.0 Release: 0 Summary: A library for creating and verifying challenges for ALTCHA License: MIT ++++++ altcha-0.2.0.tar.gz -> altcha-1.0.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/altcha-0.2.0/PKG-INFO new/altcha-1.0.0/PKG-INFO --- old/altcha-0.2.0/PKG-INFO 2025-06-07 13:43:43.345699500 +0200 +++ new/altcha-1.0.0/PKG-INFO 2025-12-14 06:29:16.194569800 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.4 Name: altcha -Version: 0.2.0 +Version: 1.0.0 Summary: A library for creating and verifying challenges for ALTCHA. Home-page: https://github.com/altcha-org/altcha-lib-py Author: Daniel Regeci diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/altcha-0.2.0/altcha/altcha.py new/altcha-1.0.0/altcha/altcha.py --- old/altcha-0.2.0/altcha/altcha.py 2025-06-07 13:43:38.000000000 +0200 +++ new/altcha-1.0.0/altcha/altcha.py 2025-12-14 06:29:12.000000000 +0100 @@ -426,7 +426,16 @@ salt_params = dict(urllib.parse.parse_qsl(salt_query)) if options.expires: - salt_params["expires"] = str(int(time.mktime(options.expires.timetuple()))) + expires = options.expires + + if expires.tzinfo is None: + # Backward compatibility: assume naive datetimes are local time + timestamp = int(time.mktime(expires.timetuple())) + else: + # Aware datetimes: use true UTC timestamp + timestamp = int(expires.timestamp()) + + salt_params["expires"] = str(timestamp) if options.params: salt_params.update(options.params) @@ -434,6 +443,10 @@ if salt_params: salt += "?" + urllib.parse.urlencode(salt_params) + # Add a delimiter to prevent parameter splicing + if not salt.endswith("&"): + salt += "&" + challenge = hash_hex(algorithm, (salt + str(number)).encode()) signature = hmac_hex(algorithm, challenge.encode(), options.hmac_key) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/altcha-0.2.0/altcha.egg-info/PKG-INFO new/altcha-1.0.0/altcha.egg-info/PKG-INFO --- old/altcha-0.2.0/altcha.egg-info/PKG-INFO 2025-06-07 13:43:43.000000000 +0200 +++ new/altcha-1.0.0/altcha.egg-info/PKG-INFO 2025-12-14 06:29:16.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.4 Name: altcha -Version: 0.2.0 +Version: 1.0.0 Summary: A library for creating and verifying challenges for ALTCHA. Home-page: https://github.com/altcha-org/altcha-lib-py Author: Daniel Regeci diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/altcha-0.2.0/setup.py new/altcha-1.0.0/setup.py --- old/altcha-0.2.0/setup.py 2025-06-07 13:43:38.000000000 +0200 +++ new/altcha-1.0.0/setup.py 2025-12-14 06:29:12.000000000 +0100 @@ -2,7 +2,7 @@ setup( name="altcha", - version="0.2.0", + version="1.0.0", description="A library for creating and verifying challenges for ALTCHA.", long_description=open("README.md").read(), long_description_content_type="text/markdown", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/altcha-0.2.0/tests/test_altcha.py new/altcha-1.0.0/tests/test_altcha.py --- old/altcha-0.2.0/tests/test_altcha.py 2025-06-07 13:43:38.000000000 +0200 +++ new/altcha-1.0.0/tests/test_altcha.py 2025-12-14 06:29:12.000000000 +0100 @@ -129,6 +129,30 @@ result, _ = verify_solution(payload_encoded, self.hmac_key, check_expires=False) self.assertTrue(result) + def test_verify_solution_expires_utc(self): + options = ChallengeOptions( + algorithm="SHA-256", + max_number=1000, + salt_length=16, + hmac_key=self.hmac_key, + salt="somesalt", + number=123, + expires=datetime.datetime.now(datetime.timezone.utc), + ) + challenge = create_challenge(options) + payload = Payload( + algorithm="SHA-256", + challenge=challenge.challenge, + number=123, + salt=challenge.salt, + signature=challenge.signature, + ) + payload_encoded = base64.b64encode( + json.dumps(payload.__dict__).encode() + ).decode() + result, _ = verify_solution(payload_encoded, self.hmac_key, check_expires=True) + self.assertFalse(result) + def test_verify_solution_not_expired(self): options = ChallengeOptions( algorithm="SHA-256", @@ -204,6 +228,30 @@ result, _ = verify_solution(payload_encoded, self.hmac_key, check_expires=True) self.assertFalse(result) + def test_verify_solution_salt_splicing(self): + options = ChallengeOptions( + algorithm="SHA-256", + max_number=1000, + salt_length=16, + hmac_key=self.hmac_key, + expires=datetime.datetime.now().astimezone() + + datetime.timedelta(minutes=1), + number=123, + ) + challenge = create_challenge(options) + payload = Payload( + algorithm="SHA-256", + challenge=challenge.challenge, + number=23, + salt=challenge.salt + "1", + signature=challenge.signature, + ) + payload_encoded = base64.b64encode( + json.dumps(payload.__dict__).encode() + ).decode() + result, _ = verify_solution(payload_encoded, self.hmac_key, check_expires=False) + self.assertFalse(result) + def test_valid_signature(self): expire_time = int(time.time()) + 600 # 10 minutes from now verification_data = (
