Documentation
¶
Overview ¶
External anchoring of signed checkpoints to the Rekor transparency log.
Rekor (https://docs.sigstore.dev/logging/overview/) is Sigstore's public, append-only transparency log. Anchoring a checkpoint publishes a hashedrekord entry: the SHA-256 of the checkpoint payload, the Ed25519 signature over it, and the public key. Once accepted, the entry is publicly fetchable and cannot be removed, so a third party can confirm the chain head existed at the integrated time without trusting the operator of this gateway.
Rekor does not yet verify ML-DSA signatures, which is why checkpoints are dual-signed: ML-DSA-65 travels in the local evidence bundle, Ed25519 goes to the log.
Package trust provides cryptographic audit chains, compliance evaluation, and evidence export for the AIR Blackbox Gateway trust layer.
Signed chain checkpoints.
A checkpoint is a canonical snapshot of the audit chain head: the chain length, the hash of the most recent entry, and the time it was cut. Checkpoints are signed with ML-DSA-65 (post-quantum) and Ed25519, so they can be verified locally far into the future and anchored to external transparency logs today.
Threat model: the HMAC chain proves internal consistency, but the operator holds the HMAC secret and could rewrite history. A signed checkpoint that has been anchored externally (see anchor.go) proves the chain head existed at a point in time, in a log the operator does not control.
ML-DSA-65 (FIPS 204) post-quantum digital signature support.
ML-DSA-65 (formerly Dilithium3) is a lattice-based signature scheme standardized by NIST as FIPS 204. It provides 128-bit post-quantum security, meaning signatures remain secure even against future quantum computers.
This module provides:
- Key generation (keys never leave the machine)
- Signing of audit chain entries and evidence bundles
- Verification of ML-DSA-65 signatures
- Fallback to Ed25519 when circl is not available
The signing key is generated locally and stored in the configured key directory. It never leaves the machine or touches the network.
Package trust — PDF evidence export. Wraps GenerateEvidencePackage() output in a professional compliance report PDF suitable for regulatory handoff.
Requires: github.com/jung-kurt/gofpdf/v2
Index ¶
- Constants
- func ExportPDF(pkg *EvidencePackage, path string, opts PDFOptions) error
- func FetchRekorEntry(server, uuid string) ([]byte, error)
- func Verify(sd SignedData, data []byte) (bool, error)
- func VerifyAttestation(pkg *EvidencePackage, secret string) bool
- func VerifySignedCheckpoint(sc SignedCheckpoint) error
- type AuditChain
- type ChainEntry
- type Checkpoint
- type ComplianceConfig
- type ComplianceReport
- type Control
- type ControlStatus
- type EvidencePackage
- type PDFOptions
- type RekorAnchor
- type SignatureAlgorithm
- type SignedCheckpoint
- type SignedData
- type Signer
- type Summary
- type TimeRange
Constants ¶
const DefaultRekorServer = "https://rekor.sigstore.dev"
DefaultRekorServer is Sigstore's public Rekor instance.
Variables ¶
This section is empty.
Functions ¶
func ExportPDF ¶ added in v1.8.0
func ExportPDF(pkg *EvidencePackage, path string, opts PDFOptions) error
ExportPDF renders an EvidencePackage into a compliance report PDF and writes it to the given path. Returns an error if rendering or file write fails.
func FetchRekorEntry ¶ added in v1.13.2
FetchRekorEntry retrieves a previously anchored entry by UUID, so anyone can confirm the anchor exists in the public log.
func Verify ¶ added in v1.8.0
func Verify(sd SignedData, data []byte) (bool, error)
Verify checks a signature against the provided public key and data.
func VerifyAttestation ¶
func VerifyAttestation(pkg *EvidencePackage, secret string) bool
VerifyAttestation checks that an evidence package's attestation signature matches its contents. Returns true if the package hasn't been tampered with.
func VerifySignedCheckpoint ¶ added in v1.13.2
func VerifySignedCheckpoint(sc SignedCheckpoint) error
VerifySignedCheckpoint verifies every signature in the checkpoint against its payload bytes. It returns an error describing the first failure, or nil if all signatures are valid.
Types ¶
type AuditChain ¶
type AuditChain struct {
// contains filtered or unexported fields
}
AuditChain maintains an ordered, signed sequence of AIR record hashes. It is safe for concurrent use.
func NewAuditChain ¶
func NewAuditChain(secret string) *AuditChain
NewAuditChain creates a new audit chain with the given HMAC signing key.
func (*AuditChain) Append ¶
func (ac *AuditChain) Append(runID string, recordJSON []byte) ChainEntry
Append adds a new AIR record to the chain. It computes the SHA-256 hash of the record JSON, signs it with the previous entry's hash, and returns the new chain entry.
func (*AuditChain) Entries ¶
func (ac *AuditChain) Entries() []ChainEntry
Entries returns a copy of all chain entries.
func (*AuditChain) Head ¶ added in v1.13.2
func (ac *AuditChain) Head() (int64, string)
Head returns the current chain length and head hash. The head hash is empty when the chain has no entries.
func (*AuditChain) Len ¶
func (ac *AuditChain) Len() int64
Len returns the number of entries in the chain.
func (*AuditChain) Verify ¶
func (ac *AuditChain) Verify() (valid bool, brokenAt int64, err error)
Verify walks the chain and checks that every entry's signature is valid and every prev_hash matches the actual hash of the previous entry. Returns (true, 0, nil) if valid, or (false, brokenAt, err) if tampered.
type ChainEntry ¶
type ChainEntry struct {
Sequence int64 `json:"sequence"` // monotonic counter (1-based)
RunID string `json:"run_id"` // the AIR record this signs
RecordHash string `json:"record_hash"` // sha256 of the AIR record JSON
PrevHash string `json:"prev_hash"` // hash of the previous ChainEntry (empty for first)
Signature string `json:"signature"` // HMAC-SHA256(sequence|run_id|record_hash|prev_hash, secret)
Timestamp time.Time `json:"timestamp"`
}
ChainEntry is one signed link in the audit chain. Each entry includes the hash of the previous entry, forming a tamper-proof chain similar to a blockchain — modifying any record breaks the chain.
type Checkpoint ¶ added in v1.13.2
type Checkpoint struct {
ChainLength int64 `json:"chain_length"`
HeadHash string `json:"head_hash"` // sha256 of the latest ChainEntry JSON
Timestamp string `json:"timestamp"` // RFC3339 UTC, when the checkpoint was cut
}
Checkpoint is the canonical payload that gets signed and anchored.
func (Checkpoint) PayloadBytes ¶ added in v1.13.2
func (c Checkpoint) PayloadBytes() []byte
PayloadBytes returns the canonical bytes that signatures cover. json.Marshal on a struct emits fields in declaration order, so this is deterministic for a given Checkpoint value.
type ComplianceConfig ¶
type ComplianceConfig struct {
Frameworks []string `yaml:"frameworks" json:"frameworks"`
}
ComplianceConfig holds which frameworks to evaluate.
type ComplianceReport ¶
type ComplianceReport struct {
GeneratedAt time.Time `json:"generated_at"`
GatewayVersion string `json:"gateway_version"`
Frameworks []string `json:"frameworks"`
Controls []Control `json:"controls"`
Summary Summary `json:"summary"`
}
ComplianceReport is the result of evaluating the gateway against one or more compliance frameworks.
func EvaluateCompliance ¶
func EvaluateCompliance(cfg ComplianceConfig, chainLen int64, hasVault bool, hasGuardrails bool, hasAnalytics bool) *ComplianceReport
EvaluateCompliance maps gateway capabilities to SOC 2 and ISO 27001 controls and evaluates which ones pass based on the current configuration.
type Control ¶
type Control struct {
ID string `json:"id"` // e.g. "CC6.1" or "A.12.4.1"
Framework string `json:"framework"` // "SOC2" or "ISO27001"
Name string `json:"name"` // human-readable control name
Description string `json:"description"` // what the control requires
Status ControlStatus `json:"status"` // pass, fail, or partial
Evidence string `json:"evidence"` // how the gateway satisfies this
GatewayFeature string `json:"gateway_feature"` // which layer provides it
}
Control is a single compliance control mapped to a gateway capability.
type ControlStatus ¶
type ControlStatus string
ControlStatus represents whether a compliance control is satisfied.
const ( ControlPass ControlStatus = "pass" ControlFail ControlStatus = "fail" ControlPartial ControlStatus = "partial" )
type EvidencePackage ¶
type EvidencePackage struct {
ExportedAt time.Time `json:"exported_at"`
GatewayID string `json:"gateway_id"`
ChainLength int64 `json:"chain_length"`
ChainValid bool `json:"chain_valid"`
ChainBrokenAt int64 `json:"chain_broken_at,omitempty"`
AuditEntries []ChainEntry `json:"audit_entries"`
ComplianceReport *ComplianceReport `json:"compliance_report"`
RecordCount int64 `json:"record_count"`
TimeRange TimeRange `json:"time_range"`
Attestation string `json:"attestation"` // HMAC of package contents
}
EvidencePackage bundles the audit chain, compliance report, and verification results into a single exportable JSON document for regulators and auditors.
func GenerateEvidencePackage ¶
func GenerateEvidencePackage(chain *AuditChain, compliance *ComplianceReport, gatewayID string, secret string) *EvidencePackage
GenerateEvidencePackage creates a signed evidence package from the current audit chain and compliance report. The package itself is signed with HMAC-SHA256 so regulators can verify the export hasn't been tampered with.
type PDFOptions ¶ added in v1.8.0
type PDFOptions struct {
Title string // report title (default: "AIR Blackbox — Compliance Evidence Report")
Subtitle string // subtitle line (default: "Generated by AIR Blackbox Gateway")
CompanyName string // organization name shown on cover
LogoPath string // optional path to logo image (PNG/JPG)
}
PDFOptions configures the PDF report layout.
type RekorAnchor ¶ added in v1.13.2
type RekorAnchor struct {
Server string `json:"server"`
UUID string `json:"uuid"`
LogIndex int64 `json:"log_index"`
IntegratedTime int64 `json:"integrated_time"` // unix seconds, per the log
AnchoredAt string `json:"anchored_at"` // RFC3339, local clock
AlreadyExisted bool `json:"already_existed"`
}
RekorAnchor is the receipt returned after a checkpoint is accepted by (or already present in) the transparency log.
func AnchorToRekor ¶ added in v1.13.2
func AnchorToRekor(server string, sc SignedCheckpoint) (RekorAnchor, error)
AnchorToRekor publishes the Ed25519 signature from a signed checkpoint to the given Rekor server. The checkpoint must contain an Ed25519 signature; it errors otherwise with an explanation.
type SignatureAlgorithm ¶ added in v1.8.0
type SignatureAlgorithm string
SignatureAlgorithm identifies which algorithm produced a signature.
const ( AlgoMLDSA65 SignatureAlgorithm = "ML-DSA-65" AlgoEd25519 SignatureAlgorithm = "Ed25519" )
type SignedCheckpoint ¶ added in v1.13.2
type SignedCheckpoint struct {
Checkpoint Checkpoint `json:"checkpoint"`
Signatures []SignedData `json:"signatures"`
Anchors []RekorAnchor `json:"anchors,omitempty"`
}
SignedCheckpoint bundles a checkpoint with one or more signatures over its payload bytes.
func CheckpointFromEntries ¶ added in v1.13.2
func CheckpointFromEntries(entries []ChainEntry, signers ...*Signer) (SignedCheckpoint, error)
CheckpointFromEntries cuts a checkpoint from exported chain entries, as returned by GET /v1/audit/export. The head hash is recomputed from the final entry, so it matches a checkpoint cut against the live chain.
func CreateCheckpoint ¶ added in v1.13.2
func CreateCheckpoint(ac *AuditChain, signers ...*Signer) (SignedCheckpoint, error)
CreateCheckpoint cuts a checkpoint at the current chain head and signs it with every provided signer. At least one signer is required and the chain must not be empty.
type SignedData ¶ added in v1.8.0
type SignedData struct {
Algorithm SignatureAlgorithm `json:"algorithm"`
Signature string `json:"signature"` // hex-encoded
PublicKey string `json:"public_key"` // hex-encoded
SignedAt string `json:"signed_at"`
}
SignedData wraps a signature with metadata for verification.
type Signer ¶ added in v1.8.0
type Signer struct {
// contains filtered or unexported fields
}
Signer provides post-quantum signing and verification.
func NewSigner ¶ added in v1.8.0
NewSigner creates a Signer with ML-DSA-65 key generation. Keys are stored in keyDir. If keys already exist, they are loaded. If circl is not available at compile time, falls back to Ed25519.
func NewSignerEd25519 ¶ added in v1.13.2
NewSignerEd25519 creates a Signer that uses Ed25519 regardless of ML-DSA availability. Rekor and most current transparency logs verify Ed25519 but not yet ML-DSA, so anchored checkpoints carry both signature types.
func (*Signer) Algorithm ¶ added in v1.8.0
func (s *Signer) Algorithm() SignatureAlgorithm
Algorithm returns which signature algorithm is active.
func (*Signer) Sign ¶ added in v1.8.0
func (s *Signer) Sign(data []byte) (SignedData, error)
Sign signs arbitrary data and returns a SignedData structure.
func (*Signer) SignChain ¶ added in v1.8.0
func (s *Signer) SignChain(chain *AuditChain) (SignedData, error)
SignChain signs the entire audit chain and returns a SignedData.
func (*Signer) SignEvidencePackage ¶ added in v1.8.0
func (s *Signer) SignEvidencePackage(pkg *EvidencePackage) (SignedData, error)
SignEvidencePackage signs an evidence package JSON.