crypto

package
v0.26.13 Latest Latest
Warning

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

Go to latest
Published: Oct 24, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package crypto — the AEAD port implemented by each concrete algorithm.

Package crypto — the Agreement port: DH-style key agreement.

Package crypto — the process-wide Agreement registry + GenerateAgreementKey / AgreementShared dispatch.

Package crypto declares the authenticated-encryption port: the AEAD contract, the redacting Key value type, and the process-wide registry that maps an Algorithm (and its 1-byte wire id) to a registered AEAD. It is the peer of internal/core/data/codec — the registry resolves an Algorithm to an AEAD exactly as codec resolves a Format to a Codec.

No algorithm bodies and no vendor types live here; concrete AEADs live under internal/service/crypto/<algo>/ (stdlib AES-GCM today) and third-party/ x-crypto/* (XChaCha20-Poly1305 tomorrow) and self-register via a package-level var initialiser when imported — no init().

Package crypto — range 0.2.4.* (ADR 0013 core/crypto block).

Package crypto — the key-derivation port implemented by each KDF scheme.

Package crypto — the process-wide Deriver registry + Subkey dispatch.

Package crypto — declares the sentinels returned by the AEAD facade. Each var's name equals its errs.Define Reason in SCREAMING_SNAKE form. DuplicateRegistration is never returned: every registrar panics at boot with conflictText of it (see registry_generic.go and registry.go).

Package crypto — the process-wide Hasher registry + Sum / SumHex dispatch.

Package crypto — the Hasher port: fingerprint / content-addressing hashing.

Package crypto — the opaque, redacting symmetric Key value type.

Package crypto — the MAC port: keyed, detached message authentication.

Package crypto — the process-wide MAC registry + MACTag / MACVerify dispatch.

Package crypto — the password-hashing port implemented by each scheme.

Package crypto — the process-wide PasswordHasher registry + HashPassword / VerifyPassword / NeedsRehash dispatch.

Package crypto — holds the process-wide AEAD registry. Service- and third-party-level scheme packages register themselves via package-level var initialisers when imported (no init()), mirroring core/data/codec.

Package crypto — the registrar every scheme registry shares (AEAD, Hasher, Signer, MAC, Deriver, Agreement, PasswordHasher, StreamSealer). The table under each one is the kernel's (kernel/plugin.Registry, ADR 0159); what this file adds is the crypto domain's refusal — the code, the reason and the fields a conflict panics with — written once instead of once per capability.

Package crypto — the Seal / Open dispatch over the AEAD registry.

Package crypto — the digital-signature port implemented by each scheme.

Package crypto — the process-wide Signer registry + GenerateKey / Sign / Verify dispatch.

Package crypto — the StreamSealer port: chunked authenticated encryption.

Package crypto — the process-wide StreamSealer registry + SealStream / OpenStream dispatch.

Index

Constants

View Source
const CodeAgreementFailed errs.Code = 0x00_02_04_11 // 0.2.4.17

CodeAgreementFailed identifies an AgreementShared call whose scheme rejected the inputs (e.g. a low-order peer point) — wrapped, never leaking key bytes.

View Source
const CodeDecryptionFailed errs.Code = 0x00_02_04_04 // 0.2.4.4

CodeDecryptionFailed identifies any Open failure — bad authentication tag, malformed framing, unknown wire id, or wrong key. It is deliberately undifferentiated so Open cannot become a padding/format oracle.

View Source
const CodeDerivationFailed errs.Code = 0x00_02_04_0B // 0.2.4.11

CodeDerivationFailed identifies a Subkey call whose requested length exceeds the scheme's maximum output — a caller data error, not a fault.

View Source
const CodeDigestMismatch errs.Code = 0x00_02_04_14 // 0.2.4.20

CodeDigestMismatch identifies a VerifyingReader whose computed digest did not match the expected hex at EOF. The digest is public, so the mismatch is non-oracle — it surfaces only on the terminal read, never mid-stream.

View Source
const CodeDuplicateRegistration errs.Code = 0x00_02_04_01 // 0.2.4.1

CodeDuplicateRegistration identifies an init-time collision on a scheme registry; two distinct schemes tried to claim the same Algorithm or wire id. Surfaced via panic at boot through the DuplicateRegistration sentinel.

View Source
const CodeEntropyFailed errs.Code = 0x00_02_04_05 // 0.2.4.5

CodeEntropyFailed identifies a crypto/rand failure while generating a nonce in Seal — a host entropy fault, not a caller error.

View Source
const CodeInvalidKey errs.Code = 0x00_02_04_03 // 0.2.4.3

CodeInvalidKey identifies a NewKey call whose input was not exactly KeyLen bytes, or a cipher that rejected the key material.

View Source
const CodeInvalidKeyEnvelope errs.Code = 0x00_02_04_13 // 0.2.4.19

CodeInvalidKeyEnvelope identifies a structurally invalid key-envelope string passed to UnwrapKey — a corrupt $kenv$ frame, NOT a wrong-passphrase oracle.

View Source
const CodeInvalidPasswordHash errs.Code = 0x00_02_04_0E // 0.2.4.14

CodeInvalidPasswordHash identifies a stored PHC string that cannot be parsed during VerifyPassword — server-side data corruption, not a password mismatch.

View Source
const CodeKeyGenerationFailed errs.Code = 0x00_02_04_09 // 0.2.4.9

CodeKeyGenerationFailed identifies a crypto/rand failure while generating a signing keypair in GenerateKey — a host entropy fault, not a caller error.

View Source
const CodePasswordHashFailed errs.Code = 0x00_02_04_0D // 0.2.4.13

CodePasswordHashFailed identifies a crypto/rand failure while generating a password salt in HashPassword — a host entropy fault, not a caller error.

View Source
const CodeSigningFailed errs.Code = 0x00_02_04_08 // 0.2.4.8

CodeSigningFailed identifies a Sign call whose private key was not well-formed for the scheme (e.g. the wrong length) — a caller data error, not a fault.

View Source
const CodeStreamTruncated errs.Code = 0x00_02_04_12 // 0.2.4.18

CodeStreamTruncated identifies a streaming Open that hit EOF before the final-flag chunk — the stream was cut short, not legitimately ended.

View Source
const CodeUnknownAgreementAlgorithm errs.Code = 0x00_02_04_10 // 0.2.4.16

CodeUnknownAgreementAlgorithm identifies a GenerateAgreementKey/AgreementShared call naming a key-agreement Algorithm that no imported package has registered.

View Source
const CodeUnknownAlgorithm errs.Code = 0x00_02_04_02 // 0.2.4.2

CodeUnknownAlgorithm identifies a Seal/SealAs call naming an Algorithm that no imported package has registered.

View Source
const CodeUnknownHashAlgorithm errs.Code = 0x00_02_04_06 // 0.2.4.6

CodeUnknownHashAlgorithm identifies a Sum/SumHex call naming a hash Algorithm that no imported package has registered.

View Source
const CodeUnknownKDFAlgorithm errs.Code = 0x00_02_04_0A // 0.2.4.10

CodeUnknownKDFAlgorithm identifies a Subkey call naming a key-derivation Algorithm that no imported package has registered.

View Source
const CodeUnknownMACAlgorithm errs.Code = 0x00_02_04_0F // 0.2.4.15

CodeUnknownMACAlgorithm identifies a MACTag/MACVerify call naming a MAC Algorithm that no imported package has registered.

View Source
const CodeUnknownPasswordAlgorithm errs.Code = 0x00_02_04_0C // 0.2.4.12

CodeUnknownPasswordAlgorithm identifies a HashPassword/VerifyPassword call whose Algorithm (or PHC id segment) no imported package has registered.

View Source
const CodeUnknownSignatureAlgorithm errs.Code = 0x00_02_04_07 // 0.2.4.7

CodeUnknownSignatureAlgorithm identifies a Sign/Verify/GenerateKey call naming an Algorithm that no imported signature package has registered.

View Source
const KeyLen int = 32

KeyLen is the required symmetric key length in bytes (256-bit). Both shipped AEADs — AES-256-GCM and XChaCha20-Poly1305 — take a 32-byte key, so a single fixed length keeps the surface tiny and the validation total.

View Source
const Version byte = 0x01

Version is the box wire-format version, the first byte of every sealed box (Version[id][nonce][ciphertext||tag]). It is frozen post-v1.0.0; a future framing change bumps it and Open rejects an unknown version as DecryptionFailed. Concrete AEADs embed it via this constant.

Variables

View Source
var (
	// UnknownAlgorithm is returned by Seal/SealAs when no AEAD is registered
	// under the requested Algorithm — typically a missing blank-import.
	UnknownAlgorithm = errs.Static(CodeUnknownAlgorithm, "UNKNOWN_ALGORITHM",
		"No AEAD is registered under that algorithm",
		"core/crypto.Seal: algorithm absent from registry; blank-import the scheme's package to register it",
		0,
		0)

	// InvalidKey is returned by NewKey when the supplied material is not
	// exactly KeyLen bytes (or by an AEAD when the cipher rejects the key).
	InvalidKey = errs.Static(CodeInvalidKey, "INVALID_KEY",
		"Encryption key has the wrong length",
		"core/crypto.NewKey: key must be exactly KeyLen bytes",
		0,
		65)

	// DecryptionFailed is the single non-oracle error returned by Open for any
	// failure — bad tag, malformed framing, unknown wire id, or wrong key.
	DecryptionFailed = errs.Static(CodeDecryptionFailed, "DECRYPTION_FAILED",
		"Decryption failed",
		"core/crypto.Open: authentication, framing, or key check failed (cause withheld to avoid an oracle)",
		400,
		65)

	// EntropyFailed wraps a crypto/rand failure while generating a Seal nonce;
	// it signals a host entropy fault rather than a caller error.
	EntropyFailed = errs.Static(CodeEntropyFailed, "ENTROPY_FAILED",
		"Could not gather entropy for encryption",
		"core/crypto.Seal: crypto/rand.Read failed while generating a nonce",
		0,
		0)

	// UnknownHashAlgorithm is returned by Sum/SumHex when no Hasher is
	// registered under the requested Algorithm — typically a missing blank-import.
	UnknownHashAlgorithm = errs.Static(CodeUnknownHashAlgorithm, "UNKNOWN_HASH_ALGORITHM",
		"No hasher is registered under that algorithm",
		"core/crypto.Sum: hash algorithm absent from registry; blank-import the hasher's package to register it",
		0,
		0)

	// UnknownSignatureAlgorithm is returned by Sign/Verify/GenerateKey when no
	// Signer is registered under the requested Algorithm — usually a missing
	// blank-import of the scheme's package.
	UnknownSignatureAlgorithm = errs.Static(CodeUnknownSignatureAlgorithm, "UNKNOWN_SIGNATURE_ALGORITHM",
		"No signer is registered under that algorithm",
		"core/crypto.Sign: signature algorithm absent from registry; blank-import the signer's package to register it",
		0,
		0)

	// SigningFailed is returned by Sign when the supplied private key is not
	// well-formed for the scheme (e.g. the wrong length).
	SigningFailed = errs.Static(CodeSigningFailed, "SIGNING_FAILED",
		"Signing key is malformed",
		"core/crypto.Sign: private key is not valid for the scheme (wrong length or encoding)",
		0,
		65)

	// KeyGenerationFailed wraps a crypto/rand failure while generating a signing
	// keypair; it signals a host entropy fault rather than a caller error.
	KeyGenerationFailed = errs.Static(CodeKeyGenerationFailed, "KEY_GENERATION_FAILED",
		"Could not gather entropy for key generation",
		"core/crypto.GenerateKey: crypto/rand failed while generating a signing keypair",
		0,
		0)

	// UnknownKDFAlgorithm is returned by Subkey when no Deriver is registered
	// under the requested Algorithm — usually a missing blank-import.
	UnknownKDFAlgorithm = errs.Static(CodeUnknownKDFAlgorithm, "UNKNOWN_KDF_ALGORITHM",
		"No key-derivation function is registered under that algorithm",
		"core/crypto.Subkey: KDF algorithm absent from registry; blank-import the deriver's package to register it",
		0,
		0)

	// DerivationFailed is returned by Subkey when the requested length exceeds
	// the scheme's maximum output (e.g. HKDF's 255*HashLen ceiling).
	DerivationFailed = errs.Static(CodeDerivationFailed, "DERIVATION_FAILED",
		"Requested derived-key length is too large",
		"core/crypto.Subkey: requested length exceeds the scheme's maximum output",
		0,
		65)

	// UnknownPasswordAlgorithm is returned by HashPassword/VerifyPassword when no
	// PasswordHasher is registered under the requested Algorithm or PHC id —
	// usually a missing blank-import.
	UnknownPasswordAlgorithm = errs.Static(CodeUnknownPasswordAlgorithm, "UNKNOWN_PASSWORD_ALGORITHM",
		"No password hasher is registered under that algorithm",
		"core/crypto.VerifyPassword: password scheme absent from registry; blank-import the hasher's package to register it",
		0,
		0)

	// PasswordHashFailed wraps a crypto/rand failure while generating a password
	// salt; it signals a host entropy fault rather than a caller error.
	PasswordHashFailed = errs.Static(CodePasswordHashFailed, "PASSWORD_HASH_FAILED",
		"Could not gather entropy for password hashing",
		"core/crypto.HashPassword: crypto/rand failed while generating a salt",
		0,
		0)

	// InvalidPasswordHash is returned by VerifyPassword when the stored PHC
	// string cannot be parsed — server-side data corruption, never a mismatch.
	InvalidPasswordHash = errs.Static(CodeInvalidPasswordHash, "INVALID_PASSWORD_HASH",
		"Stored password hash is malformed",
		"core/crypto.VerifyPassword: stored PHC string is not well-formed for its scheme",
		0,
		0)

	// UnknownMACAlgorithm is returned by MACTag/MACVerify when no MAC is
	// registered under the requested Algorithm — typically a missing blank-import.
	UnknownMACAlgorithm = errs.Static(CodeUnknownMACAlgorithm, "UNKNOWN_MAC_ALGORITHM",
		"No MAC is registered under that algorithm",
		"core/crypto.MACTag: MAC algorithm absent from registry; blank-import the scheme's package to register it",
		0,
		0)

	// UnknownAgreementAlgorithm is returned by GenerateAgreementKey/AgreementShared
	// when no Agreement scheme is registered under the requested Algorithm.
	UnknownAgreementAlgorithm = errs.Static(CodeUnknownAgreementAlgorithm, "UNKNOWN_AGREEMENT_ALGORITHM",
		"No key-agreement scheme is registered under that algorithm",
		"core/crypto.AgreementShared: agreement algorithm absent from registry; blank-import the scheme's package to register it",
		0,
		0)

	// AgreementFailed wraps an AgreementShared fault where the scheme rejected the
	// inputs (e.g. a low-order peer point); it never leaks key bytes.
	AgreementFailed = errs.Static(CodeAgreementFailed, "AGREEMENT_FAILED",
		"Key agreement failed to derive a shared secret",
		"core/crypto.AgreementShared: the scheme rejected the inputs (cause withheld of key bytes)",
		0,
		65)

	// StreamTruncated is returned by a streaming Open reader when the stream ends
	// before its final-flag chunk — a truncated or tampered stream, not a clean EOF.
	StreamTruncated = errs.Static(CodeStreamTruncated, "STREAM_TRUNCATED",
		"The authenticated stream was truncated before its final chunk",
		"core/crypto.OpenStream: reader hit EOF before decrypting the final-flag chunk",
		0,
		65)

	// InvalidKeyEnvelope is returned by UnwrapKey when the supplied $kenv$ string
	// is structurally invalid (bad field count, magic, version, kdf/aead id, or
	// base64). It signals corruption only — a wrong passphrase surfaces the
	// non-oracle DecryptionFailed instead, so this is no key/password oracle.
	InvalidKeyEnvelope = errs.Static(CodeInvalidKeyEnvelope, "INVALID_KEY_ENVELOPE",
		"Key envelope is malformed",
		"service/crypto/key/keyenvelope.UnwrapKey: $kenv$ string is not well-formed",
		0,
		65)

	// DigestMismatch is returned by a VerifyingReader on its final (EOF) read when
	// the computed digest does not match the expected value. The digest is public,
	// so the comparison is non-oracle and surfaces only at the terminal read.
	DigestMismatch = errs.Static(CodeDigestMismatch, "DIGEST_MISMATCH",
		"Stream digest does not match the expected value",
		"service/crypto/hash/stdhash.VerifyingReader: computed digest differs from the expected hex at EOF",
		0,
		65)

	// DuplicateRegistration is the conflict every registrar refuses at boot: a
	// distinct scheme already holds the Algorithm — or, for an AEAD, the wire
	// id — a second one claims. The registrar panics with conflictText of it,
	// so the panic carries the dotted-quad header AND the key that collided.
	DuplicateRegistration = errs.Static(CodeDuplicateRegistration, "DUPLICATE_REGISTRATION",
		"A scheme is already registered under that algorithm or wire id",
		"core/crypto: a distinct scheme already holds this Algorithm, or this AEAD wire id",
		0,
		0)
)

Functions

func AgreementShared

func AgreementShared(name Algorithm, priv, peerPub []byte) (secret []byte, err error)

AgreementShared derives the raw shared secret with the Agreement scheme registered as name. The result MUST be passed through a KDF before use as a key. A name with no registered scheme returns UnknownAgreementAlgorithm; a scheme Shared fault is wrapped into AgreementFailed, leaking no key bytes.

func GenerateAgreementKey

func GenerateAgreementKey(name Algorithm) (pub, priv []byte, err error)

GenerateAgreementKey draws a fresh keypair from the Agreement scheme registered as name. A name with no registered scheme returns UnknownAgreementAlgorithm; an entropy fault from the scheme propagates unchanged so callers see the original cause.

func GenerateKey

func GenerateKey(name Algorithm) (pub, priv []byte, err error)

GenerateKey draws a fresh keypair for the Signer registered as name. A name with no registered signer returns UnknownSignatureAlgorithm (blank-import the scheme's package to register it).

func HashPassword

func HashPassword(name Algorithm, password []byte) (phc string, err error)

HashPassword returns a PHC-string hash of password using the PasswordHasher registered as name. A name with no registered hasher returns UnknownPasswordAlgorithm (blank-import the scheme's package to register it).

func MACTag

func MACTag(name Algorithm, key Key, message []byte) (tag []byte, err error)

MACTag returns the authentication tag over message under key for the MAC registered as name. It is named MACTag (not Tag) so the dispatch verb never collides with the signer/verifier surface. A name with no registered MAC returns UnknownMACAlgorithm (blank-import the scheme's package to register it).

func MACVerify

func MACVerify(name Algorithm, key Key, message, tag []byte) (ok bool, err error)

MACVerify reports whether tag authenticates message under key for the MAC registered as name, using the scheme's constant-time comparison. A name with no registered MAC returns (false, UnknownMACAlgorithm) so a miss is never mistaken for a bad-tag false.

func NeedsRehash

func NeedsRehash(phc string) bool

NeedsRehash reports whether the stored PHC hash was produced with cost parameters weaker than its scheme's current policy, so a caller can re-hash on a successful login. A malformed or unknown-scheme phc reports false.

func NewHash

func NewHash(name Algorithm) (h hash.Hash, err error)

NewHash returns a fresh streaming hash.Hash for the Hasher registered as name (for io.Copy over large inputs). A name with no registered hasher returns UnknownHashAlgorithm.

func Open

func Open(key Key, box, aad []byte) (plaintext []byte, err error)

Open decrypts a box produced by Seal, verifying aad, and returns the plaintext. The scheme is resolved from the box's 1-byte id header — the caller never names it. Any failure (short box, unknown id, bad tag, wrong key) returns the single non-oracle DecryptionFailed.

func OpenStream

func OpenStream(name Algorithm, key Key, src io.Reader, aad []byte) (opened io.Reader, err error)

OpenStream wraps src so reads are opened under key with aad by the StreamSealer registered as name. A name with no registered sealer returns the shared UnknownAlgorithm sentinel; a truncated stream surfaces later as StreamTruncated from the returned reader.

func Seal

func Seal(name Algorithm, key Key, plaintext, aad []byte) (box []byte, err error)

Seal encrypts plaintext under the AEAD registered as name, binding aad, and returns the self-framed box. A name with no registered scheme returns UnknownAlgorithm (blank-import the scheme's package to register it).

func SealStream

func SealStream(name Algorithm, key Key, dst io.Writer, aad []byte) (sealed io.WriteCloser, err error)

SealStream wraps dst so writes are sealed under key with aad by the StreamSealer registered as name. Streaming extends the AEAD domain, so a name with no registered sealer returns the shared UnknownAlgorithm sentinel; a scheme construction fault propagates unchanged.

func Sign

func Sign(name Algorithm, priv, message []byte) (sig []byte, err error)

Sign produces a detached signature over message using priv under the Signer registered as name. A name with no registered signer returns UnknownSignatureAlgorithm; a malformed priv returns SigningFailed.

func Subkey

func Subkey(name Algorithm, secret, salt []byte, info string, length int) (subkey []byte, err error)

Subkey derives a length-byte subkey from secret (with optional salt and the context label info) using the Deriver registered as name. A name with no registered deriver returns UnknownKDFAlgorithm (blank-import the scheme's package to register it); an over-long length returns DerivationFailed.

func Sum

func Sum(name Algorithm, data []byte) (digest []byte, err error)

Sum returns the digest of data under the Hasher registered as name. A name with no registered hasher returns UnknownHashAlgorithm (blank-import the scheme's package to register it).

func SumHex

func SumHex(name Algorithm, data []byte) (digest string, err error)

SumHex is Sum rendered as canonical lowercase hex — the frozen string form for content IDs and cache keys.

func Verify

func Verify(name Algorithm, pub, message, sig []byte) (ok bool, err error)

Verify reports whether sig is a valid signature for message under pub for the Signer registered as name. An unregistered name returns (false, UnknownSignatureAlgorithm); an invalid signature is (false, nil) so Verify never becomes an oracle on WHY a check failed.

func VerifyPassword

func VerifyPassword(password []byte, phc string) (ok bool, err error)

VerifyPassword reports whether password matches the stored PHC hash. The scheme is read from phc's id segment — no algorithm argument is needed. A malformed phc or unregistered scheme returns an error; a genuine mismatch is (false, nil).

Types

type AEAD

type AEAD interface {
	// Algorithm reports the canonical key under which this scheme registers.
	Algorithm() Algorithm
	// ID reports the 1-byte wire identifier embedded in the box header so Open
	// can resolve the scheme without the caller naming it.
	ID() byte
	// Seal encrypts plaintext, binding aad, and returns the self-framed box
	// (Version + id + random nonce + ciphertext||tag).
	Seal(key Key, plaintext, aad []byte) (box []byte, err error)
	// Open reverses Seal: it validates the framing, decrypts, and verifies aad,
	// returning the plaintext or the non-oracle DecryptionFailed.
	Open(key Key, box, aad []byte) (plaintext []byte, err error)
}

AEAD is an authenticated-encryption-with-associated-data scheme. Each implementation owns its complete self-describing wire framing (Version[id][nonce][ciphertext||tag]) so the registry can dispatch Open by reading the 1-byte id, and so the nonce — generated from crypto/rand inside Seal — never reaches a caller. Implementations MUST be safe for concurrent use and MUST return the shared non-oracle DecryptionFailed for every Open failure (bad tag, bad header, wrong key) so they cannot become an oracle.

IFACE-PLUGIN: the registry hands plug-in AEAD instances back to callers behind this interface; concrete scheme types stay unexported in their own packages.

func Lookup

func Lookup(name Algorithm) (a AEAD, ok bool)

Lookup returns the AEAD registered under name.

IFACE-PLUGIN: the registry stores plug-in scheme instances behind the AEAD interface — concrete types are intentionally unexported per scheme.

func Register

func Register(a AEAD) AEAD

Register inserts a into the registry under a.Algorithm() + a.ID() and returns it so callers can bind the singleton to a typed package-level variable like `var AEAD = crypto.Register(aesGCM{})`. Panics on a nil scheme or when a distinct scheme already claims the same Algorithm or wire id.

IFACE-PLUGIN: the registry hands plug-in AEAD instances back to callers so each scheme keeps its concrete type unexported; the stable contract is the AEAD interface itself.

"Nil" here means UNUSABLE, not only an untyped nil: a typed nil pointer and a plug-in whose type is not comparable both satisfy the port and neither can serve one call (see internal/kernel/plugin).

type Agreement

type Agreement interface {
	// Algorithm reports the canonical key under which this scheme registers.
	Algorithm() Algorithm
	// GenerateKey draws a fresh public/private keypair from the scheme's
	// entropy source.
	GenerateKey() (pub, priv []byte, err error)
	// Shared derives the raw shared secret from priv and peerPub. The result
	// MUST be passed through a KDF before any use as a key.
	Shared(priv, peerPub []byte) (secret []byte, err error)
}

Agreement is a key-agreement scheme (Diffie-Hellman style): it produces an ephemeral keypair and derives a shared secret from a local private key and a peer public key. The raw Shared output is low-level key material and MUST be run through a KDF (a Deriver) before use as a key — the pkg/v1 facade never hands the raw secret back to generic callers. Implementations self-register via RegisterAgreement.

IFACE-PLUGIN: the registry hands plug-in Agreement instances back behind this interface; concrete scheme types stay unexported in their own packages.

func LookupAgreement

func LookupAgreement(name Algorithm) (a Agreement, ok bool)

LookupAgreement returns the Agreement scheme registered under name.

IFACE-PLUGIN: the registry stores plug-in Agreement instances behind the Agreement interface — concrete types are intentionally unexported per scheme.

func RegisterAgreement

func RegisterAgreement(a Agreement) Agreement

RegisterAgreement inserts a under a.Algorithm() and returns it so callers can bind the singleton to a typed package-level variable. Panics on a nil scheme or when a distinct scheme already claims the same Algorithm.

IFACE-PLUGIN: the registry hands plug-in Agreement instances back to callers so each scheme keeps its concrete type unexported; the contract is the Agreement interface itself.

"Nil" here means UNUSABLE, not only an untyped nil: a typed nil pointer and a plug-in whose type is not comparable both satisfy the port and neither can serve one call (see internal/kernel/plugin).

type Algorithm

type Algorithm string

Algorithm is the typed key under which an AEAD registers (e.g. "aes-256-gcm"). The zero value Algorithm("") is reserved invalid, mirroring codec.Format.

func Available

func Available() []Algorithm

Available returns the sorted list of registered Algorithms, or nil before any Register.

func AvailableAgreements

func AvailableAgreements() []Algorithm

AvailableAgreements returns the sorted list of registered agreement Algorithms.

func AvailableDerivers

func AvailableDerivers() []Algorithm

AvailableDerivers returns the sorted list of registered KDF Algorithms.

func AvailableHashers

func AvailableHashers() []Algorithm

AvailableHashers returns the sorted list of registered hash Algorithms.

func AvailableMACs

func AvailableMACs() []Algorithm

AvailableMACs returns the sorted list of registered MAC Algorithms.

func AvailablePasswordHashers

func AvailablePasswordHashers() []Algorithm

AvailablePasswordHashers returns the sorted list of registered password Algorithms.

func AvailableSigners

func AvailableSigners() []Algorithm

AvailableSigners returns the sorted list of registered signature Algorithms.

func AvailableStreamSealers

func AvailableStreamSealers() []Algorithm

AvailableStreamSealers returns the sorted list of registered streaming-AEAD Algorithms.

func (Algorithm) Known

func (a Algorithm) Known() bool

Known reports whether a has been registered in the AEAD registry.

func (Algorithm) String

func (a Algorithm) String() string

String implements fmt.Stringer and returns the raw identifier.

type Deriver

type Deriver interface {
	// Algorithm reports the canonical key under which this scheme registers.
	Algorithm() Algorithm
	// Derive expands secret (with optional salt and the context label info) into
	// a length-byte subkey, or DerivationFailed when length exceeds the scheme's
	// maximum output.
	Derive(secret, salt []byte, info string, length int) (subkey []byte, err error)
}

Deriver is a key-derivation function for KEY SEPARATION: it expands one high-entropy secret into independent, purpose-bound subkeys. It is NOT a password hash — the input must already be a strong key (an AEAD Key, an HKDF PRK, a Diffie-Hellman shared secret), never a human password. Password stretching (argon2id) is a separate, deliberately slow port.

salt is optional domain randomness (nil is allowed); info is a context label that binds each subkey to its purpose ("aead-key", "mac-key", …) so two derivations from the same secret never collide. Implementations MUST be safe for concurrent use.

IFACE-PLUGIN: the registry hands plug-in Deriver instances back to callers behind this interface; concrete scheme types stay unexported in their own packages.

func LookupDeriver

func LookupDeriver(name Algorithm) (d Deriver, ok bool)

LookupDeriver returns the Deriver registered under name.

IFACE-PLUGIN: the registry stores plug-in Deriver instances behind the Deriver interface — concrete types are intentionally unexported per scheme.

func RegisterDeriver

func RegisterDeriver(d Deriver) Deriver

RegisterDeriver inserts d under d.Algorithm() and returns it so callers can bind the singleton to a typed package-level variable like `var Deriver = crypto.RegisterDeriver(hkdfSHA256{})`. Panics on a nil deriver or when a distinct deriver already claims the same Algorithm.

IFACE-PLUGIN: the registry hands plug-in Deriver instances back to callers so each scheme keeps its concrete type unexported; the stable contract is the Deriver interface itself.

"Nil" here means UNUSABLE, not only an untyped nil: a typed nil pointer and a plug-in whose type is not comparable both satisfy the port and neither can serve one call (see internal/kernel/plugin).

type Hasher

type Hasher interface {
	// Algorithm reports the canonical key under which this hasher registers.
	Algorithm() Algorithm
	// New returns a fresh hash.Hash for streaming (io.Copy) or one-shot use.
	New() hash.Hash
}

Hasher is a fingerprint / content-addressing hash scheme producing a non-keyed digest of arbitrary bytes (content IDs, cache keys, dedup keys).

It is explicitly NOT authentication: no Hasher is a MAC, none takes a key, and a digest is public — never branch on a secret-dependent comparison of one. Keyed/authenticated integrity belongs to the AEAD and (future) signature ports. Implementations self-register via RegisterHasher.

IFACE-PLUGIN: the registry hands plug-in Hasher instances back behind this interface; concrete scheme types stay unexported in their own packages.

func LookupHasher

func LookupHasher(name Algorithm) (h Hasher, ok bool)

LookupHasher returns the Hasher registered under name.

IFACE-PLUGIN: the registry stores plug-in Hasher instances behind the Hasher interface — concrete types are intentionally unexported per scheme.

func RegisterHasher

func RegisterHasher(h Hasher) Hasher

RegisterHasher inserts h under h.Algorithm() and returns it so callers can bind the singleton to a typed package-level variable like `var Hasher = crypto.RegisterHasher(sha256Hasher{})`. Panics on a nil hasher or when a distinct hasher already claims the same Algorithm.

IFACE-PLUGIN: the registry hands plug-in Hasher instances back to callers so each scheme keeps its concrete type unexported; the stable contract is the Hasher interface itself.

"Nil" here means UNUSABLE, not only an untyped nil: a typed nil pointer and a plug-in whose type is not comparable both satisfy the port and neither can serve one call (see internal/kernel/plugin).

type Key

type Key struct {
	// contains filtered or unexported fields
}

Key is an opaque, redacting 256-bit symmetric key. Every rendering — String, GoString and Format, so %v, %s, %#v, %d and every other verb — writes "<redacted>", so an accidental print never leaks the secret; Bytes hands a fresh copy to the cipher and is the only way out. All copies of a Key share one backing array, so Zeroize on any copy clears the secret everywhere — call it when you are done with the key.

The bytes sit behind a pointer rather than in the struct: fmt cannot call Format on a Key held in an UNEXPORTED field of another struct, so it prints that field's own fields instead, and a pointer prints an address where a slice would print the key as a list of byte values. A zero-size field of a non-comparable type keeps == from compiling, so no pointer comparison can pass for a key comparison.

func NewKey

func NewKey(raw []byte) (key Key, err error)

NewKey builds a Key from raw, which MUST be exactly KeyLen (32) bytes. A wrong length returns InvalidKey rather than silently truncating or padding; the bytes are copied so a later mutation of raw cannot affect the Key.

func (Key) Bytes

func (k Key) Bytes() []byte

Bytes returns a fresh copy of the raw key material for handoff to a cipher. Callers MUST NOT log the result; the redaction only covers the renderings. A zero-value Key returns nil.

func (Key) Format added in v0.13.0

func (k Key) Format(state fmt.State, verb rune)

Format implements fmt.Formatter, so EVERY verb writes "<redacted>" — %d included, which bypasses String and would otherwise print the struct's bytes. %q writes it quoted.

func (Key) GoString

func (k Key) GoString() string

GoString implements fmt.GoStringer so %#v stays redacted too — fmt bypasses String for Go-syntax formatting and would otherwise dump the raw slice.

func (Key) String

func (k Key) String() string

String implements fmt.Stringer and always redacts so the key never reaches a log line through %v / %s.

func (Key) Zeroize

func (k Key) Zeroize()

Zeroize overwrites the key material with zeros. Because copies share one backing array, this clears the secret for every copy of the Key.

type MAC

type MAC interface {
	// Algorithm reports the canonical key under which this MAC registers.
	Algorithm() Algorithm
	// Tag returns the authentication tag over message under key.
	Tag(key Key, message []byte) []byte
	// Verify reports whether tag authenticates message under key, using a
	// constant-time comparison so it never becomes a timing oracle.
	Verify(key Key, message, tag []byte) bool
	// New returns a fresh streaming hash.Hash keyed by key, paralleling
	// Hasher.New, for incremental tagging over large inputs.
	New(key Key) hash.Hash
}

MAC is a detached message-authentication-code scheme: it binds a secret Key to a message and yields an authentication tag. Unlike a Hasher digest, a MAC tag IS secret-comparison-sensitive — callers MUST route equality through Verify (constant-time), never `==` or bytes.Equal, which is the exact inverse of the Hasher rule. Implementations self-register via RegisterMAC.

IFACE-PLUGIN: the registry hands plug-in MAC instances back behind this interface; concrete scheme types stay unexported in their own packages.

func LookupMAC

func LookupMAC(name Algorithm) (m MAC, ok bool)

LookupMAC returns the MAC registered under name.

IFACE-PLUGIN: the registry stores plug-in MAC instances behind the MAC interface — concrete types are intentionally unexported per scheme.

func RegisterMAC

func RegisterMAC(m MAC) MAC

RegisterMAC inserts m under m.Algorithm() and returns it so callers can bind the singleton to a typed package-level variable. Panics on a nil MAC or when a distinct MAC already claims the same Algorithm.

IFACE-PLUGIN: the registry hands plug-in MAC instances back to callers so each scheme keeps its concrete type unexported; the contract is the MAC interface.

"Nil" here means UNUSABLE, not only an untyped nil: a typed nil pointer and a plug-in whose type is not comparable both satisfy the port and neither can serve one call (see internal/kernel/plugin).

type PasswordHasher

type PasswordHasher interface {
	// Algorithm reports the canonical key under which this scheme registers; it
	// is also the PHC id segment (the first `$`-delimited field).
	Algorithm() Algorithm
	// Hash returns a PHC-string hash of password with a fresh random salt and
	// the scheme's current cost parameters, or PasswordHashFailed on an entropy
	// fault.
	Hash(password []byte) (phc string, err error)
	// Verify reports whether password matches the stored PHC hash, comparing in
	// constant time. A malformed phc returns InvalidPasswordHash; a genuine
	// mismatch is (false, nil) so Verify is not an oracle on WHY it failed.
	Verify(password []byte, phc string) (ok bool, err error)
	// NeedsRehash reports whether phc was produced with cost parameters weaker
	// than this scheme's current policy, so callers can transparently re-hash on
	// a successful login. A malformed phc reports false (Verify surfaces the error).
	NeedsRehash(phc string) (stale bool)
}

PasswordHasher stretches a human password into a slow, salted, self-describing PHC-string hash for storage. UNLIKE the Deriver (key separation) and Hasher (fingerprints) ports, this one is DELIBERATELY SLOW and salted: it is the only crypto surface meant to consume a low-entropy human secret.

The returned hash is a PHC string (`$id$params$salt$digest`) that embeds the scheme id and its cost parameters, so Verify needs no side-channel: the stored string fully describes how to check it. Implementations MUST compare digests in constant time and MUST be safe for concurrent use.

IFACE-PLUGIN: the registry hands plug-in PasswordHasher instances back to callers behind this interface; concrete scheme types stay unexported.

func LookupPasswordHasher

func LookupPasswordHasher(name Algorithm) (p PasswordHasher, ok bool)

LookupPasswordHasher returns the PasswordHasher registered under name.

IFACE-PLUGIN: the registry stores plug-in PasswordHasher instances behind the PasswordHasher interface — concrete types are intentionally unexported per scheme.

func RegisterPasswordHasher

func RegisterPasswordHasher(p PasswordHasher) PasswordHasher

RegisterPasswordHasher inserts p under p.Algorithm() and returns it so callers can bind the singleton to a typed package-level variable. Panics on a nil hasher or when a distinct hasher already claims the same Algorithm.

IFACE-PLUGIN: the registry hands plug-in PasswordHasher instances back to callers so each scheme keeps its concrete type unexported; the contract is the PasswordHasher interface itself.

"Nil" here means UNUSABLE, not only an untyped nil: a typed nil pointer and a plug-in whose type is not comparable both satisfy the port and neither can serve one call (see internal/kernel/plugin).

type Signer

type Signer interface {
	// Algorithm reports the canonical key under which this scheme registers.
	Algorithm() Algorithm
	// GenerateKey draws a fresh keypair from crypto/rand, returning the public
	// and private key bytes (or KeyGenerationFailed on a host entropy fault).
	GenerateKey() (pub, priv []byte, err error)
	// Sign produces a detached signature over message using priv, or
	// SigningFailed when priv is not a well-formed private key for this scheme.
	Sign(priv, message []byte) (sig []byte, err error)
	// Verify reports whether sig is a valid signature for message under pub. A
	// malformed key or signature is reported as false, never as a panic.
	Verify(pub, message, sig []byte) (ok bool)
}

Signer is a detached digital-signature scheme over a public/private keypair. Keys and signatures are scheme-specific byte slices (their lengths are fixed per scheme); the registry dispatches on the Algorithm name. Implementations MUST be safe for concurrent use, MUST NOT panic on a malformed key (return SigningFailed instead), and Verify MUST run in constant time with respect to the signature so it cannot become a timing oracle.

Unlike the AEAD port, a signature scheme has no hidden nonce and no wire framing: the caller holds the keypair and chooses what bytes to sign. The private key is secret material — treat it like Key.Bytes(): never log it.

IFACE-PLUGIN: the registry hands plug-in Signer instances back to callers behind this interface; concrete scheme types stay unexported in their own packages.

func LookupSigner

func LookupSigner(name Algorithm) (s Signer, ok bool)

LookupSigner returns the Signer registered under name.

IFACE-PLUGIN: the registry stores plug-in Signer instances behind the Signer interface — concrete types are intentionally unexported per scheme.

func RegisterSigner

func RegisterSigner(s Signer) Signer

RegisterSigner inserts s under s.Algorithm() and returns it so callers can bind the singleton to a typed package-level variable. Panics on a nil signer or when a distinct signer already claims the same Algorithm.

IFACE-PLUGIN: the registry hands plug-in Signer instances back to callers so each scheme keeps its concrete type unexported; the contract is the Signer interface itself.

"Nil" here means UNUSABLE, not only an untyped nil: a typed nil pointer and a plug-in whose type is not comparable both satisfy the port and neither can serve one call (see internal/kernel/plugin).

type StreamSealer

type StreamSealer interface {
	// Algorithm reports the canonical key under which this scheme registers.
	Algorithm() Algorithm
	// Writer wraps dst so writes are sealed under key with aad; Close writes
	// the final authenticated chunk.
	Writer(key Key, dst io.Writer, aad []byte) (io.WriteCloser, error)
	// Reader wraps src so reads are opened under key with aad; a truncated
	// stream surfaces as StreamTruncated from the returned reader.
	Reader(key Key, src io.Reader, aad []byte) (io.Reader, error)
}

StreamSealer is a streaming authenticated-encryption scheme: it seals and opens an io.Writer / io.Reader pair in fixed-size chunks under a Key and associated data, extending the whole-buffer AEAD domain to arbitrarily large payloads. The Reader honours the hold-back contract: it MUST NOT surface a chunk's plaintext downstream before that chunk authenticates, and a stream cut short surfaces as StreamTruncated rather than as accepted plaintext (the final chunk carries a flag that a truncated stream never reaches). Implementations self-register via RegisterStreamSealer.

IFACE-PLUGIN: the registry hands plug-in StreamSealer instances back behind this interface; concrete scheme types stay unexported in their own packages.

func LookupStreamSealer

func LookupStreamSealer(name Algorithm) (s StreamSealer, ok bool)

LookupStreamSealer returns the StreamSealer registered under name.

IFACE-PLUGIN: the registry stores plug-in StreamSealer instances behind the StreamSealer interface — concrete types are intentionally unexported per scheme.

func RegisterStreamSealer

func RegisterStreamSealer(s StreamSealer) StreamSealer

RegisterStreamSealer inserts s under s.Algorithm() and returns it so callers can bind the singleton to a typed package-level variable. Panics on a nil sealer or when a distinct sealer already claims the same Algorithm.

IFACE-PLUGIN: the registry hands plug-in StreamSealer instances back to callers so each scheme keeps its concrete type unexported; the contract is the StreamSealer interface itself.

"Nil" here means UNUSABLE, not only an untyped nil: a typed nil pointer and a plug-in whose type is not comparable both satisfy the port and neither can serve one call (see internal/kernel/plugin).

Directories

Path Synopsis
key
jwk
Package jwk — the JSON Web Key format's codes, range 0.3.42.* (ADR 0005).
Package jwk — the JSON Web Key format's codes, range 0.3.42.* (ADR 0005).

Jump to

Keyboard shortcuts

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