Documentation
¶
Overview ¶
Package envelope implements keyforge's self-describing ciphertext format: its binary and text forms, the authenticated header, and sealing and opening of the payload.
The format is frozen once data exists. Any change needs a new format version, new known-answer vectors in testdata, and a fuzz run. Unknown versions, modes, algorithms and flags fail with typed errors; the parser never guesses.
Layout ¶
Version 1, big-endian:
magic "KF" | format u8 | mode u8 | algorithm u8 | flags u8
purpose : len u8 + bytes
reference : dek_id 16 bytes (reference mode)
inline : kek_id 16 bytes, kek_version u32,
wrapped_len u16, wrapped (inline mode)
nonce : 12 bytes
ciphertext || tag
The additional authenticated data is the header bytes up to the nonce, followed by the caller's context, so changing the purpose, key, mode, algorithm or context makes decryption fail.
The text form is "kf1." followed by unpadded base64url of the binary form.
Index ¶
Constants ¶
const ( // FormatVersion is the only format version this build writes and reads. FormatVersion uint8 = 1 // NonceSize is the size of the nonce field in format 1. NonceSize = 12 // MaxPurposeLen is the longest purpose name, bounded by its u8 length. MaxPurposeLen = 255 // MaxWrappedLen is the longest wrapped data key in inline mode, bounded // by its u16 length. MaxWrappedLen = 65535 )
Variables ¶
var ( // ErrBadMagic is returned when the input does not begin with "KF". ErrBadMagic = errors.New("envelope: bad magic") // ErrTruncated is returned when the input ends before the structure it // describes. ErrTruncated = errors.New("envelope: truncated input") // ErrUnsupportedFormat is returned for a format version this build does // not implement. ErrUnsupportedFormat = errors.New("envelope: unsupported format version") // ErrUnknownMode is returned for a mode this build does not implement. ErrUnknownMode = errors.New("envelope: unknown mode") // ErrUnknownAlgorithm is returned for an algorithm identifier that is not // in the registry. ErrUnknownAlgorithm = errors.New("envelope: unknown algorithm") // ErrUnsupportedFlags is returned when any flag bit is set. All bits are // reserved in format 1 and every bit assigned later is critical. ErrUnsupportedFlags = errors.New("envelope: unsupported flags") // ErrInvalidPurpose is returned for an empty or malformed purpose name. ErrInvalidPurpose = errors.New("envelope: invalid purpose") // ErrInvalidHeader is returned when a header's fields are inconsistent // with its mode. ErrInvalidHeader = errors.New("envelope: invalid header") // ErrBadTextForm is returned when text input does not have the // "kf<version>." prefix or is not valid unpadded base64url. ErrBadTextForm = errors.New("envelope: bad text form") // ErrAuthentication is returned when the payload does not authenticate: // a wrong key, a changed header or context, or a modified ciphertext. // It deliberately carries no further detail. ErrAuthentication = errors.New("envelope: authentication failed") // ErrNotRandomNonce is returned when Seal or Open is given an AEAD that // takes an explicit nonce. The format stores a random nonce generated by // the AEAD, and nothing else is accepted. ErrNotRandomNonce = errors.New("envelope: AEAD must generate its own nonce") )
Typed errors. Callers match them with errors.Is. Errors that carry the offending value are *ValueError; use errors.As to read it.
Functions ¶
func ValidPurpose ¶
ValidPurpose reports whether p is a legal purpose name: 1 to 255 bytes of lowercase ASCII letters, digits, '.', '_' and '-', beginning with a letter or digit.
Types ¶
type Envelope ¶
Envelope is a parsed or sealed ciphertext: the header, the nonce and the ciphertext with its authentication tag.
func Parse ¶
Parse decodes the binary form. It fails with a typed error for any input it does not fully understand: it never guesses and never reads past the input.
func ParseText ¶
ParseText decodes the text form. The prefix must be exactly "kf1."; a well-formed prefix for another version fails with ErrUnsupportedFormat. Padding, line breaks and non-canonical base64url are rejected.
func Seal ¶
Seal encrypts plaintext under aead and returns the envelope for header h. The header and context are authenticated: opening needs the same header and the same context.
aead must generate its own nonce, as the AEAD returned by algorithm.New does; anything that takes an explicit nonce is refused so that a nonce can never be chosen by a caller.
func (*Envelope) MarshalBinary ¶
MarshalBinary returns the binary form of the envelope.
func (*Envelope) MarshalText ¶
MarshalText returns the text form: "kf1." followed by unpadded base64url of the binary form. It implements encoding.TextMarshaler, so an Envelope is a string in JSON.
func (*Envelope) Open ¶
Open authenticates and decrypts the envelope under aead with the same context that was given to Seal. Any failure to authenticate, whether a wrong key, a changed header or context, or a modified ciphertext, is ErrAuthentication with no further detail.
func (*Envelope) String ¶
String returns the text form, or an empty string if the envelope is not valid.
func (*Envelope) UnmarshalText ¶
UnmarshalText parses the text form. It implements encoding.TextUnmarshaler.
type Header ¶
type Header struct {
Mode Mode
Algorithm algorithm.ID
Purpose string
DEKID ID // reference mode
KEKID ID // inline mode
KEKVersion uint32 // inline mode
Wrapped []byte // inline mode
}
Header is the authenticated, self-describing part of an envelope.
Which fields are used depends on Mode. In reference mode DEKID names the data key and the inline fields must be zero. In inline mode KEKID, KEKVersion and Wrapped describe the wrapped data key and DEKID must be zero.
type ID ¶
type ID [16]byte
ID is a 16-byte key identifier.
func (ID) MarshalText ¶
MarshalText implements encoding.TextMarshaler with the hex form, so an identifier is a string in JSON rather than an array of numbers.
func (*ID) UnmarshalText ¶
UnmarshalText implements encoding.TextUnmarshaler. It accepts only the 32-character hex form.
type Mode ¶
type Mode uint8
Mode says where the wrapped data key lives.
const ( // ModeReference names the data key by identifier. The wrapped key is held // by the registry, so rotating the key-encryption key re-wraps registry // records and stored data is not touched. ModeReference Mode = 1 // ModeInline carries the wrapped data key, its key-encryption key and // version beside the ciphertext, for standalone objects. ModeInline Mode = 2 )
type ValueError ¶
ValueError is a typed error that carries the offending value, for example the format version that was not recognized.
func (*ValueError) Unwrap ¶
func (e *ValueError) Unwrap() error
Unwrap lets errors.Is match the sentinel in Kind.