Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/demo.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -1093,7 +1093,7 @@
"outputs": [],
"source": [
"hashing_config = model_signing.hashing.Config().set_ignored_paths(\n",
" paths=[\"README.md\"], ignore_git_paths=True\n",
" paths=[\"README.md\"], ignore_git_paths=True, ignore_att_paths=True\n",
")"
]
},
Expand Down
4 changes: 4 additions & 0 deletions docs/model_signing_format.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ library after passing it an In-Toto Statement. This API will sign the statement,
producing a DSSE envelope, along with a DSSE log entry that is submitted to the
transparency log.

## Excluded Files

Signature and attestation files are automatically excluded from the model signature to allow attestations (SLSA provenance, SBOMs, etc.) to accumulate independently throughout a model's lifecycle. Excluded patterns include `*.sig`, `*.sigstore.json`, and `claims.jsonl`.

## Example Format

Below is an example of the Sigstore bundle showing each of the layers described above.
Expand Down
6 changes: 3 additions & 3 deletions src/model_signing/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,14 @@
private_key="key"
).set_hashing_config(
model_signing.hashing.Config().set_ignored_paths(
paths=["README.md"], ignore_git_paths=True
paths=["README.md"], ignore_git_paths=True, ignore_att_paths=True
)
).sign("finbert", "finbert.sig")
```

This example generates a signature using a private key based on elliptic curve
cryptography. It also hashes the model by ignoring `README.md` and any git
related file present in the model directory.
cryptography. It also hashes the model by ignoring `README.md`, any git-related
files, and attestation files present in the model directory.

We also support signing with signing certificates, using a similar API as above.

Expand Down
72 changes: 64 additions & 8 deletions src/model_signing/_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,18 @@ def set_attribute(self, key, value):
help="Ignore git-related files when signing or verifying.",
)

# Decorator for the commonly used option to ignore attestation files
_ignore_att_paths_option = click.option(
"--ignore-att-paths/--no-ignore-att-paths",
type=bool,
default=True,
show_default=True,
help=(
"Ignore signature and attestation files "
"(*.sig, *.sigstore.json, claims.jsonl)."
),
)

# Decorator for the commonly used option to ignore all unsigned files
_ignore_unsigned_files_option = click.option(
"--ignore_unsigned_files/--no-ignore_unsigned_files",
Expand Down Expand Up @@ -282,6 +294,7 @@ def _sign() -> None:
@_model_path_argument
@_ignore_paths_option
@_ignore_git_paths_option
@_ignore_att_paths_option
@_allow_symlinks_option
@_write_signature_option
@_sigstore_staging_option
Expand Down Expand Up @@ -326,6 +339,7 @@ def _sign_sigstore(
model_path: pathlib.Path,
ignore_paths: Iterable[pathlib.Path],
ignore_git_paths: bool,
ignore_att_paths: bool,
allow_symlinks: bool,
signature: pathlib.Path,
use_ambient_credentials: bool,
Expand Down Expand Up @@ -388,7 +402,9 @@ def _sign_sigstore(
).set_hashing_config(
model_signing.hashing.Config()
.set_ignored_paths(
paths=ignored, ignore_git_paths=ignore_git_paths
paths=ignored,
ignore_git_paths=ignore_git_paths,
ignore_att_paths=ignore_att_paths,
)
.set_allow_symlinks(allow_symlinks)
).sign(model_path, signature)
Expand All @@ -403,6 +419,7 @@ def _sign_sigstore(
@_model_path_argument
@_ignore_paths_option
@_ignore_git_paths_option
@_ignore_att_paths_option
@_allow_symlinks_option
@_write_signature_option
@_private_key_option
Expand All @@ -416,6 +433,7 @@ def _sign_private_key(
model_path: pathlib.Path,
ignore_paths: Iterable[pathlib.Path],
ignore_git_paths: bool,
ignore_att_paths: bool,
allow_symlinks: bool,
signature: pathlib.Path,
private_key: pathlib.Path,
Expand All @@ -442,7 +460,11 @@ def _sign_private_key(
private_key=private_key, password=password
).set_hashing_config(
model_signing.hashing.Config()
.set_ignored_paths(paths=ignored, ignore_git_paths=ignore_git_paths)
.set_ignored_paths(
paths=ignored,
ignore_git_paths=ignore_git_paths,
ignore_att_paths=ignore_att_paths,
)
.set_allow_symlinks(allow_symlinks)
).sign(model_path, signature)
except Exception as err:
Expand All @@ -456,13 +478,15 @@ def _sign_private_key(
@_model_path_argument
@_ignore_paths_option
@_ignore_git_paths_option
@_ignore_att_paths_option
@_allow_symlinks_option
@_write_signature_option
@_pkcs11_uri_option
def _sign_pkcs11_key(
model_path: pathlib.Path,
ignore_paths: Iterable[pathlib.Path],
ignore_git_paths: bool,
ignore_att_paths: bool,
allow_symlinks: bool,
signature: pathlib.Path,
pkcs11_uri: str,
Expand All @@ -488,7 +512,11 @@ def _sign_pkcs11_key(
pkcs11_uri=pkcs11_uri
).set_hashing_config(
model_signing.hashing.Config()
.set_ignored_paths(paths=ignored, ignore_git_paths=ignore_git_paths)
.set_ignored_paths(
paths=ignored,
ignore_git_paths=ignore_git_paths,
ignore_att_paths=ignore_att_paths,
)
.set_allow_symlinks(allow_symlinks)
).sign(model_path, signature)
except Exception as err:
Expand All @@ -502,6 +530,7 @@ def _sign_pkcs11_key(
@_model_path_argument
@_ignore_paths_option
@_ignore_git_paths_option
@_ignore_att_paths_option
@_allow_symlinks_option
@_write_signature_option
@_private_key_option
Expand All @@ -511,6 +540,7 @@ def _sign_certificate(
model_path: pathlib.Path,
ignore_paths: Iterable[pathlib.Path],
ignore_git_paths: bool,
ignore_att_paths: bool,
allow_symlinks: bool,
signature: pathlib.Path,
private_key: pathlib.Path,
Expand Down Expand Up @@ -543,7 +573,11 @@ def _sign_certificate(
certificate_chain=certificate_chain,
).set_hashing_config(
model_signing.hashing.Config()
.set_ignored_paths(paths=ignored, ignore_git_paths=ignore_git_paths)
.set_ignored_paths(
paths=ignored,
ignore_git_paths=ignore_git_paths,
ignore_att_paths=ignore_att_paths,
)
.set_allow_symlinks(allow_symlinks)
).sign(model_path, signature)
except Exception as err:
Expand All @@ -557,6 +591,7 @@ def _sign_certificate(
@_model_path_argument
@_ignore_paths_option
@_ignore_git_paths_option
@_ignore_att_paths_option
@_allow_symlinks_option
@_write_signature_option
@_pkcs11_uri_option
Expand All @@ -566,6 +601,7 @@ def _sign_pkcs11_certificate(
model_path: pathlib.Path,
ignore_paths: Iterable[pathlib.Path],
ignore_git_paths: bool,
ignore_att_paths: bool,
allow_symlinks: bool,
signature: pathlib.Path,
pkcs11_uri: str,
Expand Down Expand Up @@ -599,7 +635,11 @@ def _sign_pkcs11_certificate(
certificate_chain=certificate_chain,
).set_hashing_config(
model_signing.hashing.Config()
.set_ignored_paths(paths=ignored, ignore_git_paths=ignore_git_paths)
.set_ignored_paths(
paths=ignored,
ignore_git_paths=ignore_git_paths,
ignore_att_paths=ignore_att_paths,
)
.set_allow_symlinks(allow_symlinks)
).sign(model_path, signature)
except Exception as err:
Expand Down Expand Up @@ -637,6 +677,7 @@ def _verify() -> None:
@_read_signature_option
@_ignore_paths_option
@_ignore_git_paths_option
@_ignore_att_paths_option
@_allow_symlinks_option
@_sigstore_staging_option
@_trust_config_option
Expand All @@ -660,6 +701,7 @@ def _verify_sigstore(
signature: pathlib.Path,
ignore_paths: Iterable[pathlib.Path],
ignore_git_paths: bool,
ignore_att_paths: bool,
allow_symlinks: bool,
identity: str,
identity_provider: str,
Expand Down Expand Up @@ -696,7 +738,9 @@ def _verify_sigstore(
).set_hashing_config(
model_signing.hashing.Config()
.set_ignored_paths(
paths=ignored, ignore_git_paths=ignore_git_paths
paths=ignored,
ignore_git_paths=ignore_git_paths,
ignore_att_paths=ignore_att_paths,
)
.set_allow_symlinks(allow_symlinks)
).set_ignore_unsigned_files(ignore_unsigned_files).verify(
Expand All @@ -714,6 +758,7 @@ def _verify_sigstore(
@_read_signature_option
@_ignore_paths_option
@_ignore_git_paths_option
@_ignore_att_paths_option
@_allow_symlinks_option
@click.option(
"--public_key",
Expand All @@ -728,6 +773,7 @@ def _verify_private_key(
signature: pathlib.Path,
ignore_paths: Iterable[pathlib.Path],
ignore_git_paths: bool,
ignore_att_paths: bool,
allow_symlinks: bool,
public_key: pathlib.Path,
ignore_unsigned_files: bool,
Expand All @@ -753,7 +799,11 @@ def _verify_private_key(
public_key=public_key
).set_hashing_config(
model_signing.hashing.Config()
.set_ignored_paths(paths=ignored, ignore_git_paths=ignore_git_paths)
.set_ignored_paths(
paths=ignored,
ignore_git_paths=ignore_git_paths,
ignore_att_paths=ignore_att_paths,
)
.set_allow_symlinks(allow_symlinks)
).set_ignore_unsigned_files(ignore_unsigned_files).verify(
model_path, signature
Expand All @@ -770,6 +820,7 @@ def _verify_private_key(
@_read_signature_option
@_ignore_paths_option
@_ignore_git_paths_option
@_ignore_att_paths_option
@_allow_symlinks_option
@_certificate_root_of_trust_option
@click.option(
Expand All @@ -786,6 +837,7 @@ def _verify_certificate(
signature: pathlib.Path,
ignore_paths: Iterable[pathlib.Path],
ignore_git_paths: bool,
ignore_att_paths: bool,
allow_symlinks: bool,
certificate_chain: Iterable[pathlib.Path],
log_fingerprints: bool,
Expand Down Expand Up @@ -816,7 +868,11 @@ def _verify_certificate(
log_fingerprints=log_fingerprints,
).set_hashing_config(
model_signing.hashing.Config()
.set_ignored_paths(paths=ignored, ignore_git_paths=ignore_git_paths)
.set_ignored_paths(
paths=ignored,
ignore_git_paths=ignore_git_paths,
ignore_att_paths=ignore_att_paths,
)
.set_allow_symlinks(allow_symlinks)
).set_ignore_unsigned_files(ignore_unsigned_files).verify(
model_path, signature
Expand Down
Loading
Loading