mirror of
https://github.com/theupdateframework/python-tuf
synced 2026-05-24 10:08:28 +00:00
Make new API compatible with the Signing interface
In the securesystemslib pr https://github.com/secure-systems-lab/securesystemslib/pull/319 I added a new Signer interface with the purpose of supporting multiple signing implementations. Additionally, I added the SSlibSigner implementation of that interface which implements the signing operation for rsa, ed25519 and ecdsa schemes. With this commit, I integrate the SSlibSigner into the new API in tuf. Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
This commit is contained in:
parent
3b33deb26b
commit
49aa0fc167
3 changed files with 30 additions and 16 deletions
2
setup.py
2
setup.py
|
|
@ -113,7 +113,7 @@
|
||||||
python_requires="~=3.6",
|
python_requires="~=3.6",
|
||||||
install_requires = [
|
install_requires = [
|
||||||
'requests>=2.19.1',
|
'requests>=2.19.1',
|
||||||
'securesystemslib>=0.18.0',
|
'securesystemslib>=0.20.0',
|
||||||
'six>=1.11.0'
|
'six>=1.11.0'
|
||||||
],
|
],
|
||||||
packages = find_packages(exclude=['tests']),
|
packages = find_packages(exclude=['tests']),
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,10 @@
|
||||||
format_keyval_to_metadata
|
format_keyval_to_metadata
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from securesystemslib.signer import (
|
||||||
|
SSlibSigner
|
||||||
|
)
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -163,8 +167,9 @@ def test_sign_verify(self):
|
||||||
self.assertTrue(metadata_obj.verify(
|
self.assertTrue(metadata_obj.verify(
|
||||||
self.keystore['targets']['public']))
|
self.keystore['targets']['public']))
|
||||||
|
|
||||||
|
sslib_signer = SSlibSigner(self.keystore['snapshot']['private'])
|
||||||
# Append a new signature with the unrelated key and assert that ...
|
# Append a new signature with the unrelated key and assert that ...
|
||||||
metadata_obj.sign(self.keystore['snapshot']['private'], append=True)
|
metadata_obj.sign(sslib_signer, append=True)
|
||||||
# ... there are now two signatures, and
|
# ... there are now two signatures, and
|
||||||
self.assertTrue(len(metadata_obj.signatures) == 2)
|
self.assertTrue(len(metadata_obj.signatures) == 2)
|
||||||
# ... both are valid for the corresponding keys.
|
# ... both are valid for the corresponding keys.
|
||||||
|
|
@ -173,8 +178,9 @@ def test_sign_verify(self):
|
||||||
self.assertTrue(metadata_obj.verify(
|
self.assertTrue(metadata_obj.verify(
|
||||||
self.keystore['snapshot']['public']))
|
self.keystore['snapshot']['public']))
|
||||||
|
|
||||||
|
sslib_signer.key_dict = self.keystore['timestamp']['private']
|
||||||
# Create and assign (don't append) a new signature and assert that ...
|
# Create and assign (don't append) a new signature and assert that ...
|
||||||
metadata_obj.sign(self.keystore['timestamp']['private'], append=False)
|
metadata_obj.sign(sslib_signer, append=False)
|
||||||
# ... there now is only one signature,
|
# ... there now is only one signature,
|
||||||
self.assertTrue(len(metadata_obj.signatures) == 1)
|
self.assertTrue(len(metadata_obj.signatures) == 1)
|
||||||
# ... valid for that key.
|
# ... valid for that key.
|
||||||
|
|
@ -182,7 +188,7 @@ def test_sign_verify(self):
|
||||||
self.keystore['timestamp']['public']))
|
self.keystore['timestamp']['public']))
|
||||||
|
|
||||||
# Assert exception if there are more than one signatures for a key
|
# Assert exception if there are more than one signatures for a key
|
||||||
metadata_obj.sign(self.keystore['timestamp']['private'], append=True)
|
metadata_obj.sign(sslib_signer, append=True)
|
||||||
with self.assertRaises(tuf.exceptions.Error) as ctx:
|
with self.assertRaises(tuf.exceptions.Error) as ctx:
|
||||||
metadata_obj.verify(self.keystore['timestamp']['public'])
|
metadata_obj.verify(self.keystore['timestamp']['public'])
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
|
|
|
||||||
|
|
@ -20,10 +20,11 @@
|
||||||
|
|
||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
|
from securesystemslib.keys import verify_signature
|
||||||
from securesystemslib.util import persist_temp_file
|
from securesystemslib.util import persist_temp_file
|
||||||
|
from securesystemslib.signer import Signer, Signature
|
||||||
from securesystemslib.storage import (StorageBackendInterface,
|
from securesystemslib.storage import (StorageBackendInterface,
|
||||||
FilesystemBackend)
|
FilesystemBackend)
|
||||||
from securesystemslib.keys import create_signature, verify_signature
|
|
||||||
|
|
||||||
from tuf.api.serialization import (MetadataSerializer, MetadataDeserializer,
|
from tuf.api.serialization import (MetadataSerializer, MetadataDeserializer,
|
||||||
SignedSerializer)
|
SignedSerializer)
|
||||||
|
|
@ -90,12 +91,14 @@ def from_dict(cls, metadata: Mapping[str, Any]) -> 'Metadata':
|
||||||
else:
|
else:
|
||||||
raise ValueError(f'unrecognized metadata type "{_type}"')
|
raise ValueError(f'unrecognized metadata type "{_type}"')
|
||||||
|
|
||||||
# NOTE: If Signature becomes a class, we should iterate over
|
signatures = []
|
||||||
# metadata['signatures'], call Signature.from_dict for each item, and
|
for signature in metadata.pop('signatures'):
|
||||||
# pass a list of Signature objects to the Metadata constructor instead.
|
signature_obj = Signature.from_dict(signature)
|
||||||
|
signatures.append(signature_obj)
|
||||||
|
|
||||||
return cls(
|
return cls(
|
||||||
signed=inner_cls.from_dict(metadata.pop('signed')),
|
signed=inner_cls.from_dict(metadata.pop('signed')),
|
||||||
signatures=metadata.pop('signatures'))
|
signatures=signatures)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_file(
|
def from_file(
|
||||||
|
|
@ -139,8 +142,13 @@ def from_file(
|
||||||
|
|
||||||
def to_dict(self) -> Dict[str, Any]:
|
def to_dict(self) -> Dict[str, Any]:
|
||||||
"""Returns the dict representation of self. """
|
"""Returns the dict representation of self. """
|
||||||
|
|
||||||
|
signatures = []
|
||||||
|
for sig in self.signatures:
|
||||||
|
signatures.append(sig.to_dict())
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'signatures': self.signatures,
|
'signatures': signatures,
|
||||||
'signed': self.signed.to_dict()
|
'signed': self.signed.to_dict()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -178,13 +186,14 @@ def to_file(
|
||||||
|
|
||||||
# Signatures.
|
# Signatures.
|
||||||
def sign(
|
def sign(
|
||||||
self, key: Mapping[str, Any], append: bool = False,
|
self, signer: Signer, append: bool = False,
|
||||||
signed_serializer: Optional[SignedSerializer] = None
|
signed_serializer: Optional[SignedSerializer] = None
|
||||||
) -> Dict[str, Any]:
|
) -> Dict[str, Any]:
|
||||||
"""Creates signature over 'signed' and assigns it to 'signatures'.
|
"""Creates signature over 'signed' and assigns it to 'signatures'.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
key: A securesystemslib-style private key object used for signing.
|
signer: An object implementing the securesystemslib.signer.Signer
|
||||||
|
interface.
|
||||||
append: A boolean indicating if the signature should be appended to
|
append: A boolean indicating if the signature should be appended to
|
||||||
the list of signatures or replace any existing signatures. The
|
the list of signatures or replace any existing signatures. The
|
||||||
default behavior is to replace signatures.
|
default behavior is to replace signatures.
|
||||||
|
|
@ -209,8 +218,7 @@ def sign(
|
||||||
from tuf.api.serialization.json import CanonicalJSONSerializer
|
from tuf.api.serialization.json import CanonicalJSONSerializer
|
||||||
signed_serializer = CanonicalJSONSerializer()
|
signed_serializer = CanonicalJSONSerializer()
|
||||||
|
|
||||||
signature = create_signature(key,
|
signature = signer.sign(signed_serializer.serialize(self.signed))
|
||||||
signed_serializer.serialize(self.signed))
|
|
||||||
|
|
||||||
if append:
|
if append:
|
||||||
self.signatures.append(signature)
|
self.signatures.append(signature)
|
||||||
|
|
@ -244,7 +252,7 @@ def verify(self, key: Mapping[str, Any],
|
||||||
|
|
||||||
"""
|
"""
|
||||||
signatures_for_keyid = list(filter(
|
signatures_for_keyid = list(filter(
|
||||||
lambda sig: sig['keyid'] == key['keyid'], self.signatures))
|
lambda sig: sig.keyid == key['keyid'], self.signatures))
|
||||||
|
|
||||||
if not signatures_for_keyid:
|
if not signatures_for_keyid:
|
||||||
raise tuf.exceptions.Error(
|
raise tuf.exceptions.Error(
|
||||||
|
|
@ -262,7 +270,7 @@ def verify(self, key: Mapping[str, Any],
|
||||||
signed_serializer = CanonicalJSONSerializer()
|
signed_serializer = CanonicalJSONSerializer()
|
||||||
|
|
||||||
return verify_signature(
|
return verify_signature(
|
||||||
key, signatures_for_keyid[0],
|
key, signatures_for_keyid[0].to_dict(),
|
||||||
signed_serializer.serialize(self.signed))
|
signed_serializer.serialize(self.signed))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue