• Stars
    star
    630
  • Rank 71,328 (Top 2 %)
  • Language
    C
  • License
    The Unlicense
  • Created over 7 years ago
  • Updated almost 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Encrypted personal archives

Enchive : encrypted personal archives

Enchive is a tool to encrypt files to yourself for long-term archival. It's a focused, simple alternative to more complex solutions such as GnuPG or encrypted filesystems. Enchive has no external dependencies and is trivial to build for local use. Portability is emphasized over performance.

Supported platforms: Linux, BSD, macOS, Windows

The name is a portmanteau of "encrypt" and "archive," pronounced en'kīv.

Files are secured with ChaCha20, Curve25519, and HMAC-SHA256.

Manual page: enchive(1)

Installation

Clone this repository, then:

$ make PREFIX=/usr install

This will install both the compiled binary and manual page under PREFIX. For staged installs, DESTDIR is also supported. The binary doesn't have any external dependencies and doesn't actually need to be installed before use.

Usage

There are only three commands to worry about: keygen, archive, and extract. The very first thing to do is generate a master keypair using keygen. You will be prompted for the passphrase to protect the secret key, just like ssh-keygen.

$ enchive keygen

By default, this will create two files in $XDG_CONFIG_HOME/enchive (or $HOME/.config/enchive): enchive.pub (public key) and enchive.sec (secret key). On Windows, these are found under %APPDATA%\enchive instead. Distribute enchive.pub to any machines where you plan to archive files. It's sufficient to encrypt files, but not to decrypt them.

To archive a file for storage:

$ enchive archive sensitive.zip

This will encrypt sensitive.zip as sensitive.zip.enchive (leaving the original in place). You can safely archive this wherever.

To extract the file on a machine with enchive.sec, use extract. It will prompt for the passphrase you entered during key generation.

$ enchive extract sensitive.zip.enchive

The original sensitive.zip will be reproduced.

With no filenames, archive and extract operate on standard input and output.

Key management

One of the core features of Enchive is the ability to derive an asymmetric key pair from a passphrase. This means you can store your archive key in your brain! To access this feature, use the --derive (-d) option with the keygen command.

$ enchive keygen --derive

There's an optional argument to --derive that controls the number of key derivation iterations (e.g. --derive=26). The default is 29. This is a power two exponent, so every increment doubles the cost both in memory and computational demands.

If you want to change your protection passphrase, use the --edit option with keygen. It will load the secret key as if it were going to "extract" an archive, then write it back out with the new options. This mode will also regenerate the public key file whether or not it exists.

Enchive has a built-in protection key agent that keeps the protection key in memory for a configurable period of time (default: 15 minutes) after a protection passphrase has been read. This allows many files to be decrypted inside a brief window with only a single passphrase prompt. Use the --agent (-a) global option to enable it. If it's enabled by default, use --no-agent to turn it off.

$ enchive --agent extract file.enchive

Unlike gpg-agent and ssh-agent, this agent need not be started ahead of time. It is started on demand, shuts down on timeout, and does not coordinate with environment variables. One agent is created per unique secret key file. This feature requires a unix-like system.

Notes

The major version number increments each time any of the file formats change, including the key derivation algorithm.

There's no effort at error recovery. It bails out on early on the first error. It should clean up any incomplete files when it does so.

A purposeful design choice is that encrypted/archived files have no distinguishing marks whatsoever (magic numbers, etc.), making them indistinguishable from random data.

Frequently asked questions

This tool will never achieve critical mass, so what's the point?

Enchive doesn't need to interact with any other systems or people, so there's no need for critical mass, nor that there are any other users.

Why can't you use an existing/established tool instead?

I'm not aware of any tool that does everything Enchive does. GnuPG comes close, but doesn't support deriving a key pair from a passphrase. If you're aware of an equal or better tool, please let me know.

Isn't it dangerous to derive a key pair from a passphrase?

It is when it's done incorrectly. However, Enchive uses a memory-hard key derivation scheme that makes cracking passphrases very expensive — prohibitively so for any decent passphrase. This is because anyone who has access to even a single encrypted file can mount an offline attack.

Deriving asymmetric keys from a passphrase is a standard practice in the Bitcoin world: brainwallets. The caveat is that the passphrase must be sufficiently long, preferably chosen by a computer or with dice.

