Files
sourcehub/.venv/Lib/site-packages/joserfc/_rfc7797/compact.py
T
2026-09-14 23:22:10 +09:00

91 lines
2.8 KiB
Python

import re
from typing import Any
from ..util import (
to_bytes,
to_str,
json_b64encode,
urlsafe_b64encode,
urlsafe_b64decode,
)
from .._rfc7515.model import JWSAlgModel, CompactSignature
from .._rfc7515.compact import decode_header
from .._rfc7515.registry import JWSRegistry, default_registry
from ..errors import DecodeError
from .util import is_rfc7797_enabled
def sign_rfc7515_compact(obj: CompactSignature, alg: JWSAlgModel, key: Any) -> bytes:
header_segment = json_b64encode(obj.headers())
signing_input = header_segment + b"." + obj.payload
signature = urlsafe_b64encode(alg.sign(signing_input, key))
# if need to detach payload
if __is_urlsafe_characters(obj.payload):
out = signing_input + b"." + signature
else:
out = header_segment + b".." + signature
return out
def extract_rfc7515_compact(
value: bytes, payload: bytes | str | None = None, registry: JWSRegistry | None = None
) -> CompactSignature:
"""Extract the JWS Compact Serialization from bytes to object.
:param value: JWS in bytes
:param payload: optional payload, required with detached content
:param registry: optional JWSRegistry instance
:raise DecodeError: when decoding fails
"""
parts = value.split(b".")
if len(parts) != 3:
raise DecodeError("Invalid JSON Web Signature")
if registry is None:
registry = default_registry
header_segment, payload_segment, signature_segment = parts
registry.validate_header_size(header_segment)
registry.validate_signature_size(signature_segment)
if payload_segment:
registry.validate_payload_size(payload_segment)
protected = decode_header(header_segment)
if is_rfc7797_enabled(protected):
if not payload_segment and payload:
payload_segment = to_bytes(payload)
registry.validate_payload_size(payload_segment)
payload = payload_segment
else:
if not payload_segment and payload:
payload = to_bytes(payload)
payload_segment = urlsafe_b64encode(payload)
else:
try:
payload = urlsafe_b64decode(payload_segment)
except (TypeError, ValueError):
raise DecodeError("Invalid payload")
obj = CompactSignature(protected, payload)
obj.segments.update(
{
"header": header_segment,
"payload": payload_segment,
"signature": signature_segment,
}
)
return obj
# https://datatracker.ietf.org/doc/html/rfc7797#section-5.2
# the application MUST ensure that the payload contains only the URL-safe
# characters 'a'-'z', 'A'-'Z', '0'-'9', dash ('-'), underscore ('_'),
# and tilde ('~')
_re_urlsafe = re.compile("^[a-zA-Z0-9-_~]+$")
def __is_urlsafe_characters(s: bytes | str) -> bool:
return bool(_re_urlsafe.match(to_str(s)))