From e7cdab018153a8fe81a0ec691a3a00f181fba4b9 Mon Sep 17 00:00:00 2001 From: Martin Vrachev Date: Thu, 10 Jun 2021 16:41:17 +0300 Subject: [PATCH] New Metadata API: add Key class validation Reuse securesystemslib format checks to easily check key attributes. Had to change "id" to "abcd" when calling "Key.from_dict()", because "id" is not a string in hexdigest format. Signed-off-by: Martin Vrachev --- tests/test_api.py | 6 +++--- tuf/api/metadata.py | 12 +++++++++++- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/tests/test_api.py b/tests/test_api.py index 7d00a85720..7b141223db 100755 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -366,18 +366,18 @@ def test_key_class(self): # Testing that the workflow of deserializing and serializing # a key dictionary doesn't change the content. test_key_dict = key_dict.copy() - key_obj = Key.from_dict("id", test_key_dict) + key_obj = Key.from_dict("abcd", test_key_dict) self.assertEqual(key_dict, key_obj.to_dict()) # Test creating an instance without a required attribute. for key in key_dict.keys(): test_key_dict = key_dict.copy() del test_key_dict[key] with self.assertRaises(KeyError): - Key.from_dict("id", test_key_dict) + Key.from_dict("abcd", test_key_dict) # Test creating a Key instance with wrong keyval format. key_dict["keyval"] = {} with self.assertRaises(ValueError): - Key.from_dict("id", key_dict) + Key.from_dict("abcd", key_dict) def test_role_class(self): diff --git a/tuf/api/metadata.py b/tuf/api/metadata.py index 5f6a210e45..74385cd1cf 100644 --- a/tuf/api/metadata.py +++ b/tuf/api/metadata.py @@ -20,6 +20,7 @@ from datetime import datetime, timedelta from typing import Any, ClassVar, Dict, List, Mapping, Optional, Tuple, Type +from securesystemslib import formats from securesystemslib import keys as sslib_keys from securesystemslib.signer import Signature, Signer from securesystemslib.storage import FilesystemBackend, StorageBackendInterface @@ -398,7 +399,16 @@ def __init__( keyval: Dict[str, str], unrecognized_fields: Optional[Mapping[str, Any]] = None, ) -> None: - if not keyval.get("public"): + formats.KEYTYPE_SCHEMA.check_match(keytype) + formats.KEYID_SCHEMA.check_match(keyid) + if keytype == "rsa": + formats.RSA_SCHEME_SCHEMA.check_match(scheme) + elif keytype in ["ecdsa", "ecdsa-sha2-nistp256", "ecdsa-sha2-nistp384"]: + formats.ECDSA_SCHEME_SCHEMA.check_match(scheme) + elif keytype == "ed25519": + formats.ED25519_SIG_SCHEMA.check_match(scheme) + + if not (keyval.get("public") and isinstance(keyval.get("public"), str)): raise ValueError("keyval doesn't follow the specification format!") self.keyid = keyid self.keytype = keytype