When generating a master key, Enchive's default configuration is extremely paranoid. It would be far cheaper to break into your home and perform an evil maid attack than it would be to crack even a short passphrase. This is not the weak point.

Shouldn't the initialization vector (IV) be generated randomly?

The purpose of an IV is to allow the same key to be safely used multiple times. This is particularly important when the same key is derived on different occasions by Diffie-Hellman between the same key pair. Enchive generates a random ephemeral key pair each time a file is encrypted, so the IV is unnecessary.

Since ChaCha20 requires an IV regardless, Enchive simply uses the hash of the key. This has the additional effect of allowing the client to verify its symmetric key before beginning decryption. Otherwise a wrong key would only be detected by the MAC after decryption has completed.

I'm getting the error "Value too large for defined data type."

This is a flaw in the 32-bit version of glibc that prevents C programs from even opening files larger than 2GB. Compile with "large file support" enabled:

make CFLAGS='-O3 -D_FILE_OFFSET_BITS=64'

Alternatively, use your shell to open files for Enchive:

$ enchive archive <largefile >largefile.enchive

Note that Enchive will not be able to delete shell-opened files in case of errors (tampering, etc.).

Encryption/decryption algorithm

The process for encrypting a file:

  1. Generate an ephemeral 256-bit Curve25519 key pair.
  2. Perform a Curve25519 Diffie-Hellman key exchange with the master key to produce a shared secret.
  3. SHA-256 hash the shared secret to generate a 64-bit IV.
  4. Add the format number to the first byte of the IV.
  5. Initialize ChaCha20 with the shared secret as the key.
  6. Write the 8-byte IV.
  7. Write the 32-byte ephemeral public key.
  8. Encrypt the file with ChaCha20 and write the ciphertext.
  9. Write HMAC(key, plaintext).

The process for decrypting a file:

  1. Read the 8-byte ChaCha20 IV.
  2. Read the 32-byte ephemeral public key.
  3. Perform a Curve25519 Diffie-Hellman key exchange with the ephemeral public key.
  4. Validate the IV against the shared secret hash and format version.
  5. Initialize ChaCha20 with the shared secret as the key.
  6. Decrypt the ciphertext using ChaCha20.
  7. Verify HMAC(key, plaintext).

Key derivation algorithm

Enchive uses an scrypt-like algorithm for key derivation, requiring a large buffer of random access memory. Derivation is controlled by a single difficulty exponent D. Secret key derivation requires 512MB of memory (D=29) by default, and protection key derivation requires 32MB by default (D=25). The salt for the secret key is all zeros.

  1. Allocate a (1 << D) + 32 byte buffer, M.
  2. Compute HMAC_SHA256(salt, passphrase) and write this 32-byte result to the beginning of M.
  3. For each uninitialized 32-byte chunk in M, compute the SHA-256 hash of the previous 32-byte chunk.
  4. Initialize a byte pointer P to the last 32-byte chunk of M.
  5. Compute the SHA-256 hash, H, of the 32 bytes at P.
  6. Overwrite the memory at P with H.
  7. Take the first D bits of H and use this value to set a new P pointing into M.
  8. Repeat from step 5 1 << (D - 5) times.
  9. P points to the result.

Compilation

To build on any unix-like system, run make. The resulting binary has no dependencies or external data, so you can just copy/move this into your PATH.

$ make

The easiest way to build with Visual Studio is to use the amalgamation build. On any unix-like system (requires sed):

$ make amalgamation

This will create enchive-cli.c, a standalone C program that you can copy anywhere and compile. Over on Windows:

C:\> cl.exe -nologo -Ox enchive-cli.c advapi32.lib

The compile-time options below also apply to this amalgamation build.

Compile-time configuration

Various options and defaults can be configured at compile time using C defines (-D...).

ENCHIVE_OPTION_AGENT

Whether to expose the --agent and --no-agent option. This option is 0 by default on Windows since agents are unsupported.

ENCHIVE_AGENT_TIMEOUT

The default agent timeout in seconds. This can be configured at run time with an optional argument to --agent.

ENCHIVE_AGENT_DEFAULT_ENABLED

Whether or not to enable the agent by default. This can be explicitly overridden at run time with --agent and --no-agent.

ENCHIVE_PINENTRY_DEFAULT

The default program to use for pinentry.

ENCHIVE_PINENTRY_DEFAULT_ENABLED

