Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-webauthn for openSUSE:Factory
checked in at 2026-04-19 18:17:51
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-webauthn (Old)
and /work/SRC/openSUSE:Factory/.python-webauthn.new.11940 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-webauthn"
Sun Apr 19 18:17:51 2026 rev:8 rq:1348036 version:2.7.1
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-webauthn/python-webauthn.changes
2025-11-06 18:18:27.324762237 +0100
+++
/work/SRC/openSUSE:Factory/.python-webauthn.new.11940/python-webauthn.changes
2026-04-19 18:17:51.608213356 +0200
@@ -1,0 +2,10 @@
+Fri Apr 17 07:52:56 UTC 2026 - John Paul Adrian Glaubitz
<[email protected]>
+
+- Update to 2.7.1
+ * This project now uses the pyasn1 library to parse ASN.1-encoded
+ values (#263), h/t @ggirol-rc)
+ * Some bare `dict` type annotations have been replaced with `Dict[str, Any]`
+ to satisfy stricter type checking setups (#262), h/t @typestring)
+- Update BuildRequires and Requires from pyproject.toml
+
+-------------------------------------------------------------------
Old:
----
webauthn-2.7.0.tar.gz
New:
----
webauthn-2.7.1.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-webauthn.spec ++++++
--- /var/tmp/diff_new_pack.2QzjKS/_old 2026-04-19 18:17:52.176236503 +0200
+++ /var/tmp/diff_new_pack.2QzjKS/_new 2026-04-19 18:17:52.176236503 +0200
@@ -1,7 +1,7 @@
#
# spec file for package python-webauthn
#
-# Copyright (c) 2025 SUSE LLC and contributors
+# 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
@@ -18,7 +18,7 @@
%{?sle15_python_module_pythons}
Name: python-webauthn
-Version: 2.7.0
+Version: 2.7.1
Release: 0
Summary: Pythonic WebAuthn
License: BSD-3-Clause
@@ -29,17 +29,17 @@
BuildRequires: %{python_module wheel}
BuildRequires: python-rpm-macros
# SECTION test requirements
-BuildRequires: %{python_module asn1crypto >= 1.5.1}
+BuildRequires: %{python_module pyasn1 >= 0.6.2}
BuildRequires: %{python_module cbor2 >= 5.6.2}
BuildRequires: %{python_module cryptography >= 44.0.2}
BuildRequires: %{python_module pyOpenSSL >= 25.0.0}
BuildRequires: %{python_module pytest}
# /SECTION
BuildRequires: fdupes
-Requires: python-asn1crypto >= 1.5.1
Requires: python-cbor2 >= 5.6.2
Requires: python-cryptography >= 44.0.2
Requires: python-pyOpenSSL >= 25.0.0
+Requires: python-pyasn1 >= 0.6.2
BuildArch: noarch
%python_subpackages
++++++ webauthn-2.7.0.tar.gz -> webauthn-2.7.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/py_webauthn-2.7.0/CHANGELOG.md
new/py_webauthn-2.7.1/CHANGELOG.md
--- old/py_webauthn-2.7.0/CHANGELOG.md 2025-09-05 01:17:58.000000000 +0200
+++ new/py_webauthn-2.7.1/CHANGELOG.md 2026-02-12 00:33:40.000000000 +0100
@@ -1,5 +1,12 @@
# Changelog
+## v2.7.1
+
+**Changes:**
+
+- This project now uses the [pyasn1](https://github.com/pyasn1/pyasn1/)
library to parse ASN.1-encoded values
([#263](https://github.com/duo-labs/py_webauthn/pull/263), h/t @ggirol-rc)
+- Some bare `dict` type annotations have been replaced with `Dict[str, Any]`
to satisfy stricter type checking setups
([#262](https://github.com/duo-labs/py_webauthn/pull/262), h/t @typestring)
+
## v2.7.0
**Changes:**
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/py_webauthn-2.7.0/mypy.ini
new/py_webauthn-2.7.1/mypy.ini
--- old/py_webauthn-2.7.0/mypy.ini 2025-09-05 01:17:58.000000000 +0200
+++ new/py_webauthn-2.7.1/mypy.ini 2026-02-12 00:33:40.000000000 +0100
@@ -1,9 +1,6 @@
[mypy]
python_version = 3.9
-[mypy-asn1crypto.*]
-ignore_missing_imports = True
-
[mypy-cbor2.*]
ignore_missing_imports = True
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/py_webauthn-2.7.0/pyproject.toml
new/py_webauthn-2.7.1/pyproject.toml
--- old/py_webauthn-2.7.0/pyproject.toml 2025-09-05 01:17:58.000000000
+0200
+++ new/py_webauthn-2.7.1/pyproject.toml 2026-02-12 00:33:40.000000000
+0100
@@ -18,7 +18,7 @@
]
requires-python = ">=3.9"
dependencies = [
- "asn1crypto>=1.5.1",
+ "pyasn1>=0.6.2",
"cbor2>=5.6.5",
"cryptography>=44.0.2",
"pyOpenSSL>=25.0.0",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/py_webauthn-2.7.0/requirements.txt
new/py_webauthn-2.7.1/requirements.txt
--- old/py_webauthn-2.7.0/requirements.txt 2025-09-05 01:17:58.000000000
+0200
+++ new/py_webauthn-2.7.1/requirements.txt 2026-02-12 00:33:40.000000000
+0100
@@ -1,4 +1,4 @@
-asn1crypto==1.5.1
+pyasn1==0.6.2
black==24.8.0
cbor2==5.6.5
cffi==1.17.1
@@ -18,3 +18,4 @@
toml==0.10.2
tomli==2.0.1
typing_extensions==4.12.2
+types-pyasn1==0.6.0.20250914
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/py_webauthn-2.7.0/webauthn/__init__.py
new/py_webauthn-2.7.1/webauthn/__init__.py
--- old/py_webauthn-2.7.0/webauthn/__init__.py 2025-09-05 01:17:58.000000000
+0200
+++ new/py_webauthn-2.7.1/webauthn/__init__.py 2026-02-12 00:33:40.000000000
+0100
@@ -8,7 +8,7 @@
)
from .helpers import base64url_to_bytes, options_to_json
-__version__ = "2.7.0"
+__version__ = "2.7.1"
__all__ = [
"generate_registration_options",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/py_webauthn-2.7.0/webauthn/authentication/verify_authentication_response.py
new/py_webauthn-2.7.1/webauthn/authentication/verify_authentication_response.py
---
old/py_webauthn-2.7.0/webauthn/authentication/verify_authentication_response.py
2025-09-05 01:17:58.000000000 +0200
+++
new/py_webauthn-2.7.1/webauthn/authentication/verify_authentication_response.py
2026-02-12 00:33:40.000000000 +0100
@@ -1,6 +1,6 @@
from dataclasses import dataclass
import hashlib
-from typing import List, Union
+from typing import Any, Dict, List, Union
from cryptography.exceptions import InvalidSignature
@@ -46,7 +46,7 @@
def verify_authentication_response(
*,
- credential: Union[str, dict, AuthenticationCredential],
+ credential: Union[str, Dict[str, Any], AuthenticationCredential],
expected_challenge: bytes,
expected_rp_id: str,
expected_origin: Union[str, List[str]],
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/py_webauthn-2.7.0/webauthn/helpers/asn1/android_key.py
new/py_webauthn-2.7.1/webauthn/helpers/asn1/android_key.py
--- old/py_webauthn-2.7.0/webauthn/helpers/asn1/android_key.py 2025-09-05
01:17:58.000000000 +0200
+++ new/py_webauthn-2.7.1/webauthn/helpers/asn1/android_key.py 2026-02-12
00:33:40.000000000 +0100
@@ -1,6 +1,9 @@
from enum import Enum
-from asn1crypto.core import (
+from pyasn1.type import tag
+from pyasn1.type.namedtype import NamedTypes, NamedType, OptionalNamedType
+from pyasn1.type.namedval import NamedValues
+from pyasn1.type.univ import (
Boolean,
Enumerated,
Integer,
@@ -12,75 +15,261 @@
class Integers(SetOf):
- _child_spec = Integer
+ # type error ignored due to https://github.com/python/typeshed/issues/15369
+ componentType = Integer() # type: ignore
class SecurityLevel(Enumerated):
- _map = {
- 0: "Software",
- 1: "TrustedEnvironment",
- 2: "StrongBox",
- }
+ namedValues = NamedValues(
+ ("Software", 0),
+ ("TrustedEnvironment", 1),
+ ("StrongBox", 2),
+ )
class VerifiedBootState(Enumerated):
- _map = {
- 0: "Verified",
- 1: "SelfSigned",
- 2: "Unverified",
- 3: "Failed",
- }
+ namedValues = NamedValues(
+ ("Verified", 0),
+ ("SelfSigned", 1),
+ ("Unverified", 2),
+ ("Failed", 3),
+ )
class RootOfTrust(Sequence):
- _fields = [
- ("verifiedBootKey", OctetString),
- ("deviceLocked", Boolean),
- ("verifiedBootState", VerifiedBootState),
- ("verifiedBootHash", OctetString),
- ]
+ componentType = NamedTypes(
+ NamedType("verifiedBootKey", OctetString()),
+ NamedType("deviceLocked", Boolean()),
+ NamedType("verifiedBootState", VerifiedBootState()),
+ NamedType("verifiedBootHash", OctetString()),
+ )
class AuthorizationList(Sequence):
- _fields = [
- ("purpose", Integers, {"explicit": 1, "optional": True}),
- ("algorithm", Integer, {"explicit": 2, "optional": True}),
- ("keySize", Integer, {"explicit": 3, "optional": True}),
- ("digest", Integers, {"explicit": 5, "optional": True}),
- ("padding", Integers, {"explicit": 6, "optional": True}),
- ("ecCurve", Integer, {"explicit": 10, "optional": True}),
- ("rsaPublicExponent", Integer, {"explicit": 200, "optional": True}),
- ("rollbackResistance", Null, {"explicit": 303, "optional": True}),
- ("activeDateTime", Integer, {"explicit": 400, "optional": True}),
- ("originationExpireDateTime", Integer, {"explicit": 401, "optional":
True}),
- ("usageExpireDateTime", Integer, {"explicit": 402, "optional": True}),
- ("noAuthRequired", Null, {"explicit": 503, "optional": True}),
- ("userAuthType", Integer, {"explicit": 504, "optional": True}),
- ("authTimeout", Integer, {"explicit": 505, "optional": True}),
- ("allowWhileOnBody", Null, {"explicit": 506, "optional": True}),
- ("trustedUserPresenceRequired", Null, {"explicit": 507, "optional":
True}),
- ("trustedConfirmationRequired", Null, {"explicit": 508, "optional":
True}),
- ("unlockedDeviceRequired", Null, {"explicit": 509, "optional": True}),
- ("allApplications", Null, {"explicit": 600, "optional": True}),
- ("applicationId", OctetString, {"explicit": 601, "optional": True}),
- ("creationDateTime", Integer, {"explicit": 701, "optional": True}),
- ("origin", Integer, {"explicit": 702, "optional": True}),
- ("rollbackResistant", Null, {"explicit": 703, "optional": True}),
- ("rootOfTrust", RootOfTrust, {"explicit": 704, "optional": True}),
- ("osVersion", Integer, {"explicit": 705, "optional": True}),
- ("osPatchLevel", Integer, {"explicit": 706, "optional": True}),
- ("attestationApplicationId", OctetString, {"explicit": 709,
"optional": True}),
- ("attestationIdBrand", OctetString, {"explicit": 710, "optional":
True}),
- ("attestationIdDevice", OctetString, {"explicit": 711, "optional":
True}),
- ("attestationIdProduct", OctetString, {"explicit": 712, "optional":
True}),
- ("attestationIdSerial", OctetString, {"explicit": 713, "optional":
True}),
- ("attestationIdImei", OctetString, {"explicit": 714, "optional":
True}),
- ("attestationIdMeid", OctetString, {"explicit": 715, "optional":
True}),
- ("attestationIdManufacturer", OctetString, {"explicit": 716,
"optional": True}),
- ("attestationIdModel", OctetString, {"explicit": 717, "optional":
True}),
- ("vendorPatchLevel", Integer, {"explicit": 718, "optional": True}),
- ("bootPatchLevel", Integer, {"explicit": 719, "optional": True}),
- ]
+ componentType = NamedTypes(
+ OptionalNamedType(
+ "purpose",
+ Integers().subtype(
+ explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple,
1)
+ ),
+ ),
+ OptionalNamedType(
+ "algorithm",
+ Integer().subtype(
+ explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple,
2)
+ ),
+ ),
+ OptionalNamedType(
+ "keySize",
+ Integer().subtype(
+ explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple,
3)
+ ),
+ ),
+ OptionalNamedType(
+ "digest",
+ Integers().subtype(
+ explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple,
5)
+ ),
+ ),
+ OptionalNamedType(
+ "padding",
+ Integers().subtype(
+ explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple,
6)
+ ),
+ ),
+ OptionalNamedType(
+ "ecCurve",
+ Integer().subtype(
+ explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple,
10)
+ ),
+ ),
+ OptionalNamedType(
+ "rsaPublicExponent",
+ Integer().subtype(
+ explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple,
200)
+ ),
+ ),
+ OptionalNamedType(
+ "rollbackResistance",
+ Null().subtype(
+ explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple,
303)
+ ),
+ ),
+ OptionalNamedType(
+ "activeDateTime",
+ Integer().subtype(
+ explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple,
400)
+ ),
+ ),
+ OptionalNamedType(
+ "originationExpireDateTime",
+ Integer().subtype(
+ explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple,
401)
+ ),
+ ),
+ OptionalNamedType(
+ "usageExpireDateTime",
+ Integer().subtype(
+ explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple,
402)
+ ),
+ ),
+ OptionalNamedType(
+ "noAuthRequired",
+ Null().subtype(
+ explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple,
503)
+ ),
+ ),
+ OptionalNamedType(
+ "userAuthType",
+ Integer().subtype(
+ explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple,
504)
+ ),
+ ),
+ OptionalNamedType(
+ "authTimeout",
+ Integer().subtype(
+ explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple,
505)
+ ),
+ ),
+ OptionalNamedType(
+ "allowWhileOnBody",
+ Null().subtype(
+ explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple,
506)
+ ),
+ ),
+ OptionalNamedType(
+ "trustedUserPresenceRequired",
+ Null().subtype(
+ explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple,
507)
+ ),
+ ),
+ OptionalNamedType(
+ "trustedConfirmationRequired",
+ Null().subtype(
+ explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple,
508)
+ ),
+ ),
+ OptionalNamedType(
+ "unlockedDeviceRequired",
+ Null().subtype(
+ explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple,
509)
+ ),
+ ),
+ OptionalNamedType(
+ "allApplications",
+ Null().subtype(
+ explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple,
600)
+ ),
+ ),
+ OptionalNamedType(
+ "applicationId",
+ OctetString().subtype(
+ explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple,
601)
+ ),
+ ),
+ OptionalNamedType(
+ "creationDateTime",
+ Integer().subtype(
+ explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple,
701)
+ ),
+ ),
+ OptionalNamedType(
+ "origin",
+ Integer().subtype(
+ explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple,
702)
+ ),
+ ),
+ OptionalNamedType(
+ "rollbackResistant",
+ Null().subtype(
+ explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple,
703)
+ ),
+ ),
+ OptionalNamedType(
+ "rootOfTrust",
+ RootOfTrust().subtype(
+ explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple,
704)
+ ),
+ ),
+ OptionalNamedType(
+ "osVersion",
+ Integer().subtype(
+ explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple,
705)
+ ),
+ ),
+ OptionalNamedType(
+ "osPatchLevel",
+ Integer().subtype(
+ explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple,
706)
+ ),
+ ),
+ OptionalNamedType(
+ "attestationApplicationId",
+ OctetString().subtype(
+ explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple,
709)
+ ),
+ ),
+ OptionalNamedType(
+ "attestationIdBrand",
+ OctetString().subtype(
+ explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple,
710)
+ ),
+ ),
+ OptionalNamedType(
+ "attestationIdDevice",
+ OctetString().subtype(
+ explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple,
711)
+ ),
+ ),
+ OptionalNamedType(
+ "attestationIdProduct",
+ OctetString().subtype(
+ explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple,
712)
+ ),
+ ),
+ OptionalNamedType(
+ "attestationIdSerial",
+ OctetString().subtype(
+ explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple,
713)
+ ),
+ ),
+ OptionalNamedType(
+ "attestationIdImei",
+ OctetString().subtype(
+ explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple,
714)
+ ),
+ ),
+ OptionalNamedType(
+ "attestationIdMeid",
+ OctetString().subtype(
+ explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple,
715)
+ ),
+ ),
+ OptionalNamedType(
+ "attestationIdManufacturer",
+ OctetString().subtype(
+ explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple,
716)
+ ),
+ ),
+ OptionalNamedType(
+ "attestationIdModel",
+ OctetString().subtype(
+ explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple,
717)
+ ),
+ ),
+ OptionalNamedType(
+ "vendorPatchLevel",
+ Integer().subtype(
+ explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple,
718)
+ ),
+ ),
+ OptionalNamedType(
+ "bootPatchLevel",
+ Integer().subtype(
+ explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple,
719)
+ ),
+ ),
+ )
class KeyDescription(Sequence):
@@ -93,16 +282,16 @@
See https://source.android.com/security/keystore/attestation#schema
"""
- _fields = [
- ("attestationVersion", Integer),
- ("attestationSecurityLevel", SecurityLevel),
- ("keymasterVersion", Integer),
- ("keymasterSecurityLevel", SecurityLevel),
- ("attestationChallenge", OctetString),
- ("uniqueId", OctetString),
- ("softwareEnforced", AuthorizationList),
- ("teeEnforced", AuthorizationList),
- ]
+ componentType = NamedTypes(
+ NamedType("attestationVersion", Integer()),
+ NamedType("attestationSecurityLevel", SecurityLevel()),
+ NamedType("keymasterVersion", Integer()),
+ NamedType("keymasterSecurityLevel", SecurityLevel()),
+ NamedType("attestationChallenge", OctetString()),
+ NamedType("uniqueId", OctetString()),
+ NamedType("softwareEnforced", AuthorizationList()),
+ NamedType("teeEnforced", AuthorizationList()),
+ )
class KeyOrigin(int, Enum):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/py_webauthn-2.7.0/webauthn/helpers/parse_attestation_statement.py
new/py_webauthn-2.7.1/webauthn/helpers/parse_attestation_statement.py
--- old/py_webauthn-2.7.0/webauthn/helpers/parse_attestation_statement.py
2025-09-05 01:17:58.000000000 +0200
+++ new/py_webauthn-2.7.1/webauthn/helpers/parse_attestation_statement.py
2026-02-12 00:33:40.000000000 +0100
@@ -1,7 +1,9 @@
+from typing import Any, Dict
+
from .structs import AttestationStatement
-def parse_attestation_statement(val: dict) -> AttestationStatement:
+def parse_attestation_statement(val: Dict[str, Any]) -> AttestationStatement:
"""
Turn `response.attestationObject.attStmt` into structured data
"""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/py_webauthn-2.7.0/webauthn/helpers/parse_authentication_credential_json.py
new/py_webauthn-2.7.1/webauthn/helpers/parse_authentication_credential_json.py
---
old/py_webauthn-2.7.0/webauthn/helpers/parse_authentication_credential_json.py
2025-09-05 01:17:58.000000000 +0200
+++
new/py_webauthn-2.7.1/webauthn/helpers/parse_authentication_credential_json.py
2026-02-12 00:33:40.000000000 +0100
@@ -1,6 +1,6 @@
import json
from json.decoder import JSONDecodeError
-from typing import Union
+from typing import Any, Dict, Union
from .exceptions import InvalidAuthenticationResponse, InvalidJSONStructure
from .base64url_to_bytes import base64url_to_bytes
@@ -12,7 +12,9 @@
)
-def parse_authentication_credential_json(json_val: Union[str, dict]) ->
AuthenticationCredential:
+def parse_authentication_credential_json(
+ json_val: Union[str, Dict[str, Any]]
+) -> AuthenticationCredential:
"""
Parse a JSON form of an authentication credential, as either a stringified
JSON object or a
plain dict, into an instance of AuthenticationCredential
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/py_webauthn-2.7.0/webauthn/helpers/parse_authentication_options_json.py
new/py_webauthn-2.7.1/webauthn/helpers/parse_authentication_options_json.py
--- old/py_webauthn-2.7.0/webauthn/helpers/parse_authentication_options_json.py
2025-09-05 01:17:58.000000000 +0200
+++ new/py_webauthn-2.7.1/webauthn/helpers/parse_authentication_options_json.py
2026-02-12 00:33:40.000000000 +0100
@@ -1,6 +1,6 @@
import json
from json import JSONDecodeError
-from typing import List, Optional, Union
+from typing import Any, Dict, List, Optional, Union
from .base64url_to_bytes import base64url_to_bytes
from .exceptions import InvalidJSONStructure, InvalidAuthenticationOptions
@@ -13,7 +13,7 @@
def parse_authentication_options_json(
- json_val: Union[str, dict]
+ json_val: Union[str, Dict[str, Any]]
) -> PublicKeyCredentialRequestOptions:
"""
Parse a JSON form of authentication options, as either stringified JSON or
a plain dict, into an
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/py_webauthn-2.7.0/webauthn/helpers/parse_registration_credential_json.py
new/py_webauthn-2.7.1/webauthn/helpers/parse_registration_credential_json.py
---
old/py_webauthn-2.7.0/webauthn/helpers/parse_registration_credential_json.py
2025-09-05 01:17:58.000000000 +0200
+++
new/py_webauthn-2.7.1/webauthn/helpers/parse_registration_credential_json.py
2026-02-12 00:33:40.000000000 +0100
@@ -1,6 +1,6 @@
import json
from json.decoder import JSONDecodeError
-from typing import Union, Optional, List
+from typing import Any, Dict, Union, Optional, List
from .base64url_to_bytes import base64url_to_bytes
from .exceptions import InvalidRegistrationResponse, InvalidJSONStructure
@@ -13,7 +13,9 @@
)
-def parse_registration_credential_json(json_val: Union[str, dict]) ->
RegistrationCredential:
+def parse_registration_credential_json(
+ json_val: Union[str, Dict[str, Any]]
+) -> RegistrationCredential:
"""
Parse a JSON form of a registration credential, as either a stringified
JSON object or a
plain dict, into an instance of RegistrationCredential
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/py_webauthn-2.7.0/webauthn/helpers/parse_registration_options_json.py
new/py_webauthn-2.7.1/webauthn/helpers/parse_registration_options_json.py
--- old/py_webauthn-2.7.0/webauthn/helpers/parse_registration_options_json.py
2025-09-05 01:17:58.000000000 +0200
+++ new/py_webauthn-2.7.1/webauthn/helpers/parse_registration_options_json.py
2026-02-12 00:33:40.000000000 +0100
@@ -1,6 +1,6 @@
import json
from json.decoder import JSONDecodeError
-from typing import Union, Optional, List
+from typing import Any, Dict, Union, Optional, List
from .structs import (
@@ -23,7 +23,7 @@
def parse_registration_options_json(
- json_val: Union[str, dict]
+ json_val: Union[str, Dict[str, Any]]
) -> PublicKeyCredentialCreationOptions:
"""
Parse a JSON form of registration options, as either stringified JSON or a
plain dict, into an
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/py_webauthn-2.7.0/webauthn/registration/formats/android_key.py
new/py_webauthn-2.7.1/webauthn/registration/formats/android_key.py
--- old/py_webauthn-2.7.0/webauthn/registration/formats/android_key.py
2025-09-05 01:17:58.000000000 +0200
+++ new/py_webauthn-2.7.1/webauthn/registration/formats/android_key.py
2026-02-12 00:33:40.000000000 +0100
@@ -1,7 +1,8 @@
import hashlib
from typing import List
-from asn1crypto.core import OctetString
+from pyasn1.type.univ import OctetString
+from pyasn1.codec.der.decoder import decode as der_decode
from cryptography import x509
from cryptography.exceptions import InvalidSignature
from cryptography.hazmat.primitives.serialization import Encoding, PublicFormat
@@ -164,7 +165,11 @@
# want
ext_value_wrapper: UnrecognizedExtension = ext_key_description.value
ext_value: bytes = ext_value_wrapper.value
- parsed_ext = KeyDescription.load(ext_value)
+ parsed_ext, trailing_garbage = der_decode(ext_value, asn1Spec =
KeyDescription())
+ if trailing_garbage:
+ raise InvalidRegistrationResponse(
+ f"Extension {ext_key_description_oid} (Android key) has trailing
garbage"
+ )
# Verify that the attestationChallenge field in the attestation
certificate extension data
# is identical to clientDataHash.
@@ -182,26 +187,26 @@
# The AuthorizationList.allApplications field is not present on either
authorization
# list (softwareEnforced nor teeEnforced), since PublicKeyCredential MUST
be scoped
# to the RP ID.
- if software_enforced["allApplications"].native is not None:
+ if software_enforced["allApplications"].hasValue():
raise InvalidRegistrationResponse(
"allApplications field was present in softwareEnforced (Android
Key)"
)
- if tee_enforced["allApplications"].native is not None:
+ if tee_enforced["allApplications"].hasValue():
raise InvalidRegistrationResponse(
"allApplications field was present in teeEnforced (Android Key)"
)
# The value in the AuthorizationList.origin field is equal to
KM_ORIGIN_GENERATED.
- origin = tee_enforced["origin"].native
- if origin != KeyOrigin.GENERATED:
+ origin = tee_enforced["origin"]
+ if origin != KeyOrigin.GENERATED.value:
raise InvalidRegistrationResponse(
f"teeEnforced.origin {origin} was not {KeyOrigin.GENERATED}"
)
# The value in the AuthorizationList.purpose field is equal to
KM_PURPOSE_SIGN.
- purpose = tee_enforced["purpose"].native
- if purpose != [KeyPurpose.SIGN]:
+ purpose = tee_enforced["purpose"]
+ if purpose != [KeyPurpose.SIGN.value]:
raise InvalidRegistrationResponse(
f"teeEnforced.purpose {purpose} was not [{KeyPurpose.SIGN}]"
)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/py_webauthn-2.7.0/webauthn/registration/verify_registration_response.py
new/py_webauthn-2.7.1/webauthn/registration/verify_registration_response.py
--- old/py_webauthn-2.7.0/webauthn/registration/verify_registration_response.py
2025-09-05 01:17:58.000000000 +0200
+++ new/py_webauthn-2.7.1/webauthn/registration/verify_registration_response.py
2026-02-12 00:33:40.000000000 +0100
@@ -1,6 +1,6 @@
import hashlib
from dataclasses import dataclass, asdict
-from typing import List, Mapping, Optional, Union
+from typing import Any, Dict, List, Mapping, Optional, Union
from webauthn.helpers import (
aaguid_to_string,
@@ -66,7 +66,7 @@
def verify_registration_response(
*,
- credential: Union[str, dict, RegistrationCredential],
+ credential: Union[str, Dict[str, Any], RegistrationCredential],
expected_challenge: bytes,
expected_rp_id: str,
expected_origin: Union[str, List[str]],