Help us shape the future of Go! Take the 2026 Go Developer Survey

verify

package
v0.6.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 28, 2026 License: Apache-2.0 Imports: 19 Imported by: 0

Documentation

Overview

Package verify checks a DSSE attestation against a bundle and a trust roster, emitting SG-PRV findings (design §7.3, rule-verification.md §4).

Index

Constants

View Source
const (
	FormatSGMT1 = "sgmt-1"
	FormatOMS   = "oms"
)

Signature formats a Result can describe. A consumer reads Format to know which trust path produced the verdict — the two formats have different guarantees, and reporting one as the other would hide that.

Variables

View Source
var (
	ErrNotACard          = errors.New("not a surfaceguard skill card")
	ErrUnsupportedSchema = errors.New("unsupported skill-card schema version")
	ErrNoContentHash     = errors.New("card has no content_hash (emitted before v1 gained one)")
)

Errors a card document can fail with before it can be checked against anything. These are malformed *input*, not a failed verification: a file that is not a surfaceguard card cannot make a false claim about a bundle, so the caller reports them as usage errors rather than as tampering.

View Source
var ErrNoSignatureFile = errors.New("verify: bundle has no signature file")

ErrNoSignatureFile is returned by DetectFormats when a bundle carries neither signature.

Functions

func CardVerificationFailed

func CardVerificationFailed(res *CardResult) bool

CardVerificationFailed decides exit code 2 for a card check. A mismatch is a claim that has been shown false, which is the same class as SG-PRV-003.

func ParseCard

func ParseCard(data []byte) (*scan.Card, error)

ParseCard reads a card document, accepting either the emitted envelope or a bare card body. It validates only what must hold for the card to be checkable at all: it is a surfaceguard card, of a version this build understands, and it carries a content hash.

Types

type CardResult

type CardResult struct {
	// Card is the parsed card, for a caller that wants to show its claims.
	Card *scan.Card
	// CardHash is the content hash the card asserts; BundleHash is the root
	// recomputed from the bundle on disk. Match reports whether they agree —
	// the whole point of the check.
	CardHash   string
	BundleHash string
	Match      bool
	Findings   []model.Finding
}

CardResult is the outcome of checking a card against the bundle it claims to describe: does this card's subject exist, and is it this one?

func VerifyCard

func VerifyCard(b *skill.Bundle, card *scan.Card) *CardResult

VerifyCard checks a parsed card against a bundle. The comparison is the bundle's SGMT-1 Merkle root — the same value an attestation signs — so a card verifies exactly when it describes this bundle, byte for byte, and stops verifying the moment one file changes.

This is deliberately *not* a re-scan. A card's verdict and risk score are products of the policy in force when it was emitted; re-deriving them under the verifier's own policy would report a policy difference as a card defect. What a card can honestly be held to is its subject.

type Result

type Result struct {
	// Format is the signature format this result describes (FormatSGMT1 or
	// FormatOMS).
	Format         string
	Present        bool
	SignatureValid bool // at least one cryptographically valid signature
	Trusted        bool // a valid signature from a roster key
	// Revoked reports that every signature which verified did so with a key the
	// roster lists under `revoked`. It is not the negation of Trusted: a key that
	// is simply absent from the roster leaves both false, and the two states need
	// different words — "the key is revoked" is a decision the consumer made,
	// "the key is unknown" is one they have not made yet.
	Revoked bool
	// IdentityRejected reports a signature that verified with a roster key
	// whose identity no trust.identities rule admits. It is distinct from
	// Revoked — the consumer did not reject *this publisher*, they scoped which
	// identities they accept — and from an unknown key, which is no decision at
	// all.
	IdentityRejected bool
	MerkleMatch      bool
	// Certificate-bound (keyless) details, set only for a certificate or
	// sigstore OMS bundle. CertError explains why such a signature could not be
	// established — most often that no roots are configured, which is a
	// consumer decision rather than a defect.
	CertIdentity string
	CertIssuer   string
	CertError    string
	SignedAt     time.Time
	// LogInclusionVerified reports that the transparency-log inclusion proof
	// reconstructs its claimed root — the entry really is in that tree.
	// LogCheckpointVerified additionally reports that a log key the consumer
	// pinned signed the checkpoint committing to that tree, which is what makes
	// it *the* log rather than any tree at all.
	LogInclusionVerified  bool
	LogCheckpointVerified bool
	Expired               bool
	Publisher             string
	Statement             *attest.Statement
	Findings              []model.Finding
}

Result summarizes verification.

func Verify

func Verify(b *skill.Bundle, env *attest.Envelope, roster policy.Trust) *Result

Verify checks env (may be nil) against the bundle under the trust roster.

func VerifyOMS

func VerifyOMS(b *skill.Bundle, data []byte, roster policy.Trust) *Result

VerifyOMS checks an OpenSSF Model Signing bundle against the skill on disk and the trust roster, reporting the same SG-PRV states the SGMT-1 path does so a consumer does not need to know which format was used.

Two trust paths are supported. A `key` bundle is checked against the roster's public keys. A `certificate` or `sigstore` bundle is checked against the consumer's configured CA roots, and the identity bound into the certificate is then admitted (or not) by trust.identities — which is what makes keyless signing usable without anyone holding a long-lived key.

data is the raw skill.oms.sig. Pass **nil** when the file is absent; an empty but non-nil slice means the file exists and is empty, which is a malformed bundle rather than a missing one — the spec's own `invalid/empty.bundle.json` vector is exactly that case, and reporting it as "unsigned" would let a truncated signature look like a skill nobody had signed yet.

func VerifyOMSAt

func VerifyOMSAt(b *skill.Bundle, data []byte, roster policy.Trust, policyDir string) *Result

VerifyOMSAt is VerifyOMS with the directory that relative trust.roots paths are resolved against — normally the directory holding the policy file, so a policy means the same thing wherever the command is run from.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL