1"""Signature container class"""
2
3from __future__ import annotations
4
5import logging
6from typing import Any
7
8from securesystemslib._internal.utils import make_hashable
9
10logger = logging.getLogger(__name__)
11
12
13class Signature:
14 """A container class containing information about a signature.
15
16 Contains a signature and the keyid uniquely identifying the key used
17 to generate the signature.
18
19 Provides utility methods to easily create an object from a dictionary
20 and return the dictionary representation of the object.
21
22 Args:
23 keyid: HEX string used as a unique identifier of the key.
24 sig: HEX string representing the signature.
25 unrecognized_fields: Dictionary of all attributes that are not managed
26 by securesystemslib.
27
28 Attributes:
29 keyid: HEX string used as a unique identifier of the key.
30 signature: HEX string representing the signature.
31 unrecognized_fields: Dictionary of all attributes that are not managed
32 by securesystemslib.
33
34 """
35
36 def __init__(
37 self,
38 keyid: str,
39 sig: str,
40 unrecognized_fields: dict[str, Any] | None = None,
41 ):
42 self.keyid = keyid
43 self.signature = sig
44
45 if unrecognized_fields is None:
46 unrecognized_fields = {}
47
48 self.unrecognized_fields = unrecognized_fields
49
50 def __eq__(self, other: Any) -> bool:
51 if not isinstance(other, Signature):
52 return False
53
54 return (
55 self.keyid == other.keyid
56 and self.signature == other.signature
57 and self.unrecognized_fields == other.unrecognized_fields
58 )
59
60 def __hash__(self) -> int:
61 return hash(
62 (
63 self.keyid,
64 self.signature,
65 make_hashable(self.unrecognized_fields),
66 )
67 )
68
69 @classmethod
70 def from_dict(cls, signature_dict: dict) -> Signature:
71 """Creates a Signature object from its JSON/dict representation.
72
73 Arguments:
74 signature_dict:
75 A dict containing a valid keyid and a signature.
76 Note that the fields in it should be named "keyid" and "sig"
77 respectively.
78
79 Raises:
80 KeyError: If any of the "keyid" and "sig" fields are missing from
81 the signature_dict.
82
83 Side Effect:
84 Destroys the metadata dict passed by reference.
85
86 Returns:
87 A "Signature" instance.
88 """
89
90 keyid = signature_dict.pop("keyid")
91 sig = signature_dict.pop("sig")
92 # All fields left in the signature_dict are unrecognized.
93 return cls(keyid, sig, signature_dict)
94
95 def to_dict(self) -> dict:
96 """Returns the JSON-serializable dictionary representation of self."""
97
98 return {
99 "keyid": self.keyid,
100 "sig": self.signature,
101 **self.unrecognized_fields,
102 }