git-crypt
A Rust implementation of git-crypt for transparent encryption of files in a git repository.
Features
- 🔒 Transparent Encryption: Files are automatically encrypted when committed and decrypted when checked out
- 🛡️ AES-256-GCM: Strong authenticated encryption with tamper detection
- 🔧 Git Filter Integration: Seamless integration using git's clean/smudge filters
- 🔑 Key Management: Export and import symmetric keys for secure sharing
- 👥 GPG Support: Optional GPG integration for team key distribution
- 🪪 SSH/age Sharing: Optional age/rage integration to share keys using SSH recipients
- ☁️ S3 Sync (Optional): Upload encrypted key blobs to S3/MinIO when
sync-s3is enabled - 📦 Simple CLI: Easy-to-use command-line interface
Installation
Using cargo
# If you want GPG support, install with the gpg feature
# If you want SSH/age support for sharing keys via SSH
# SSH sharing with automatic S3 sync (requires ssh + sync-s3)
Quick Start
# Initialize in your git repository
# Configure which files to encrypt in .gitattributes
# Add encrypted files (automatically encrypted)
# Export key for sharing
Documentation
📚 View Full Documentation (generated with cargo doc)
The complete documentation includes:
- Detailed usage examples
- Security considerations
- Architecture overview
- Complete API reference
- Testing guide
Generate documentation locally:
How It Works
git-crypt uses git's filter system to transparently encrypt and decrypt files:
- Clean filter: Encrypts files when you
git add - Smudge filter: Decrypts files when you
git checkout - Diff filter: Shows encryption status in
git diff
The encryption key is stored in .git/git-crypt/keys/default and is never committed.
SSH/age Key Sharing (Optional)
Build with --features ssh (and optionally sync-s3) to share keys using SSH recipients powered by the Rust age implementation:
# Encrypt the repo key for an SSH public key (optionally sync to S3 when sync-s3 is enabled)
# Recipient decrypts using their private key
Key command flags:
--ssh-key <PATH>: path to the recipient's SSH public key (OpenSSH format).--alias <NAME>: optional label used for the generated.agefile; falls back to the key's comment or a fingerprint when omitted.--input <FILE>: the.agebundle produced byadd-ssh-user(local path or S3 URL if synced).--identity <PATH>: the SSH private key used to decrypt the age file (works with encrypted keys; the CLI will prompt for a passphrase when needed).
This uses rage/age under the hood, so the resulting .age files are also compatible with the standalone rage CLI or any S3-compatible object storage if sync-s3 uploads are enabled.
S3 Sync (Optional sync-s3 feature)
When the sync-s3 feature is compiled together with ssh, git-crypt can automatically upload the encrypted .age blob to S3 or a compatible service (MinIO). Configure the behaviour by adding a .git-crypt.toml file in the repository root:
[]
= true
= "git-crypt"
= "team-alpha"
= "demo-repo" # optional, defaults to the folder name
= "us-east-1"
= "http://localhost:9000" # optional (useful for MinIO)
= "minioadmin"
= "minioadmin"
= true
Environment variables can override any of these settings or replace the file entirely. Supported keys:
GIT_CRYPT_SYNC_S3_BUCKETGIT_CRYPT_SYNC_S3_SCOPEGIT_CRYPT_SYNC_S3_REPOGIT_CRYPT_SYNC_S3_REGIONGIT_CRYPT_SYNC_S3_ENDPOINTGIT_CRYPT_SYNC_S3_ACCESS_KEYGIT_CRYPT_SYNC_S3_SECRET_KEYGIT_CRYPT_SYNC_S3_ENABLED(1/0,true/false)GIT_CRYPT_SYNC_S3_PATH_STYLE(1/0,true/false)
Example:
GIT_CRYPT_SYNC_S3_BUCKET=git-crypt \
GIT_CRYPT_SYNC_S3_SCOPE=team-alpha \
GIT_CRYPT_SYNC_S3_ENDPOINT=http://localhost:9000 \
GIT_CRYPT_SYNC_S3_ACCESS_KEY=minioadmin \
GIT_CRYPT_SYNC_S3_SECRET_KEY=minioadmin \
Each uploaded object follows the pattern <scope>/<repo>/keys/age/<alias>.age. To experiment locally you can use the provided docker-compose.yaml:
# then build git-crypt with ssh + sync-s3 features and run add-ssh-user
# run the sync integration test (requires Docker/MinIO running locally)
SYNC_S3_TEST=1
By default the upload is best-effort: failures are reported as warnings but do not prevent the local .age file from being written.
Commands
init- Initialize git-crypt in the current repositorylock- Lock the repository (remove filters)unlock [--key-file PATH]- Unlock the repositoryexport-key OUTPUT- Export the symmetric key to a fileimport-key INPUT- Import a symmetric key from a fileadd-gpg-user GPG_ID- Grant access to a GPG user (requires GPG feature)add-ssh-user --ssh-key PATH [--alias NAME]- Encrypt the key for an SSH user via age/rage (requires ssh feature)import-age-key --input FILE --identity SSH_KEY- Import an age-encrypted key with your SSH identity (requires ssh feature)
Differences from Original git-crypt
This is a complete reimplementation with some differences:
- ✅ Written in Rust for memory safety and performance
- ✅ GPG support is optional (compile-time feature)
- ⚠️ Not compatible with original git-crypt (different file format)
- ✅ Focus on simplicity and modern Rust idioms
Development
# Run tests
# Build with GPG support
# Generate documentation
License
MIT OR Apache-2.0
Contributing
Contributions welcome! Please open an issue or pull request.
Note: For complete documentation, examples, and API reference, please run cargo doc --no-deps --open or visit docs.rs/git-crypt.