Documentation
¶
Overview ¶
Package bundle is the BlakBox bundle-format reference library: signing, verification, and (later) encryption for the signed, offline-verifiable artifacts that cross the air gap.
This file implements the phase-1 signature primitive: ECDSA P-384 over the DSSE Pre-Authentication Encoding (PAE), hashed with SHA-384 (decision D5). The signer/verifier satisfy go-securesystemslib/dsse's Signer/Verifier interfaces so the DSSE library owns the envelope + PAE and we own only the key math. ML-DSA-87 arrives as a second, algorithm-typed signer (D3/phase 2).
Index ¶
- Constants
- Variables
- func DecryptStream(w io.Writer, r io.Reader, cek, streamAAD []byte) error
- func EncryptStream(w io.Writer, r io.Reader, cek, streamAAD []byte) error
- func GenerateCEK() ([]byte, error)
- func KeyFingerprint(pub crypto.PublicKey) (string, error)
- func SignStatement(priv *ecdsa.PrivateKey, st *Statement) (*dsse.Envelope, error)
- func SignStatementHybrid(ecdsaPriv *ecdsa.PrivateKey, mldsaPriv *mldsa.PrivateKey, st *Statement) (*dsse.Envelope, error)
- func UnwrapCEK(recipient *ecdh.PrivateKey, stanza *WrapStanza) ([]byte, error)
- type Algorithm
- type Anchor
- type Mode
- type Policy
- type Statement
- type Subject
- type WrapStanza
Constants ¶
const ( // StatementType is the in-toto v1 Statement `_type`. StatementType = "https://in-toto.io/Statement/v1" // PayloadType is the DSSE payloadType for an in-toto Statement. PayloadType = "application/vnd.in-toto+json" // BundlePredicateType is BlakBox's bundle predicate. BundlePredicateType = "application/vnd.blakbox.bundle+json" )
const ( // SegmentSize is the plaintext size of each STREAM segment (D1): 1 MiB. SegmentSize = 1 << 20 // CEKSize is the length of a content-encryption key (AES-256). CEKSize = 32 )
Variables ¶
var ErrWrongCurve = errors.New("bundle: key is not ECDSA P-384")
ErrWrongCurve is returned when a key is not on the P-384 curve.
Functions ¶
func DecryptStream ¶
DecryptStream reverses EncryptStream, writing recovered plaintext to w. It rejects any tamper, reorder, duplication, truncation, extension, or cross-stream splice.
func EncryptStream ¶
EncryptStream reads plaintext from r and writes the AES-256-GCM STREAM to w.
func GenerateCEK ¶
GenerateCEK returns a fresh random 256-bit content-encryption key.
func KeyFingerprint ¶
KeyFingerprint returns the stable identity fingerprint of a public key — hex(SHA-256(SPKI DER)) for stdlib keys, hex(SHA-256(raw bytes)) for ML-DSA. It is the exact value the policy uses to match signatures back to pinned anchors (decision D3) and the value written to a keypair's .fingerprint sidecar, so an out-of-band fingerprint comparison and the on-box trust decision agree on one identity.
This is the exported entry point for the same computation the package uses internally; consumers (the CLI, the exporter, signed egress) MUST derive a key's identity through this function so every component agrees.
func SignStatement ¶
SignStatement marshals st and signs it into a DSSE envelope with ECDSA P-384 (phase-1 signing path, decision D5). The DSSE library handles the envelope and Pre-Authentication Encoding; we supply only the key math.
func SignStatementHybrid ¶
func SignStatementHybrid(ecdsaPriv *ecdsa.PrivateKey, mldsaPriv *mldsa.PrivateKey, st *Statement) (*dsse.Envelope, error)
SignStatementHybrid signs st with BOTH ECDSA-P384 and ML-DSA-87, producing a 2-of-2 DSSE envelope — the post-2030 hybrid-PQC path. Verify it with a Policy in Enforced2of2 mode pinned to the matching ECDSA and ML-DSA anchors.
func UnwrapCEK ¶
func UnwrapCEK(recipient *ecdh.PrivateKey, stanza *WrapStanza) ([]byte, error)
UnwrapCEK recovers the CEK from a stanza using the recipient's static ECDH P-384 private key.
Types ¶
type Algorithm ¶
type Algorithm string
Algorithm identifies a signature algorithm for algorithm-typed threshold enforcement (decision D3).
type Anchor ¶
Anchor is a pinned trust anchor: an algorithm tag plus its public key. The policy matches signatures to anchors by PUBLIC KEY, never by the envelope's advisory keyid (decision D3).
type Mode ¶
type Mode int
Mode is the threshold-enforcement mode (decision D3).
const ( // Phase1 accepts the bundle on at least one valid ECDSA-P384 signature from // a pinned anchor — the only FIPS-validated signature path today. Phase1 Mode = iota // Enforced2of2 requires one valid ECDSA-P384 AND one valid ML-DSA-87 // signature, each from a distinct pinned anchor (post-2030; hybrid PQC). Enforced2of2 )
type Policy ¶
Policy is a set of pinned anchors plus a threshold mode. It is the authoritative verification path; the package-level VerifyStatement is a Phase1 convenience wrapper over it.
func (*Policy) VerifyStatement ¶
VerifyStatement verifies env against the policy and returns the in-toto Statement. It (1) verifies signatures cryptographically, (2) maps each accepted signature back to its pinned anchor by public key, then (3) enforces the algorithm-typed threshold for the policy's Mode. A signature from a key that is not pinned never counts, and one anchor cannot satisfy the threshold twice (de-duplicated by public key).
type Statement ¶
type Statement struct {
Type string `json:"_type"`
Subject []Subject `json:"subject"`
PredicateType string `json:"predicateType"`
Predicate map[string]any `json:"predicate,omitempty"`
}
Statement is an in-toto v1 Statement.
func NewStatement ¶
NewStatement builds a Statement of the given predicate type over the subjects.
func VerifyStatement ¶
VerifyStatement is a Phase1 convenience wrapper: it verifies env against the supplied ECDSA-P384 anchor keys, accepting on at least one valid signature, and returns the decoded in-toto Statement. For the full algorithm-typed threshold (including enforced 2-of-2 with ML-DSA), construct a Policy directly and call Policy.VerifyStatement.
type Subject ¶
Subject is a signed-over resource: a name plus a digest set (algorithm -> lowercase hex). Per the design, subjects carry sha256 (+ sha384 for 2030 alignment).
type WrapStanza ¶
type WrapStanza struct {
// EphemeralPublic is the sender's ephemeral ECDH P-384 public key
// (uncompressed point, crypto/ecdh encoding).
EphemeralPublic []byte
// Wrapped is AES-256-GCM(nonce||ciphertext||tag) of the CEK.
Wrapped []byte
}
WrapStanza is one recipient's wrapped copy of the CEK.