From 1ce36d0cd6ed1a25c5c2aa6f94f092013bbf390e Mon Sep 17 00:00:00 2001 From: Jussi Kukkonen Date: Thu, 3 Jun 2021 10:09:43 +0300 Subject: [PATCH] Metadata API: Use OrderedDict for signatures Dict ordering is part of regular Dict from Python 3.7: Use OrderedDict for signatures to make sure signatures are serialized in a reproducible order even on 3.6. The added benefit is that reader will immediately understand that the order has some significance. The actual type annotations are a bit convoluted because: * typing does not include OrderedDict before 3.7 so can't use that * Annotating inner types does not work for collections.OrderedDict in older pythons (so have to use the "stringified annotations") Signed-off-by: Jussi Kukkonen --- tuf/api/metadata.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/tuf/api/metadata.py b/tuf/api/metadata.py index 2a25d402..2fcb561a 100644 --- a/tuf/api/metadata.py +++ b/tuf/api/metadata.py @@ -17,6 +17,7 @@ """ import abc import tempfile +from collections import OrderedDict from datetime import datetime, timedelta from typing import Any, ClassVar, Dict, List, Mapping, Optional, Tuple, Type @@ -48,11 +49,13 @@ class Metadata: signed: A subclass of Signed, which has the actual metadata payload, i.e. one of Targets, Snapshot, Timestamp or Root. - signatures: A dict of keyids to Securesystemslib Signature objects, - each signing the canonical serialized representation of 'signed'. + signatures: An ordered dictionary of keyids to Signature objects, each + signing the canonical serialized representation of 'signed'. """ - def __init__(self, signed: "Signed", signatures: Dict[str, Signature]): + def __init__( + self, signed: "Signed", signatures: "OrderedDict[str, Signature]" + ): self.signed = signed self.signatures = signatures @@ -89,7 +92,7 @@ def from_dict(cls, metadata: Dict[str, Any]) -> "Metadata": raise ValueError(f'unrecognized metadata type "{_type}"') # Make sure signatures are unique - signatures: Dict[str, Signature] = {} + signatures: "OrderedDict[str, Signature]" = OrderedDict() for sig_dict in metadata.pop("signatures"): sig = Signature.from_dict(sig_dict) if sig.keyid in signatures: @@ -249,7 +252,7 @@ def sign( if append: self.signatures[signature.keyid] = signature else: - self.signatures = {signature.keyid: signature} + self.signatures = OrderedDict({signature.keyid: signature}) return signature