Whether or not to use pinentry by default when reading passphrases.

ENCHIVE_FILE_EXTENSION

The file extension to add when archiving and remove when extracting. The default is .enchive, as it appears in the examples.

ENCHIVE_KEY_DERIVE_ITERATIONS

Power-of-two exponent for protection key derivation. Can be configured at run time with --iterations.

ENCHIVE_SECKEY_DERIVE_ITERATIONS

Power-of-two exponent for secret key derivation. Can be configured at run time with the optional argument to --derive.

ENCHIVE_PASSPHRASE_MAX

Maximum passphrase size in bytes, including null terminator.

More Repositories

1

endlessh

SSH tarpit that slowly sends an endless banner
C
7,113
star
2

w64devkit

Portable C and C++ Development Kit for x64 (and x86) Windows
C
2,871
star
3

elfeed

An Emacs web feeds client
Emacs Lisp
1,371
star
4

skewer-mode

Live web development in Emacs
Emacs Lisp
1,066
star
5

hash-prospector

Automated integer hash function discovery
C
672
star
6

branchless-utf8

Branchless UTF-8 decoder
C
589
star
7

scratch

Personal scratch code
C
366
star
8

pixelcity

Shamus Young's procedural city project
C++
359
star
9

optparse

Portable, reentrant, getopt-like option parser
C
326
star
10

pdjson

C JSON parser library that doesn't suck
C
279
star
11

interactive-c-demo

Demonstration of interactive C programming
C
249
star
12

emacs-aio

async/await for Emacs Lisp
Emacs Lisp
215
star
13

webgl-particles

WebGL particle system demo
JavaScript
203
star
14

fantasyname

Fantasy name generator
C
180
star
15

lstack

C11 Lock-free Stack
C
172
star
16

resurrect-js

JavaScript serialization that preserves behavior and reference circularity.
JavaScript
169
star
17

passphrase2pgp

Generate a PGP key from a passphrase
Go
168
star
18

pure-linux-threads-demo

Pthreads-free Linux threading demo
Assembly
147
star
19

ptrace-examples

Examples for Linux ptrace(2)
C
134
star
20

memdig

Memory cheat tool for Windows and Linux games
C
131
star
21

dosdefender-ld31

