forked from sigstore/model-transparency
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add signing and verification CLI scripts. (sigstore#240)
* <3 git Signed-off-by: Martin Sablotny <msablotny@nvidia.com> * linter Signed-off-by: Martin Sablotny <msablotny@nvidia.com> --------- Signed-off-by: Martin Sablotny <msablotny@nvidia.com>
- Loading branch information
Showing
6 changed files
with
639 additions
and
34 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
# Copyright 2024 The Sigstore Authors | ||
# Copyright (c) 2024, NVIDIA CORPORATION. All rights reserved. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
import pathlib | ||
from typing import Callable, Iterable, TypeAlias | ||
|
||
from model_signing.manifest import manifest | ||
from model_signing.serialization import serialization | ||
from model_signing.signature import verifying | ||
from model_signing.signing import signing | ||
|
||
|
||
PayloadGeneratorFunc: TypeAlias = Callable[ | ||
[manifest.Manifest], signing.SigningPayload | ||
] | ||
|
||
|
||
def sign( | ||
model_path: pathlib.Path, | ||
signer: signing.Signer, | ||
payload_generator: PayloadGeneratorFunc, | ||
serializer: serialization.Serializer, | ||
ignore_paths: Iterable[pathlib.Path] = frozenset(), | ||
) -> signing.Signature: | ||
"""Provides a wrapper function for the steps necessary to sign a model. | ||
Args: | ||
model_path: the model to be signed. | ||
signer: the signer to be used. | ||
payload_generator: funtion to generate the manifest. | ||
serializer: the serializer to be used for the model. | ||
ignore_paths: paths that should be ignored during serialization. | ||
Defaults to an empty set. | ||
Returns: | ||
The model's signature. | ||
""" | ||
manifest = serializer.serialize(model_path, ignore_paths=ignore_paths) | ||
payload = payload_generator(manifest) | ||
sig = signer.sign(payload) | ||
return sig | ||
|
||
|
||
def verify( | ||
sig: signing.Signature, | ||
verifier: signing.Verifier, | ||
model_path: pathlib.Path, | ||
serializer: serialization.Serializer, | ||
ignore_paths: Iterable[pathlib.Path] = frozenset(), | ||
): | ||
"""Provides a simple wrapper to verify models. | ||
Args: | ||
sig: the signature to be verified. | ||
verifier: the verifier to verify the signature. | ||
model_path: the path to the model to compare manifests. | ||
serializer: the serializer used to generate the local manifest. | ||
ignore_paths: paths that should be ignored during serialization. | ||
Defaults to an empty set. | ||
Raises: | ||
verifying.VerificationError: on any verification error. | ||
""" | ||
peer_manifest = verifier.verify(sig) | ||
local_manifest = serializer.serialize(model_path, ignore_paths=ignore_paths) | ||
if peer_manifest != local_manifest: | ||
raise verifying.VerificationError("the manifests do not match") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
# Copyright (c) 2024, NVIDIA CORPORATION. All rights reserved. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
"""Support for signing intoto payloads into sigstore bundles.""" | ||
|
||
import json | ||
import pathlib | ||
from typing import Self | ||
|
||
from sigstore_protobuf_specs.dev.sigstore.bundle import v1 as bundle_pb | ||
from typing_extensions import override | ||
|
||
from model_signing.manifest import manifest as manifest_module | ||
from model_signing.signature import signing as signature_signing | ||
from model_signing.signature import verifying as signature_verifying | ||
from model_signing.signing import in_toto | ||
from model_signing.signing import signing | ||
|
||
|
||
class IntotoSignature(signing.Signature): | ||
def __init__(self, bundle: bundle_pb.Bundle): | ||
self._bundle = bundle | ||
|
||
@override | ||
def write(self, path: pathlib.Path) -> None: | ||
path.write_text(self._bundle.to_json()) | ||
|
||
@classmethod | ||
@override | ||
def read(cls, path: pathlib.Path) -> Self: | ||
bundle = bundle_pb.Bundle().from_json(path.read_text()) | ||
return cls(bundle) | ||
|
||
def to_manifest(self) -> manifest_module.Manifest: | ||
payload = json.loads(self._bundle.dsse_envelope.payload) | ||
return in_toto.IntotoPayload.manifest_from_payload(payload) | ||
|
||
|
||
class IntotoSigner(signing.Signer): | ||
def __init__(self, sig_signer: signature_signing.Signer): | ||
self._sig_signer = sig_signer | ||
|
||
@override | ||
def sign(self, payload: signing.SigningPayload) -> IntotoSignature: | ||
if not isinstance(payload, in_toto.IntotoPayload): | ||
raise TypeError("only IntotoPayloads are supported") | ||
bundle = self._sig_signer.sign(payload.statement) | ||
return IntotoSignature(bundle) | ||
|
||
|
||
class IntotoVerifier(signing.Verifier): | ||
def __init__(self, sig_verifier: signature_verifying.Verifier): | ||
self._sig_verifier = sig_verifier | ||
|
||
@override | ||
def verify(self, signature: signing.Signature) -> manifest_module.Manifest: | ||
if not isinstance(signature, IntotoSignature): | ||
raise TypeError("only IntotoSignature is supported") | ||
self._sig_verifier.verify(signature._bundle) | ||
return signature.to_manifest() |
Oops, something went wrong.