Skip to content

Commit d2c12f2

Browse files
author
Lukas Pühringer
authored
Merge pull request #2165 from jku/no-key
Move (most of) Key to Securesystemslib
2 parents 93b8fb6 + 8278f3f commit d2c12f2

File tree

13 files changed

+148
-284
lines changed

13 files changed

+148
-284
lines changed

docs/conf.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,6 @@
6161
# -- Autodoc configuration ---------------------------------------------------
6262
# https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html
6363

64-
autodoc_mock_imports = ["securesystemslib"]
65-
6664
# Tone down the "tuf.api.metadata." repetition
6765
add_module_names = False
6866
python_use_unqualified_type_names = True

examples/manual_repo/basic_repo.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,12 @@
2727
from typing import Any, Dict
2828

2929
from securesystemslib.keys import generate_ed25519_key
30-
from securesystemslib.signer import SSlibSigner
30+
from securesystemslib.signer import SSlibKey, SSlibSigner
3131

3232
from tuf.api.metadata import (
3333
SPECIFICATION_VERSION,
3434
DelegatedRole,
3535
Delegations,
36-
Key,
3736
Metadata,
3837
MetaFile,
3938
Root,
@@ -157,7 +156,7 @@ def _in(days: float) -> datetime:
157156
for name in ["targets", "snapshot", "timestamp", "root"]:
158157
keys[name] = generate_ed25519_key()
159158
roles["root"].signed.add_key(
160-
Key.from_securesystemslib_key(keys[name]), name
159+
SSlibKey.from_securesystemslib_key(keys[name]), name
161160
)
162161

163162
# NOTE: We only need the public part to populate root, so it is possible to use
@@ -173,7 +172,7 @@ def _in(days: float) -> datetime:
173172
# required signature threshold.
174173
another_root_key = generate_ed25519_key()
175174
roles["root"].signed.add_key(
176-
Key.from_securesystemslib_key(another_root_key), "root"
175+
SSlibKey.from_securesystemslib_key(another_root_key), "root"
177176
)
178177
roles["root"].signed.roles["root"].threshold = 2
179178

@@ -271,7 +270,7 @@ def _in(days: float) -> datetime:
271270
# https://theupdateframework.github.io/specification/latest/#delegations
272271
roles["targets"].signed.delegations = Delegations(
273272
keys={
274-
keys[delegatee_name]["keyid"]: Key.from_securesystemslib_key(
273+
keys[delegatee_name]["keyid"]: SSlibKey.from_securesystemslib_key(
275274
keys[delegatee_name]
276275
)
277276
},
@@ -345,7 +344,7 @@ def _in(days: float) -> datetime:
345344

346345
roles["root"].signed.revoke_key(keys["root"]["keyid"], "root")
347346
roles["root"].signed.add_key(
348-
Key.from_securesystemslib_key(new_root_key), "root"
347+
SSlibKey.from_securesystemslib_key(new_root_key), "root"
349348
)
350349
roles["root"].signed.version += 1
351350

examples/manual_repo/hashed_bin_delegation.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,11 @@
2323
from typing import Any, Dict, Iterator, List, Tuple
2424

2525
from securesystemslib.keys import generate_ed25519_key
26-
from securesystemslib.signer import SSlibSigner
26+
from securesystemslib.signer import SSlibKey, SSlibSigner
2727

2828
from tuf.api.metadata import (
2929
DelegatedRole,
3030
Delegations,
31-
Key,
3231
Metadata,
3332
TargetFile,
3433
Targets,
@@ -146,7 +145,7 @@ def find_hash_bin(path: str) -> str:
146145
# Create preliminary delegating targets role (bins) and add public key for
147146
# delegated targets (bin_n) to key store. Delegation details are update below.
148147
roles["bins"] = Metadata(Targets(expires=_in(365)))
149-
bin_n_key = Key.from_securesystemslib_key(keys["bin-n"])
148+
bin_n_key = SSlibKey.from_securesystemslib_key(keys["bin-n"])
150149
roles["bins"].signed.delegations = Delegations(
151150
keys={bin_n_key.keyid: bin_n_key},
152151
roles={},

examples/manual_repo/succinct_hash_bin_delegations.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
from typing import Dict, Tuple
2626

2727
from securesystemslib.keys import generate_ed25519_key
28-
from securesystemslib.signer import SSlibSigner
28+
from securesystemslib.signer import SSlibKey, SSlibSigner
2929

3030
from tuf.api.metadata import (
3131
Delegations,
@@ -82,7 +82,7 @@
8282
def create_key() -> Tuple[Key, SSlibSigner]:
8383
"""Generates a new Key and Signer."""
8484
sslib_key = generate_ed25519_key()
85-
return Key.from_securesystemslib_key(sslib_key), SSlibSigner(sslib_key)
85+
return SSlibKey.from_securesystemslib_key(sslib_key), SSlibSigner(sslib_key)
8686

8787

8888
# Create one signing key for all bins, and one for the delegating targets role.

examples/repository/_simplerepo.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,9 @@
1010
from typing import Dict, List
1111

1212
from securesystemslib import keys
13-
from securesystemslib.signer import Signer, SSlibSigner
13+
from securesystemslib.signer import Signer, SSlibKey, SSlibSigner
1414

1515
from tuf.api.metadata import (
16-
Key,
1716
Metadata,
1817
MetaFile,
1918
Root,
@@ -72,7 +71,7 @@ def __init__(self) -> None:
7271
for role in ["root", "timestamp", "snapshot", "targets"]:
7372
key = keys.generate_ed25519_key()
7473
self.signer_cache[role].append(SSlibSigner(key))
75-
root.add_key(Key.from_securesystemslib_key(key), role)
74+
root.add_key(SSlibKey.from_securesystemslib_key(key), role)
7675

7776
for role in ["timestamp", "snapshot", "targets"]:
7877
with self.edit(role):

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ classifiers = [
4444
]
4545
dependencies = [
4646
"requests>=2.19.1",
47-
"securesystemslib>=0.22.0",
47+
"securesystemslib>=0.26.0",
4848
]
4949
dynamic = ["version"]
5050

tests/generated_data/generate_md.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from datetime import datetime
99
from typing import Dict, List, Optional
1010

11-
from securesystemslib.signer import SSlibSigner
11+
from securesystemslib.signer import SSlibKey, SSlibSigner
1212

1313
from tests import utils
1414
from tuf.api.metadata import Key, Metadata, Root, Snapshot, Targets, Timestamp
@@ -36,7 +36,7 @@
3636

3737
keys: Dict[str, Key] = {}
3838
for index in range(4):
39-
keys[f"ed25519_{index}"] = Key.from_securesystemslib_key(
39+
keys[f"ed25519_{index}"] = SSlibKey.from_securesystemslib_key(
4040
{
4141
"keytype": "ed25519",
4242
"scheme": "ed25519",

tests/repository_simulator.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454

5555
import securesystemslib.hash as sslib_hash
5656
from securesystemslib.keys import generate_ed25519_key
57-
from securesystemslib.signer import SSlibSigner
57+
from securesystemslib.signer import SSlibKey, SSlibSigner
5858

5959
from tuf.api.exceptions import DownloadHTTPError
6060
from tuf.api.metadata import (
@@ -156,8 +156,8 @@ def all_targets(self) -> Iterator[Tuple[str, Targets]]:
156156

157157
@staticmethod
158158
def create_key() -> Tuple[Key, SSlibSigner]:
159-
sslib_key = generate_ed25519_key()
160-
return Key.from_securesystemslib_key(sslib_key), SSlibSigner(sslib_key)
159+
key = generate_ed25519_key()
160+
return SSlibKey.from_securesystemslib_key(key), SSlibSigner(key)
161161

162162
def add_signer(self, role: str, signer: SSlibSigner) -> None:
163163
if role not in self.signers:

tests/test_api.py

Lines changed: 46 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,14 @@
1717
from datetime import datetime, timedelta
1818
from typing import Any, ClassVar, Dict
1919

20+
from securesystemslib import exceptions as sslib_exceptions
2021
from securesystemslib import hash as sslib_hash
2122
from securesystemslib.interface import (
2223
import_ed25519_privatekey_from_file,
2324
import_ed25519_publickey_from_file,
2425
)
2526
from securesystemslib.keys import generate_ed25519_key
26-
from securesystemslib.signer import Signature, SSlibSigner
27+
from securesystemslib.signer import SSlibKey, SSlibSigner
2728

2829
from tests import utils
2930
from tuf.api import exceptions
@@ -34,6 +35,7 @@
3435
Key,
3536
Metadata,
3637
Root,
38+
Signature,
3739
Snapshot,
3840
SuccinctRoles,
3941
TargetFile,
@@ -187,8 +189,8 @@ def test_to_from_bytes(self) -> None:
187189
self.assertEqual(metadata_obj_2.to_bytes(), obj_bytes)
188190

189191
def test_sign_verify(self) -> None:
190-
root_path = os.path.join(self.repo_dir, "metadata", "root.json")
191-
root = Metadata[Root].from_file(root_path).signed
192+
path = os.path.join(self.repo_dir, "metadata")
193+
root = Metadata[Root].from_file(os.path.join(path, "root.json")).signed
192194

193195
# Locate the public keys we need from root
194196
targets_keyid = next(iter(root.roles[Targets.type].keyids))
@@ -199,41 +201,37 @@ def test_sign_verify(self) -> None:
199201
timestamp_key = root.keys[timestamp_keyid]
200202

201203
# Load sample metadata (targets) and assert ...
202-
path = os.path.join(self.repo_dir, "metadata", "targets.json")
203-
md_obj = Metadata.from_file(path)
204+
md_obj = Metadata.from_file(os.path.join(path, "targets.json"))
205+
sig = md_obj.signatures[targets_keyid]
206+
data = CanonicalJSONSerializer().serialize(md_obj.signed)
204207

205208
# ... it has a single existing signature,
206209
self.assertEqual(len(md_obj.signatures), 1)
207210
# ... which is valid for the correct key.
208-
targets_key.verify_signature(md_obj)
209-
with self.assertRaises(exceptions.UnsignedMetadataError):
210-
snapshot_key.verify_signature(md_obj)
211-
212-
# Test verifying with explicitly set serializer
213-
targets_key.verify_signature(md_obj, CanonicalJSONSerializer())
214-
with self.assertRaises(exceptions.UnsignedMetadataError):
215-
targets_key.verify_signature(md_obj, JSONSerializer()) # type: ignore[arg-type]
211+
targets_key.verify_signature(sig, data)
212+
with self.assertRaises(sslib_exceptions.VerificationError):
213+
snapshot_key.verify_signature(sig, data)
216214

217215
sslib_signer = SSlibSigner(self.keystore[Snapshot.type])
218216
# Append a new signature with the unrelated key and assert that ...
219-
sig = md_obj.sign(sslib_signer, append=True)
217+
snapshot_sig = md_obj.sign(sslib_signer, append=True)
220218
# ... there are now two signatures, and
221219
self.assertEqual(len(md_obj.signatures), 2)
222220
# ... both are valid for the corresponding keys.
223-
targets_key.verify_signature(md_obj)
224-
snapshot_key.verify_signature(md_obj)
221+
targets_key.verify_signature(sig, data)
222+
snapshot_key.verify_signature(snapshot_sig, data)
225223
# ... the returned (appended) signature is for snapshot key
226-
self.assertEqual(sig.keyid, snapshot_keyid)
224+
self.assertEqual(snapshot_sig.keyid, snapshot_keyid)
227225

228226
sslib_signer = SSlibSigner(self.keystore[Timestamp.type])
229227
# Create and assign (don't append) a new signature and assert that ...
230-
md_obj.sign(sslib_signer, append=False)
228+
ts_sig = md_obj.sign(sslib_signer, append=False)
231229
# ... there now is only one signature,
232230
self.assertEqual(len(md_obj.signatures), 1)
233231
# ... valid for that key.
234-
timestamp_key.verify_signature(md_obj)
235-
with self.assertRaises(exceptions.UnsignedMetadataError):
236-
targets_key.verify_signature(md_obj)
232+
timestamp_key.verify_signature(ts_sig, data)
233+
with self.assertRaises(sslib_exceptions.VerificationError):
234+
targets_key.verify_signature(ts_sig, data)
237235

238236
def test_sign_failures(self) -> None:
239237
# Test throwing UnsignedMetadataError because of signing problems
@@ -248,7 +246,7 @@ def test_sign_failures(self) -> None:
248246
with self.assertRaises(exceptions.UnsignedMetadataError):
249247
md.sign(sslib_signer)
250248

251-
def test_verify_failures(self) -> None:
249+
def test_key_verify_failures(self) -> None:
252250
root_path = os.path.join(self.repo_dir, "metadata", "root.json")
253251
root = Metadata[Root].from_file(root_path).signed
254252

@@ -259,36 +257,36 @@ def test_verify_failures(self) -> None:
259257
# Load sample metadata (timestamp)
260258
path = os.path.join(self.repo_dir, "metadata", "timestamp.json")
261259
md_obj = Metadata.from_file(path)
260+
sig = md_obj.signatures[timestamp_keyid]
261+
data = CanonicalJSONSerializer().serialize(md_obj.signed)
262262

263263
# Test failure on unknown scheme (securesystemslib
264264
# UnsupportedAlgorithmError)
265265
scheme = timestamp_key.scheme
266266
timestamp_key.scheme = "foo"
267-
with self.assertRaises(exceptions.UnsignedMetadataError):
268-
timestamp_key.verify_signature(md_obj)
267+
with self.assertRaises(sslib_exceptions.VerificationError):
268+
timestamp_key.verify_signature(sig, data)
269269
timestamp_key.scheme = scheme
270270

271271
# Test failure on broken public key data (securesystemslib
272272
# CryptoError)
273273
public = timestamp_key.keyval["public"]
274274
timestamp_key.keyval["public"] = "ffff"
275-
with self.assertRaises(exceptions.UnsignedMetadataError):
276-
timestamp_key.verify_signature(md_obj)
275+
with self.assertRaises(sslib_exceptions.VerificationError):
276+
timestamp_key.verify_signature(sig, data)
277277
timestamp_key.keyval["public"] = public
278278

279279
# Test failure with invalid signature (securesystemslib
280280
# FormatError)
281-
sig = md_obj.signatures[timestamp_keyid]
282-
correct_sig = sig.signature
283-
sig.signature = "foo"
284-
with self.assertRaises(exceptions.UnsignedMetadataError):
285-
timestamp_key.verify_signature(md_obj)
281+
incorrect_sig = copy(sig)
282+
incorrect_sig.signature = "foo"
283+
with self.assertRaises(sslib_exceptions.VerificationError):
284+
timestamp_key.verify_signature(incorrect_sig, data)
286285

287286
# Test failure with valid but incorrect signature
288-
sig.signature = "ff" * 64
289-
with self.assertRaises(exceptions.UnsignedMetadataError):
290-
timestamp_key.verify_signature(md_obj)
291-
sig.signature = correct_sig
287+
incorrect_sig.signature = "ff" * 64
288+
with self.assertRaises(sslib_exceptions.UnverifiedSignatureError):
289+
timestamp_key.verify_signature(incorrect_sig, data)
292290

293291
def test_metadata_signed_is_expired(self) -> None:
294292
# Use of Snapshot is arbitrary, we're just testing the base class
@@ -355,6 +353,15 @@ def test_metadata_verify_delegate(self) -> None:
355353
root.verify_delegate(Snapshot.type, snapshot)
356354
snapshot.signed.expires = expires
357355

356+
# verify fails if sslib verify fails with VerificationError
357+
# (in this case signature is malformed)
358+
keyid = next(iter(root.signed.roles[Snapshot.type].keyids))
359+
good_sig = snapshot.signatures[keyid].signature
360+
snapshot.signatures[keyid].signature = "foo"
361+
with self.assertRaises(exceptions.UnsignedMetadataError):
362+
root.verify_delegate(Snapshot.type, snapshot)
363+
snapshot.signatures[keyid].signature = good_sig
364+
358365
# verify fails if roles keys do not sign the metadata
359366
with self.assertRaises(exceptions.UnsignedMetadataError):
360367
root.verify_delegate(Timestamp.type, snapshot)
@@ -382,14 +389,9 @@ def test_key_class(self) -> None:
382389
# Test if from_securesystemslib_key removes the private key from keyval
383390
# of a securesystemslib key dictionary.
384391
sslib_key = generate_ed25519_key()
385-
key = Key.from_securesystemslib_key(sslib_key)
392+
key = SSlibKey.from_securesystemslib_key(sslib_key)
386393
self.assertFalse("private" in key.keyval.keys())
387394

388-
# Test raising ValueError with non-existent keytype
389-
sslib_key["keytype"] = "bad keytype"
390-
with self.assertRaises(ValueError):
391-
Key.from_securesystemslib_key(sslib_key)
392-
393395
def test_root_add_key_and_revoke_key(self) -> None:
394396
root_path = os.path.join(self.repo_dir, "metadata", "root.json")
395397
root = Metadata[Root].from_file(root_path)
@@ -399,7 +401,7 @@ def test_root_add_key_and_revoke_key(self) -> None:
399401
os.path.join(self.keystore_dir, "root_key2.pub")
400402
)
401403
keyid = root_key2["keyid"]
402-
key_metadata = Key(
404+
key_metadata = SSlibKey(
403405
keyid,
404406
root_key2["keytype"],
405407
root_key2["scheme"],
@@ -412,7 +414,7 @@ def test_root_add_key_and_revoke_key(self) -> None:
412414

413415
# Assert that add_key with old argument order will raise an error
414416
with self.assertRaises(ValueError):
415-
root.signed.add_key(Root.type, key_metadata) # type: ignore
417+
root.signed.add_key(Root.type, key_metadata)
416418

417419
# Add new root key
418420
root.signed.add_key(key_metadata, Root.type)
@@ -513,7 +515,7 @@ def test_targets_key_api(self) -> None:
513515

514516
# Assert that add_key with old argument order will raise an error
515517
with self.assertRaises(ValueError):
516-
targets.add_key("role1", key) # type: ignore
518+
targets.add_key("role1", key)
517519

518520
# Assert that delegated role "role1" does not contain the new key
519521
self.assertNotIn(key.keyid, targets.delegations.roles["role1"].keyids)

0 commit comments

Comments
 (0)