Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
keeper — Simple Secure Keeper for Secrets | Kitploit
Tools/GitHubGitHub/agberohq/keeper
Authentication & AuthorizationEncryption/Decryption ToolsCryptographySecret Detection
GitHubagberohq/keeper

keeper

Simple Secure Keeper for Secrets

View Repository
1204155 months agoReviewed by Kitploit

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

keeper

Keeper is a cryptographic secret store for Go. It encrypts arbitrary byte payloads at rest using Argon2id key derivation and XChaCha20-Poly1305 (default) authenticated encryption, and stores them in an embedded bbolt database.

It ships as three things you can use independently:

  • A Go library — embed a hardened secret store directly in your process, with four security levels, per-bucket DEK isolation, and a tamper-evident audit chain.
  • An HTTP handler (x/keephandler) — mount keeper endpoints on any net/http mux in one call, with pluggable hooks, guards, and response encoders for access control and audit logging.
  • A CLI (cmd/keeper) — a terminal interface with a persistent REPL session, no-echo secret entry, and zero shell-history exposure.

Keeper was designed as the foundational secret management layer for the Agbero load balancer but has no dependency on Agbero and works in any Go project.


Contents

  • Security model
  • Cryptographic design
  • Key hierarchy
  • Storage schema
  • Audit chain
  • Jack integration
  • x/keepcmd — reusable CLI operations
  • x/keephandler — HTTP handler
  • API reference
  • Error catalogue
  • Security decisions
  • Dependencies

Security model

Keeper partitions secrets into buckets. Every bucket has an immutable BucketSecurityPolicy that governs how its Data Encryption Key (DEK) is protected. Four levels are available.

Schemes vs. Security Levels

A scheme is a URI prefix that groups related buckets (vault://, certs://, space://, or any name you register). A security level is a property of the bucket policy set at creation and immutable thereafter.

You can mix security levels freely within the same scheme. For example, vault://system might be LevelPasswordOnly (auto-unlocked at startup), while vault://admin is LevelAdminWrapped (requires explicit credential).

LevelPasswordOnly

The bucket DEK is derived from the master key using HKDF-SHA256 with a domain-separated info string per bucket (keeper-bucket-dek-v1:scheme:namespace). All LevelPasswordOnly buckets are unlocked automatically when UnlockDatabase is called with the correct master passphrase. No per-bucket credential is required at runtime. This level is appropriate for secrets the process needs at startup without human interaction.

LevelAdminWrapped

The bucket has a randomly generated 32-byte DEK unique to that bucket. The DEK is never stored in plaintext. For each authorised admin a Key Encryption Key (KEK) is derived from HKDF(masterKey‖adminCred, dekSalt) and used to wrap the DEK via XChaCha20-Poly1305. The bucket is inaccessible until an admin calls UnlockBucket with their credential. The master passphrase alone cannot decrypt the bucket. Revoking one admin does not affect any other admin's wrapped copy.

LevelHSM

The bucket DEK is generated at CreateBucket time and immediately wrapped by a caller-supplied HSMProvider. The provider performs the wrap and unwrap operations — keeper never handles the raw DEK after handing it to the provider. UnlockDatabase automatically calls the provider to unwrap and seed the Envelope for all registered HSM buckets. Master key rotation does not re-encrypt these buckets; the DEK is provider-controlled.

A built-in SoftHSM implementation backed by a memguard-protected wrapping key is available in pkg/hsm for testing and CI environments. Do not use it in production.

LevelRemote

Identical to LevelHSM in key management behaviour, but the HSMProvider is implemented by pkg/remote.Provider — a configurable HTTPS adapter that delegates wrap and unwrap to any remote KMS service over TLS. Pre-built configurations for HashiCorp Vault Transit, AWS KMS, and GCP Cloud KMS are provided in pkg/remote. For production use, configure TLSClientCert and TLSClientKey to enable mutual TLS authentication.


Cryptographic design

Master key derivation

salt ← random 32 bytes, generated once, stored as a versioned SaltStore (unencrypted)
masterKey ← Argon2id(passphrase, salt, t=3, m=64 MiB, p=4) → 32 bytes

A verification hash is stored on first derivation:

verifyHash ← Argon2id(masterKey, "verification", t=1, m=64 MiB, p=4) → 32 bytes

Subsequent DeriveMaster calls recompute this hash and compare it with crypto/subtle.ConstantTimeCompare. A mismatch returns ErrInvalidPassphrase.

The KDF salt is stored unencrypted by design. It must be readable before UnlockDatabase to derive the master key — encrypting it with a key derived from the master would be circular. A KDF salt is not a secret; its purpose is uniqueness, not confidentiality.

Secret encryption

Each plaintext value is encrypted with XChaCha20-Poly1305 using the bucket DEK:

nonce ← random 24 bytes
ciphertext ← XChaCha20-Poly1305.Seal(nonce, DEK, plaintext)

The stored record is a msgpack-encoded Secret struct containing the ciphertext, encrypted metadata, and schema version. Authentication is implicit: a ciphertext decrypted with the wrong key produces an AEAD authentication failure before any plaintext is returned.

KEK derivation — LevelAdminWrapped

salt ← random 32 bytes, generated at bucket creation, stored in policy
ikm ← masterKey ‖ adminCredential
KEK ← HKDF-SHA256(ikm, salt, info="keeper-kek-v1") → 32 bytes
wrappedDEK ← XChaCha20-Poly1305.Seal(nonce, KEK, DEK)

The KEK is derived using HKDF rather than a second Argon2 pass. The master key was already produced by a high-cost KDF; a second Argon2 invocation would add hundreds of milliseconds of latency to every UnlockBucket call with no security benefit. HKDF-SHA256 operates in approximately one microsecond.

Defense-in-depth: An attacker who compromises only the database obtains the wrapped DEK and the HKDF salt but cannot derive the KEK without the master key. An attacker who compromises only the master key cannot unwrap any LevelAdminWrapped DEK without also knowing the admin credential.

Metadata encryption — secrets

Secret metadata (creation time, update time, access count, version) is encrypted separately from the ciphertext:

metaKey ← HKDF-SHA256(bucketDEK, nil, info="keeper-metadata-v1") → 32 bytes
encryptedMeta ← XChaCha20-Poly1305.Seal(nonce, metaKey, msgpack(metadata))

For LevelAdminWrapped, LevelHSM, and LevelRemote buckets this means metadata is inaccessible without the bucket credential, preventing an attacker with read access to the database file from learning access patterns or timestamps.

Timing side-channel note: XChaCha20-Poly1305 processes the full ciphertext before returning an authentication error. The fallback decrypt path (new derived DEK → old master-key-as-DEK) takes the same wall-clock time regardless of which key succeeds. No timing side-channel leaks the migration state of a record.

Metadata encryption — policies, WAL, and audit

All structural metadata is also encrypted at rest. Two keys are derived from the master key at UnlockDatabase time:

policyEncKey ← HKDF-SHA256(masterKey, nil, info="keeper-policy-enc-v1") → 32 bytes
auditEncKey  ← HKDF-SHA256(masterKey, nil, info="keeper-audit-enc-v1")  → 32 bytes

policyEncKey encrypts: BucketSecurityPolicy values and the rotation WAL.

auditEncKey encrypts: the Scheme, Namespace, and Details fields of every audit event.

Both keys are cleared from memory at Lock(). The cipher used for metadata encryption is the same configurable crypt.Cipher interface used for secrets — the user's cipher choice (AES-256-GCM for FIPS, XChaCha20-Poly1305 by default) flows through automatically.

Wire format for all encrypted metadata blobs:

Download Tool