sign

package
v0.2.16 Latest Latest
Warning

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

Go to latest
Published: Jun 27, 2026 License: MPL-2.0 Imports: 13 Imported by: 0

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

View Source
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

func DigestToSigTag(digest string) string

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

func KeyIDForPub(pub ed25519.PublicKey) string

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

func ParseTrustedKey(s string) (ed25519.PublicKey, error)

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.

func (Payload) Bytes

func (p Payload) Bytes() ([]byte, error)

Bytes returns the canonical signed bytes for the payload.

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).

func (Verdict) String

func (v Verdict) String() string

String renders a one-line human summary for display.

Jump to

Keyboard shortcuts

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