Cryptographic substrate for Evidence-Bound Retrieval (EBR), HIPAA-class patient-owned data, and any git-tracked workflow that needs signed amendments, multi-party governance, hash-chained audit, and on-chain anchoring. Forked from AGWA/git-crypt (v0.8.0) and substantially extended. The
verumbinary and command-set are preserved for backward compatibility; verum adds capabilities, not new vocabulary.
ℹ️ Lineage. This repository is a substantial fork of
AGWA/git-crypt. The git history reaches back to 2012 (Andrew Ayer's first commits on upstreamgit-crypt); the verum extensions begin in March 2026 and currently comprise 34 commits on top of AGWA's 185 — adding modern encryption backends (age, SSH, YubiKey, wallet), Shamir M-of-N threshold key recovery, a hash-chained audit log with on-chain anchoring, SOPS integration, multi-platform CI + Homebrew distribution, and (on the previewfeature/trustless-modulebranch) multi-party ACL with policy gates, x402 HTTP licensing, ZK circuits, and on-chain governance contracts. SeeAUTHORS,THANKS.md, and the bottom-of-page Lineage section for full attribution.
- Modern encryption backends — age (X25519),
SSH (
ed25519,rsa), GPG, YubiKey PIV hardware-backed identities, plus Ethereum wallet identities for self-custody and on-chain operations. - Threshold-based recovery — split your symmetric key into Shamir M-of-N
shares across trusted recovery parties; no single party can reconstruct
the key. See
split-keyandunlock --shares. - Hash-chained audit log — every access produces a SHA-256-chained entry;
tampering is detectable via a single
verify-auditcall. - On-chain anchoring — publish the audit chain head to an
Ethereum-compatible chain, producing third-party-checkable proof that the
chain existed at time T. See
anchor-audit. - SOPS integration — bridge structured-file encryption (YAML, JSON, ENV) with Mozilla SOPS.
- Secrets-pattern bootstrap —
credentials-initsets up a.credentials/directory with.gitattributes, age recipient list, and pre-commit hook pre-configured.
verum is the cryptographic substrate referenced in the
memory-oracle papers as the
mechanism that turns file-layout precedence into cryptographically
enforced authorship + immutability. The memory-oracle position paper
paper/coala-extension/main.tex
§6 maps each open problem in the EBR substrate to a verum mechanism:
| EBR open problem | verum mechanism |
|---|---|
| Amendment authenticity | SSH/age signature on each amendment record |
| Amendment immutability | Hash-chained audit log + on-chain anchor |
| Patient-/operator-owned keys | Wallet identity + Shamir M-of-N recovery |
| Operator-bound biometric unlock | FIDO2 / WebAuthn PRF — FaceID / TouchID / YubiKey / Windows Hello; key in Secure Enclave or TPM, never extractable (preview, see below) |
| Multi-party amendment governance | Multi-party ACL with SSH-signed proposals (preview, see below) |
| Cross-substrate portability | Portable signed artifacts + on-chain hash |
| Pay-to-amend / EaaS-EBR | x402 HTTP licensing server (preview, see below) |
verum is usable independently of memory-oracle — you don't need EBR to use the encryption, signing, audit, or threshold-recovery capabilities. It is also usable as a pure git-encryption tool without any of the verum extensions, by simply not running them.
curl -fsSL http://verum.sh/install | bashThis installs the verum binary (with a git-crypt symlink for
backward compatibility with scripts invoking the legacy name). Detects
your platform, downloads the appropriate release artifact, verifies its
signature, and installs into /usr/local/bin/ (or $PREFIX if set).
brew tap ramene/tap
brew install verumRequirements: C++11 compiler (gcc 4.9+ or clang), OpenSSL libcrypto, GNU Make.
git clone https://github.com/ramene/verum.git
cd verum
make
sudo make install PREFIX=/usr/localFor macOS with Homebrew OpenSSL:
OPENSSL_PREFIX="$(brew --prefix openssl)"
make CXXFLAGS="-Wall -pedantic -Wno-long-long -O2 -std=c++11 -I${OPENSSL_PREFIX}/include" \
LDFLAGS="-L${OPENSSL_PREFIX}/lib -lcrypto"cmake -B build
cmake --build build
sudo cmake --install builddocker compose run --rm dev bash
# Inside container:
make clean && make && make testSee INSTALL.md for full details including man page building, Debian packaging, and Windows support.
These are only needed for specific features and are not required for core encryption:
| Feature | Dependency | Install |
|---|---|---|
| age encryption | age | brew install age / apt install age |
| YubiKey support | age-plugin-yubikey | brew install age-plugin-yubikey |
| SOPS integration | sops | brew install sops / apt install sops |
| Wallet identity | Ethereum wallet (MetaMask, hardware wallet, etc.) | N/A |
# 1. Initialize in your repository
cd my-repo
verum init
# 2. Specify which files to encrypt via .gitattributes
echo 'secrets/** filter=git-crypt diff=git-crypt' >> .gitattributes
echo '*.key filter=git-crypt diff=git-crypt' >> .gitattributes
git add .gitattributes
git commit -m "Configure encryption"
# 3. Add files — they encrypt transparently on commit
echo "API_KEY=s3cret" > secrets/config.env
git add secrets/config.env
git commit -m "Add encrypted secrets"
# 4. Grant access via GPG, age, SSH key, or wallet
verum add-gpg-user alice@example.com
verum add-age-recipient age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw...
verum add-age-recipient --ssh ~/.ssh/id_ed25519.pub
verum add-wallet-recipient 0xab12...
verum export-key /path/to/shared-key
# 5. Install the pre-commit hook to prevent plaintext leaks
verum install-hooksAfter a collaborator clones the repository:
# Unlock with GPG (automatic key selection)
verum unlock
# Unlock with a symmetric key
verum unlock /path/to/shared-key
# Unlock with age identity
verum unlock --age
# Unlock with SSH key via age
verum unlock --age --identity ~/.ssh/id_ed25519
# Unlock with Shamir M-of-N shares
verum unlock --shares share1.txt share2.txt share3.txt
# Unlock with wallet-derived identity
verum unlock --wallet 0xab12...| Command | Description |
|---|---|
init |
Generate a key and prepare the repo for encryption |
init -k NAME |
Initialize a named key for multi-key setups |
init -f |
Force re-initialization of an existing repo |
status |
Show encryption status of all files |
status -e |
Show only encrypted files |
status -f |
Fix files that should be encrypted but aren't |
status -m |
Machine-parseable output (TSV format) |
lock |
Encrypt all files in the working copy |
unlock |
Decrypt the repo using GPG or age |
unlock KEYFILE |
Decrypt using a symmetric key file |
unlock --shares F1 F2 ... |
Decrypt by combining Shamir key shares |
unlock --age |
Decrypt using age identity |
unlock --wallet ADDR |
Decrypt using wallet-derived identity |
refresh |
Force re-checkout of all encrypted files |
export-key FILE |
Export the symmetric key to a file |
export-key --version N |
Export a specific key version |
help [COMMAND] |
Show help information |
version |
Print the installed version |
| Command | Description |
|---|---|
add-gpg-user USERID |
Grant a GPG user access to encrypted files |
rm-gpg-user USERID |
Revoke a GPG user's access |
ls-gpg-users |
List all GPG user fingerprints per key |
| Command | Description |
|---|---|
add-age-recipient RECIPIENT |
Add an age public key as a collaborator |
add-age-recipient --ssh KEYFILE |
Add an SSH public key as a collaborator |
add-age-recipient --yubikey |
Add YubiKey PIV identities via age-plugin-yubikey |
add-age-recipient --fido2 |
Generate + add a FIDO2 hardware-bound identity via age-plugin-fido2-hmac (touch authenticator when prompted) |
add-age-recipient --se |
Generate + add an Apple Secure Enclave-bound identity via age-plugin-se (macOS 13+; Touch ID at decrypt) |
rm-age-recipient RECIPIENT |
Revoke an age recipient's access |
| Command | Description |
|---|---|
rotate-key |
Generate a new key version and re-wrap for all recipients |
split-key |
Split the symmetric key into M-of-N Shamir shares |
| Command | Description |
|---|---|
install-hooks |
Install pre-commit hook to prevent plaintext leaks |
verify-commits |
Verify GPG/SSH signatures on commits touching encrypted files |
| Command | Description |
|---|---|
sops-config |
Generate .sops.yaml for structured file encryption |
credentials-init |
Create .credentials/ directory with encryption setup |
| Command | Description |
|---|---|
audit-log |
Display the cryptographic audit trail |
verify-audit |
Verify audit log hash chain integrity |
anchor-audit |
Publish audit log hash to blockchain |
add-wallet-recipient ADDR |
Add an Ethereum wallet as a collaborator |
The feature/trustless-module branch contains substantial work that is
not yet part of the stable v0.9.0 release. It adds:
- Multi-party ACL — SSH-signed proposals, role-based access control, policy gates (m-of-n approval flows), agent support
- Per-user licensing — issue, verify, revoke, anchor, and export SSH-signed licenses; gate verum operations behind valid license checks with full backward compatibility
- x402 HTTP licensing server — automated license issuance over the
x402 protocol (
verum-trustless serve(now in ramene/verum-trustless)); pair with on-chain anchoring for verifiable proof of license issuance - ZK circuits + smart contracts —
circuits/for zero-knowledge proofs,contracts/for on-chain policy enforcement and audit anchoring
Status: preview / not-yet-released. The code is in active development and should be expected to break. The stable v0.9.0 release includes the modern encryption backends, key management, audit log, and on-chain anchoring of the audit chain head.
To preview the trustless module:
git fetch
git checkout feature/trustless-module
make -f Makefile.trustlessadd-age-recipient --fido2 generates a new FIDO2-bound age identity via
age-plugin-fido2-hmac
(MIT-licensed, written in Go). Works today on macOS and Linux with
YubiKey 5+, Solokey, NitroKey 3, Token2, OnlyKey, and other modern
FIDO2 authenticators with the hmac-secret extension. Windows builds
are not currently published by the plugin author.
# 1. Install the libfido2 dependency:
brew install libfido2 # macOS
apt install libfido2-dev # Debian/Ubuntu
# 2. Install the plugin — pick ONE of:
#
# a) Pre-built binary (recommended). Download from
# https://github.com/olastor/age-plugin-fido2-hmac/releases
# and place `age-plugin-fido2-hmac` on $PATH (alongside `age` is fine).
#
# b) One-liner install (Linux example; substitute OS/ARCH):
# VERSION=v0.5.0 OS=darwin ARCH=arm64
# curl -L "https://github.com/olastor/age-plugin-fido2-hmac/releases/download/$VERSION/age-plugin-fido2-hmac-$VERSION-$OS-$ARCH.tar.gz" \
# | tar -xz -C ~/.local/bin --strip-components=1
#
# c) Build from source (requires Go 1.22+):
# git clone https://github.com/olastor/age-plugin-fido2-hmac.git
# cd age-plugin-fido2-hmac && make build
# mv ./age-plugin-fido2-hmac ~/.local/bin/
# 3. Generate the identity (TOUCH your authenticator when prompted):
verum add-age-recipient --fido2
# → writes a recipient (age1fido2hmac1...) into the key file
# → writes the identity file (the credential pointer) to
# ./verum-fido2-identity.txt (move to a private location, mode 600)
# 4. Future unlock — point verum at the identity file via git config OR env var:
git config age.identity ~/.config/verum/fido2-identity.txt
verum unlock # touch the authenticator when prompted
# Alternative (no config writes):
AGE_IDENTITY=~/.config/verum/fido2-identity.txt verum unlock(verum unlock auto-detects age-encrypted keys and tries the configured
age identity; there is no separate --age flag.)
The private key lives in the device's secure hardware (FIDO2 chip / Secure Enclave / TPM) and never becomes extractable. The identity file on disk is a credential POINTER, not the key; possessing it without the authenticator is useless.
Recovery: pair with Shamir M-of-N (verum split-key) — losing
the authenticator AND the identity file means losing decryption
capability for that recipient.
After validating Phase 1, the original verum-touchid-helper design was
replaced with a much simpler integration using
age-plugin-se (MIT,
Apple Secure Enclave). The plugin is self-contained — no LaunchAgent
or custom Swift helper needed. The private key is bound to the Mac's
Secure Enclave and cannot be migrated to another machine; Touch ID /
passcode unlocks it at decrypt time per the configured access-control
policy. Requires macOS 13+ (Ventura).
# 1. Install age + age-plugin-se:
brew install age age-plugin-se
# (or download v0.1.4+ binaries from the plugin's GitHub releases)
# 2. Generate the identity (NO Touch ID at keygen — only at decrypt):
git-crypt add-age-recipient --se
# --se-access-control any-biometry-or-passcode (default)
# --se-identity-output PATH (default: ./verum-se-identity.txt)
# → writes recipient (age1se1...) into the key file
# → writes the identity file to ./verum-se-identity.txt (mode 600)
# 3. Future unlock fires Touch ID per the access-control policy:
git config age.identity ~/.config/verum/se-identity.txt
git-crypt unlock # Touch ID prompt firesTrade-off vs FIDO2 path: Secure Enclave keys are Mac-bound (no hardware key to lose, but also no cross-machine migration). FIDO2 keys are portable across any machine that can talk to the authenticator. Both achieve "operator-owned, biometric-gated keys" — pick by deployment shape.
Recovery: pair with Shamir M-of-N (git-crypt split-key). Losing
the Mac OR wiping the Secure Enclave means losing decryption for
SE-bound recipients.
Native iOS integration into the memory-oracle Expo demo apps. Paper-anchor demo for LNCS §7.4 dual-device demonstration: clinician's iPad scans patient's QR → patient looks at iPhone → Face ID unlocks the encrypted encounter record → record renders briefly on the clinician's iPad → patient retains key custody throughout.
Three-phase rollout, threat model, recovery patterns, caveats, and the supported-authenticator matrix are spec'd in doc/fido2-biometric-unlock.md.
verum encrypts files using AES-256 in CTR mode with a synthetic IV derived from the SHA-1 HMAC of the file. This is provably semantically secure under deterministic chosen-plaintext attack — it leaks no information beyond whether two files are identical.
Key wrapping supports GPG (RSA, ECC), age (X25519), SSH (via age), and wallet (via age-compatible derivation) backends. See doc/SECURITY.md for the full threat model, key management best practices, and security recommendations.
For post-quantum cryptography considerations, see doc/post-quantum-readiness.md.
- Not designed for encrypting most or all files in a repository. Best suited for a few sensitive files (keys, credentials, patient records, amendment sidecars) in an otherwise readable repository.
- Does not encrypt file names, commit messages, symlink targets, or other metadata.
- Key rotation (
rotate-key) re-encrypts going forward but does not retroactively protect historical content encrypted with the old key. - Encrypted files are not compressible by git's delta compression.
- Not compatible with some third-party git GUIs.
See the man page (verum help) and doc/SECURITY.md
for full details.
| Document | Description |
|---|---|
| INSTALL.md | Detailed build and installation instructions |
| CONTRIBUTING.md | Development setup, code style, and how to contribute |
| doc/SECURITY.md | Threat model and security best practices |
| doc/age-migration-guide.md | Migrating from GPG to age encryption |
| doc/post-quantum-readiness.md | Post-quantum cryptography assessment |
| doc/fido2-biometric-unlock.md | FaceID / Touch ID / FIDO2 unlock spec (v0.11 preview) |
| doc/multiple_keys.md | Using multiple named keys |
| memory-oracle/paper/coala-extension/main.tex | Academic context: EBR ↔ verum value-add mapping |
| Surface | State |
|---|---|
| Stable encryption + key management + audit chain | v0.9.0 — released |
| On-chain audit anchoring | v0.9.0 — released |
| Trustless / multi-party ACL / x402 licensing | Preview on feature/trustless-module |
| FIDO2 external keys (YubiKey 5+, Solokey, NitroKey, etc.) | Phase 1 SHIPPED on develop |
| Apple Secure Enclave (macOS 13+ Touch ID / passcode) | Phase 2 SHIPPING on feat/se-phase-2-apple-secure-enclave |
| iOS Face ID via mobile app integration | Phase 3 forthcoming per doc/fido2-biometric-unlock.md |
| Reference implementation | GPL-3.0-licensed, public |
| Memory-oracle pairing | Documented in memory-oracle paper §6 + §7 |
See CONTRIBUTING.md for development setup, code style, testing, and how to submit pull requests.
verum is licensed under the GNU General Public License v3.
Originally written by Andrew Ayer
(agwa@andrewayer.name) as git-crypt. The verum extensions are
maintained by Ramene Anthony. See AUTHORS and
THANKS.md for the full contributor list.
This repository is a fork of AGWA/git-crypt and substantially extends it. The relationship looks like this:
AGWA/git-crypt ← upstream maintained by Andrew Ayer (2012 — present, 185 commits)
│
├── 2026-03-02: forked by ramene
│
▼
ramene/git-crypt ← personal fork (preserved as frozen historical artifact)
│
│ (the 34 commits adding age + Shamir + wallet + audit + on-chain anchor
│ + SOPS + YubiKey + multi-platform release + Homebrew tap; this work
│ formerly carried the name "git-crypt-revived")
│
▼
ramene/verum ← this repository (canonical home, install via verum.sh)
same 34 + 185 commits; commit history preserved
for GPL-3.0 attribution compliance
- Upstream project:
github.com/AGWA/git-crypt— unmodified by verum. No PRs from this fork to upstream have been opened. - Frozen historical artifact:
github.com/ramene/git-crypt— the prior personal-fork home, preserved as it existed before the verum rebrand. Not deleted. - This repository:
github.com/ramene/verum— the canonical, public-facing home of the work. Same commit history as the personal fork; ongoing development happens here.
If you're a security reviewer or downstream packager evaluating verum's
relationship to upstream git-crypt, the git log is fully auditable —
185 commits authored by Andrew Ayer and contributors, 34 commits authored
by Ramene Anthony.