DOS Defender (Ludum Dare #31)
C
130
star
22

dotfiles

My personal dotfiles
Shell
124
star
23

Prelude-of-the-Chambered

Notch's Prelude of the Chambered 48-hour game
Java
124
star
24

sort-circle

Colorful sorting animations
C
124
star
25

.emacs.d

My personal .emacs.d
Emacs Lisp
119
star
26

growable-buf

Growable Memory Buffer for C99
C
116
star
27

youtube-dl-emacs

Emacs youtube-dl download manager
Emacs Lisp
104
star
28

getopt

POSIX getopt() as a portable header library
C
102
star
29

trie

C99 trie library
C
98
star
30

opengl-demo

Minimal OpenGL 3.3 core profile demo
C
97
star
31

Minicraft

Notch's Ludum Dare 22 entry.
Java
95
star
32

igloojs

Low-level, fluent, OOP WebGL wrapper
JavaScript
89
star
33

hastyhex

A blazing fast hex dumper
C
88
star
34

webgl-game-of-life

WebGL Game of Life
JavaScript
88
star
35

u-config

a smaller, simpler, portable pkg-config clone
C
84
star
36

bmp

24-bit BMP (Bitmap) ANSI C header library
C
84
star
37

elisp-ffi

Emacs Lisp Foreign Function Interface
C++
83
star
38

rng-js

JavaScript seedable random number generation tools.
JavaScript
82
star
39

mandel-simd

Mandelbrot set in SIMD (SSE, AVX)
C
81
star
40

sample-java-project

Example Ant-based Java project
Java
78
star
41

nasm-mode

Major mode for editing NASM assembly programs
Emacs Lisp
78
star
42

vulkan-test

Test if your system supports Vulkan
C
77
star
43

gap-buffer-animator

Gap buffer animation creator
C
72
star
44

at-el

Prototype-based Emacs Lisp object system
Emacs Lisp
71
star
45

skeeto.github.com

Personal website/blog
HTML
64
star
46

ulid-c

ULID Library for C
C
62
star
47

xf8

8-bit Xor Filter in C99
C
61
star
48

race64

World's fastest Base64 encoder / decoder
C
58
star
49

devdocs-lookup

Quick Emacs API lookup on devdocs.io
Emacs Lisp
58
star
50

webgl-path-solver

WebGL shortest path solver
JavaScript
57
star
51

x86-lookup

Quickly jump to x86 documentation from Emacs
Emacs Lisp
57
star
52

javadoc-lookup

Quickly lookup Javadoc pages from Emacs
Emacs Lisp
55
star
53

am-i-shadowbanned

Online reddit shadowban test
JavaScript
53
star
54

fun-liquid

Physics engine liquid in Java.
Java
53
star
55

minimail

Embeddable POP3 + SMTP server.
C
50
star
56

emacs-memoize

Elisp memoization functions
Emacs Lisp
48
star
57

webgl-fire

WebGL fire effect
JavaScript
47
star
58

simplegpg

Simplified, signify-like interface to GnuPG signatures
Shell
47
star
59

autotetris-mode

Automatically play Emacs Tetris
Emacs Lisp
45
star
60

fiber-await

Win32 Fiber async/await demo
C
45
star
61

lorenz-webgl

Lorenz System WebGL
JavaScript
42
star
62

asteroids-demo

Asteroids Clone for Windows
C
40
star
63

elisp-json-rpc

JSON-RPC library for Emacs Lisp
Emacs Lisp
39
star
64

hashtab

Simple C hash table
C
37
star
65

pgp-poisoner

PGP key poisoner
Go
36
star
66

bf-x86

x86_64 brainfuck compiler
C
36
star
67

wisp

Wisp, a lisp programming language
C
33
star
68

binitools

Bini file translator for the game Freelancer
C
32
star
69

double-pendulum

JavaScript double pendulum simulation with RK4 integration
JavaScript
30
star
70

predd

Multimethods for Emacs Lisp
Emacs Lisp
29
star
71

atomkv

In-memory, JSON, key-value service with compare-and-swap updates and event streams
Go
29
star
72

purgeable

Purgeable memory allocations for Linux
C
28
star
73

lqueue

C11 + Pthreads Atomic Bounded Work Queue
C
28
star
74

uuid

UUID generator for Go
Go
27
star
75

goblin-com

Goblin-COM roguelike game for 7DRL 2015
C
27
star
76

jekyll-deck

Template for Jekyll / deck.js presentations
27
star
77

rlhk

Roguelike Header Kit
C
26
star
78

voronoi-toy

WebGL interactive Voronoi diagram
JavaScript
26
star
79

transcription-mode

Emacs mode for editing transcripts.
Emacs Lisp
25
star
80

october-chess-engine

Java Chess Engine
Java
25
star
81

boids-js

HTML5 boids (skewer-mode demo)
JavaScript
25
star
82

optparse-go

GNU style long options for Go
Go
24
star
83

geohash

Fast, lean, efficient geohash C library
C
24
star
84

bitpack

Emacs Lisp structure packing
Emacs Lisp
23
star
85

lean-static-gpg

Lean, static GnuPG build for Linux
Shell
23
star
86

connect4

Connect Four AI and Engine
C
22
star
87

blowpipe

Authenticated Blowfish-encrypted pipe
C
22
star
88

markov-text

Markov chain text generation in Emacs Lisp
Emacs Lisp
22
star
89

joymacs

Joystick support for Emacs
C
21
star
90

emacs-rsa

RSA cryptography in Emacs Lisp
Emacs Lisp
21
star
91

live-dev-env

A live CD of my personal development environment
Shell
20
star
92

dynamic-function-benchmark

Benchmark for three different kinds of dynamic function calls
C
20
star
93

utf-7

UTF-7 encoder and decoder in ANSI C
C
19
star
94

elisp-fakespace

Emacs Lisp namespaces (defpackage)
Emacs Lisp
18
star
95

siphash

Incremental SipHash in C
C
18
star
96

bencode-c

Bencode decoder in ANSI C
C
17
star
97

british-square

British Square Engine (Analysis and Perfect AI Player)
C
17
star
98

pokerware

Pokerware Secure Passphrase Generation
Makefile
17
star
99

xxtea

100% XXTEA authenticated, chunked file encryption
C
17
star
100

gnupg-windows-build

Cross-compile GnuPG for Windows using Docker
Dockerfile
17
star