Skip to content

Commit

Permalink
Add unrecognized fields support for Signature
Browse files Browse the repository at this point in the history
The TUF specification says the following regarding unknown fields:
"All of the formats described below include the ability to add more
attribute-value fields to objects for backward-compatible format
changes. Implementers who encounter undefined attribute-value pairs in
the format must include the data when calculating hashes or verifying
signatures and must preserve the data when re-serializing."
From: https://theupdateframework.github.io/specification/latest/#document-formats

This section is the reason ADR0008 was accepted inside python-tuf
(see here: https://github.com/theupdateframework/python-tuf/blob/develop/docs/adr/0008-accept-unrecognised-fields.md)
and we have added support for unrecognized fields for all fields
inside the SIGNED portion of the metadata.
However, this limits what the citation implies or that everywhere there
inside the metadata files including signatures we should accept
unrecognized fields. That's why I made these changes.
These changes have the approval of the community see:
- theupdateframework/specification#203
- theupdateframework/python-tuf#1802

Another change I had to do, so I can add unrecognized fields support
inside Signature is to make "Signature.from_dict()" to behave the same
way as the rest of the "from_dict()" functions inside TUF or destroy
the input dictionary.
This was necessary, as that provides me with an easy way to pass the
unrecognized fields to the constructor.

Signed-off-by: Martin Vrachev <[email protected]>
  • Loading branch information
MVrachev committed Feb 9, 2022
1 parent cb72257 commit 8213d77
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 7 deletions.
31 changes: 26 additions & 5 deletions securesystemslib/signer.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import abc
import securesystemslib.keys as sslib_keys
from typing import Any, Dict
from typing import Any, Dict, Optional, Mapping


class Signature:
Expand All @@ -22,18 +22,30 @@ class Signature:
Attributes:
keyid: HEX string used as a unique identifier of the key.
signature: HEX string representing the signature.
unrecognized_fields: Dictionary of all attributes that are not managed
by securesystemslib.
"""
def __init__(self, keyid: str, sig: str):
def __init__(
self,
keyid: str,
sig: str,
unrecognized_fields: Optional[Mapping[str, Any]] = None
):
self.keyid = keyid
self.signature = sig
self.unrecognized_fields: Mapping[str, Any] = unrecognized_fields or {}


def __eq__(self, other: Any) -> bool:
if not isinstance(other, Signature):
return False

return self.keyid == other.keyid and self.signature == other.signature
return (
self.keyid == other.keyid
and self.signature == other.signature
and self.unrecognized_fields == other.unrecognized_fields
)


@classmethod
Expand All @@ -50,19 +62,28 @@ def from_dict(cls, signature_dict: Dict) -> "Signature":
KeyError: If any of the "keyid" and "sig" fields are missing from
the signature_dict.
Side Effect:
Destroys the metadata dict passed by reference.
Returns:
A "Signature" instance.
"""

return cls(signature_dict["keyid"], signature_dict["sig"])
keyid = signature_dict.pop("keyid")
sig = signature_dict.pop("sig")
# All fields left in the signature_dict are unrecognized.
return cls(
keyid, sig, signature_dict
)


def to_dict(self) -> Dict:
"""Returns the JSON-serializable dictionary representation of self."""

return {
"keyid": self.keyid,
"sig": self.signature
"sig": self.signature,
**self.unrecognized_fields,
}


Expand Down
8 changes: 6 additions & 2 deletions tests/test_signer.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,13 @@ def test_sslib_sign(self):
def test_signature_from_to_dict(self):
signature_dict = {
"sig": "30460221009342e4566528fcecf6a7a5d53ebacdb1df151e242f55f8775883469cb01dbc6602210086b426cc826709acfa2c3f9214610cb0a832db94bbd266fd7c5939a48064a851",
"keyid": "11fa391a0ed7a447cbfeb4b2667e286fc248f64d5e6d0eeed2e5e23f97f9f714"
"keyid": "11fa391a0ed7a447cbfeb4b2667e286fc248f64d5e6d0eeed2e5e23f97f9f714",
"foo": "bar" # unrecognized_field
}
sig_obj = Signature.from_dict(signature_dict)
sig_obj = Signature.from_dict(copy.copy(signature_dict))

# Verify that unrecognized fields are stored correctly.
self.assertEqual(sig_obj.unrecognized_fields, {"foo": "bar"})

self.assertDictEqual(signature_dict, sig_obj.to_dict())

Expand Down

0 comments on commit 8213d77

Please sign in to comment.