Skip to contents

Signs a manifest's canonical digest and records everything a verifier needs alongside it: the scheme, the public key, the context string, the digest that was signed, and the manifest's seal if it came from a chain. capsule_check_attestation() checks the result against a manifest without being told anything further.

Usage

capsule_attest(manifest, key, context = NULL, prehash = "none", note = NULL)

capsule_check_attestation(attestation, manifest, key_expected = NULL)

Arguments

manifest

A manifest, as from make_manifest().

key

A signing key from fips_keygen() or pqc_keygen().

context

Optional context string, bound into the signature for the standardised schemes; see capsule_sign().

prehash

Pre-hash, as in capsule_sign().

note

Optional free text recorded in the attestation – what the signature is meant to assert, in the signer's own words. It is covered by the signature, since it is part of the digest.

attestation

An attestation from capsule_attest().

key_expected

Optional public key hex the attestation must carry. Supply it when you know which key should have signed: without it the check confirms the attestation is internally consistent, which any key's holder could arrange.

Value

capsule_attest() a list of class bricklayer_attestation; capsule_check_attestation() a list with ok and a checks data frame, one row per check.

Details

What this adds over capsule_sign(). A bare signature leaves three things implicit – which key, which scheme, and which bytes. A verifier who has to be told those out of band cannot check anything they were not already given, which makes the signature a formality. An attestation states them, so the check is capsule_check_attestation(attestation, manifest) and nothing else.

What it does NOT establish. That the public key belongs to whoever you think it does: an attestation is only as good as the channel the key arrived on. And that the manifest is true – only that it has not changed since it was signed. capsule_falsify() is for the other question.

Examples

m <- make_manifest(list(dataset = "otis", rows = 1200L),
                   environment = FALSE)
key <- fips_keygen("ML-DSA-65")
att <- capsule_attest(m, key, note = "counts as published")

# a verifier needs the attestation and the manifest, nothing else
res <- capsule_check_attestation(att, m)
res$ok
#> [1] TRUE
res$checks
#>                  check   ok
#> 1 attestation_complete TRUE
#> 2      manifest_digest TRUE
#> 3            signature TRUE
#>                                                             detail
#> 1                                                                 
#> 2 efa1b7387f225380245de0b5170999e87ad4044f3e8fd2ef6a6bfbc2bd0a9c90
#> 3                                                                 

# any change to the manifest breaks it
m2 <- m
m2$meta$rows <- 1201L
capsule_check_attestation(att, m2)$ok
#> [1] FALSE

# and so does presenting a different key
capsule_check_attestation(att, m,
  key_expected = fips_keygen("ML-DSA-65")$public)$ok
#> [1] FALSE