Documentation
¶
Overview ¶
Package sign implements txco's native ed25519 package-signature format: a small OCI artifact, discovered by the cosign tag convention (sha256:<hex> → sha256-<hex>.sig), whose single layer is the exact signed payload bytes and whose annotations carry the ed25519 signature, key id, and public key. Verification checks the signature over the STORED payload bytes and then binds the payload to the pulled manifest digest + repository, so a signature cannot be transplanted onto different content or a different name.
This is deliberately NOT cosign-compatible — it is self-contained (stdlib crypto/ed25519, no external binary, no sigstore deps). Trust roots live in the workspace txco.yaml; this package only produces and checks the artifact, never the trust policy or the registry I/O (that's the CLI + source layers).
Index ¶
Constants ¶
const ( MediaTypeSignaturePayload = "application/vnd.thanks.computer.signature.payload.v1alpha1+json" ArtifactTypeSignature = "application/vnd.thanks.computer.signature.v1alpha1" AnnotationSignature = "computer.thanks.signature" // base64(std) ed25519 signature AnnotationKeyID = "computer.thanks.signature.keyid" // SHA256:… fingerprint AnnotationPubKey = "computer.thanks.signature.pubkey" // base64(std) raw 32-byte pubkey )
OCI media types + annotation keys for the signature artifact.
Variables ¶
This section is empty.
Functions ¶
func DigestToSigTag ¶
DigestToSigTag maps a manifest digest to its signature tag, mirroring cosign's convention: sha256:<hex> → sha256-<hex>.sig. Works on any registry (no Referrers API needed). A digest without an "<algo>:" form gets a bare ".sig" suffix as a best effort.
func KeyIDForPub ¶
KeyIDForPub is the single source of truth for a public key's id: the ssh-keygen SHA256 fingerprint (matches `ssh-keygen -lf` / `ssh-add -l`).
func ParseTrustedKey ¶
ParseTrustedKey accepts a trusted ed25519 public key as any of: an authorized_keys line ("ssh-ed25519 AAAA… [comment]"), a path to a .pub file containing that line, or a bare base64(std) raw 32-byte key.
func SignArtifact ¶
func SignArtifact(ctx context.Context, dst oras.Target, digest, repository, spec, signedAt string, s Signer) (string, error)
SignArtifact builds the signature payload for (digest, repository), signs it with s, packs a single-layer OCI artifact carrying the payload + signature annotations into dst, tags it sha256-<hex>.sig, and returns that tag. dst is any oras.Target (an in-memory store in tests, a remote repo in production); the caller copies it to the registry. signedAt is supplied by the caller (RFC3339 UTC) so this stays deterministic and testable.
Types ¶
type Payload ¶
type Payload struct {
Spec string `json:"spec"` // the publish --to ref the signer used (audit only)
Repository string `json:"repository"` // host/ns/name, no tag/digest — binds identity
Digest string `json:"digest"` // sha256:… of the package manifest — binds content
KeyID string `json:"keyId"` // signer.Fingerprint(pub)
SignedAt string `json:"signedAt"` // RFC3339 UTC
}
Payload is the exact JSON that gets signed and stored as the artifact's single layer. Field declaration order IS the wire order (encoding/json marshals struct fields in declaration order), so the bytes are deterministic. Verification trusts only Repository + Digest (the transplant-resistant binding); Spec and SignedAt are audit metadata.
type Signer ¶
type Signer struct {
Priv ed25519.PrivateKey
Pub ed25519.PublicKey
KeyID string
}
Signer holds a loaded ed25519 signing key and its derived id.
func NewSigner ¶
func NewSigner(priv ed25519.PrivateKey) Signer
NewSigner derives the public key + key id from a private key.
type TrustedKey ¶
type TrustedKey struct {
Name string
Pub ed25519.PublicKey
KeyID string
Registry string // optional host scope; empty = trusted on any registry
}
TrustedKey is a public key the consumer trusts, optionally scoped to a registry host. KeyID is the ssh fingerprint used for matching.
type Verdict ¶
type Verdict struct {
Signed bool `json:"signed"`
KeyID string `json:"keyId,omitempty"`
Name string `json:"name,omitempty"` // friendly name of the matched trusted key, when known
Trusted bool `json:"trusted"`
Reason string `json:"reason,omitempty"`
SignedAt string `json:"signedAt,omitempty"`
}
Verdict is the result of checking a package's signature. A malformed, absent, or untrusted signature is a Verdict (not a Go error) — Go errors are reserved for the caller's transport layer.
func VerifyArtifact ¶
func VerifyArtifact(manifestBytes, layerBytes []byte, ann map[string]string, expectDigest, expectRepository, registryHost string, trusted []TrustedKey) Verdict
VerifyArtifact checks an already-fetched signature artifact against the pulled manifest digest + repository and the set of trusted keys. registryHost scopes registry-bound trusted keys (pass the pulled registry host; may be empty).