Records a digest of every file named, the manifest's canonical digest,
and an attestation covering both, as a single JSON file.
capsule_bundle_verify() re-hashes
the files on disk and checks everything against it.
Usage
capsule_bundle(
dir,
manifest,
key,
files = NULL,
context = NULL,
prehash = "none",
note = NULL,
path = NULL
)
capsule_bundle_read(path)
capsule_bundle_verify(bundle, dir, manifest = NULL, key_expected = NULL)Arguments
- dir
Directory the capsule lives in.
- manifest
A manifest, as from
make_manifest().- key
A signing key from
fips_keygen()orpqc_keygen().- files
Paths relative to
dir. Defaults to every regular file indir, excluding the bundle itself.- context, prehash, note
As in
capsule_attest().- path
Where to write the bundle. Defaults to
capsule_bundle.jsoninsidedir.- bundle
A bundle read back with
capsule_bundle_read(), or the path to one.- key_expected
Optional public key hex the bundle's attestation must carry. Supply it when you know which key should have signed: without it the check confirms the bundle is internally consistent, which any key's holder could arrange.
Value
capsule_bundle() the bundle, invisibly, with the path it
was written to as an attribute; capsule_bundle_read() the bundle;
capsule_bundle_verify() a list with ok and a checks
data frame.
Details
The file digests are inside the signed payload, not alongside it. That is the whole point: a list of hashes that is not itself signed can be rewritten to match whatever the files now say, and a recipient who re-hashes the files and compares them to that list learns only that the list is consistent with itself.
What it establishes: the named files have not changed since signing, the manifest has not changed, and both were signed together by the holder of that key. What it does not: that the key belongs to anyone in particular, or that the manifest's claims are true.
Examples
dir <- tempfile()
dir.create(dir)
write.csv(data.frame(x = 1:3), file.path(dir, "data.csv"),
row.names = FALSE)
m <- make_manifest(list(dataset = "demo"), environment = FALSE)
key <- fips_keygen("ML-DSA-44")
b <- capsule_bundle(dir, m, key, note = "as published")
capsule_bundle_verify(attr(b, "path"), dir, manifest = m)$ok
#> [1] TRUE
# touch a byte of the data and the bundle no longer holds
write.csv(data.frame(x = 1:4), file.path(dir, "data.csv"),
row.names = FALSE)
capsule_bundle_verify(attr(b, "path"), dir, manifest = m)$ok
#> [1] FALSE
unlink(dir, recursive = TRUE)