{"id":17181202,"url":"https://github.com/skeeto/enchive","last_synced_at":"2025-04-04T16:13:21.136Z","repository":{"id":50247155,"uuid":"83831780","full_name":"skeeto/enchive","owner":"skeeto","description":"Encrypted personal archives","archived":false,"fork":false,"pushed_at":"2023-02-14T15:56:05.000Z","size":173,"stargazers_count":631,"open_issues_count":6,"forks_count":51,"subscribers_count":27,"default_branch":"master","last_synced_at":"2024-10-15T11:36:23.577Z","etag":null,"topics":["chacha20","curve25519","encryption","pgp","sha-256"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/skeeto.png","metadata":{"files":{"readme":"README.md","changelog":"NEWS.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-03-03T19:05:42.000Z","updated_at":"2024-10-08T17:41:17.000Z","dependencies_parsed_at":"2024-10-25T19:13:11.295Z","dependency_job_id":"75357172-d3f9-4260-a9ab-7d29d9a6360c","html_url":"https://github.com/skeeto/enchive","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skeeto%2Fenchive","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skeeto%2Fenchive/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skeeto%2Fenchive/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skeeto%2Fenchive/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/skeeto","download_url":"https://codeload.github.com/skeeto/enchive/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247208139,"owners_count":20901570,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["chacha20","curve25519","encryption","pgp","sha-256"],"created_at":"2024-10-15T00:33:22.912Z","updated_at":"2025-04-04T16:13:21.119Z","avatar_url":"https://github.com/skeeto.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Enchive : encrypted personal archives\n\nEnchive is a tool to encrypt files to yourself for long-term archival.\nIt's a focused, simple alternative to more complex solutions such as\nGnuPG or encrypted filesystems. Enchive has no external dependencies\nand is trivial to build for local use. Portability is emphasized over\nperformance.\n\nSupported platforms: Linux, BSD, macOS, Windows\n\nThe name is a portmanteau of \"encrypt\" and \"archive,\" pronounced\nen'kīv.\n\nFiles are secured with ChaCha20, Curve25519, and HMAC-SHA256.\n\nManual page: [`enchive(1)`](http://nullprogram.com/enchive/)\n\n## Installation\n\nClone this repository, then:\n\n    $ make PREFIX=/usr install\n\nThis will install both the compiled binary and manual page under\n`PREFIX`. For staged installs, `DESTDIR` is also supported. The binary\ndoesn't have any external dependencies and doesn't actually need to be\ninstalled before use.\n\n## Usage\n\nThere are only three commands to worry about: `keygen`, `archive`, and\n`extract`. The very first thing to do is generate a master keypair\nusing `keygen`. You will be prompted for the passphrase to protect the\nsecret key, just like `ssh-keygen`.\n\n    $ enchive keygen\n\nBy default, this will create two files in `$XDG_CONFIG_HOME/enchive`\n(or `$HOME/.config/enchive`): `enchive.pub` (public key) and\n`enchive.sec` (secret key). On Windows, these are found under\n`%APPDATA%\\enchive` instead. Distribute `enchive.pub` to any machines\nwhere you plan to archive files. It's sufficient to encrypt files, but\nnot to decrypt them.\n\nTo archive a file for storage:\n\n    $ enchive archive sensitive.zip\n\nThis will encrypt `sensitive.zip` as `sensitive.zip.enchive` (leaving\nthe original in place). You can safely archive this wherever.\n\nTo extract the file on a machine with `enchive.sec`, use `extract`. It\nwill prompt for the passphrase you entered during key generation.\n\n    $ enchive extract sensitive.zip.enchive\n\nThe original `sensitive.zip` will be reproduced.\n\nWith no filenames, `archive` and `extract` operate on standard input\nand output.\n\n### Key management\n\nOne of the core features of Enchive is the ability to derive an\nasymmetric key pair from a passphrase. This means you can store your\narchive key in your brain! To access this feature, use the `--derive`\n(`-d`) option with the `keygen` command.\n\n    $ enchive keygen --derive\n\nThere's an optional argument to `--derive` that controls the number of\nkey derivation iterations (e.g. `--derive=26`). The default is 29.\nThis is a power two exponent, so every increment doubles the cost both\nin memory and computational demands.\n\nIf you want to change your protection passphrase, use the `--edit`\noption with `keygen`. It will load the secret key as if it were going\nto \"extract\" an archive, then write it back out with the new options.\nThis mode will also regenerate the public key file whether or not it\nexists.\n\nEnchive has a built-in protection key agent that keeps the protection\nkey in memory for a configurable period of time (default: 15 minutes)\nafter a protection passphrase has been read. This allows many files to\nbe decrypted inside a brief window with only a single passphrase\nprompt. Use the `--agent` (`-a`) global option to enable it. If it's\nenabled by default, use `--no-agent` to turn it off.\n\n    $ enchive --agent extract file.enchive\n\nUnlike gpg-agent and ssh-agent, this agent need not be started ahead\nof time. It is started on demand, shuts down on timeout, and does not\ncoordinate with environment variables. One agent is created per unique\nsecret key file. This feature requires a unix-like system.\n\n## Notes\n\nThe major version number increments each time any of the file formats\nchange, including the key derivation algorithm.\n\nThere's no effort at error recovery. It bails out on early on the\nfirst error. It should clean up any incomplete files when it does so.\n\nA purposeful design choice is that encrypted/archived files have no\ndistinguishing marks whatsoever (magic numbers, etc.), making them\nindistinguishable from random data.\n\n### Frequently asked questions\n\n\u003e This tool will never achieve critical mass, so what's the point?\n\nEnchive doesn't need to interact with any other systems or people, so\nthere's no need for critical mass, nor that there are any other users.\n\n\u003e Why can't you use an existing/established tool instead?\n\nI'm not aware of any tool that does everything Enchive does. GnuPG\ncomes close, but doesn't support deriving a key pair from a\npassphrase. If you're aware of an equal or better tool, please let me\nknow.\n\n\u003e Isn't it dangerous to derive a key pair from a passphrase?\n\nIt is when it's done incorrectly. However, Enchive uses a memory-hard\nkey derivation scheme that makes cracking passphrases very expensive —\nprohibitively so for any decent passphrase. This is because anyone who\nhas access to even a single encrypted file can mount an offline\nattack.\n\nDeriving asymmetric keys from a passphrase is a standard practice in\nthe Bitcoin world: [brainwallets][bw]. The caveat is that the\npassphrase must be sufficiently long, preferably chosen by a computer\nor [with dice][dw].\n\nWhen generating a master key, Enchive's default configuration is\nextremely paranoid. It would be far cheaper to break into your home\nand perform an evil maid attack than it would be to crack even a short\npassphrase. This is not the weak point.\n\n\u003e Shouldn't the initialization vector (IV) be generated randomly?\n\nThe purpose of an IV is to allow the same key to be safely used\nmultiple times. This is particularly important when the same key is\nderived on different occasions by Diffie-Hellman between the same key\npair. Enchive generates a random ephemeral key pair each time a file\nis encrypted, so the IV is unnecessary.\n\nSince ChaCha20 requires an IV regardless, Enchive simply uses the hash\nof the key. This has the additional effect of allowing the client to\nverify its symmetric key before beginning decryption. Otherwise a\nwrong key would only be detected by the MAC after decryption has\ncompleted.\n\n\u003e I'm getting the error \"Value too large for defined data type.\"\n\nThis is a flaw in the 32-bit version of glibc that prevents C programs\nfrom even opening files larger than 2GB. Compile with \"large file\nsupport\" enabled:\n\n    make CFLAGS='-O3 -D_FILE_OFFSET_BITS=64'\n\nAlternatively, use your shell to open files for Enchive:\n\n    $ enchive archive \u003clargefile \u003elargefile.enchive\n\nNote that Enchive will not be able to delete shell-opened files in case\nof errors (tampering, etc.).\n\n## Encryption/decryption algorithm\n\nThe process for encrypting a file:\n\n1. Generate an ephemeral 256-bit Curve25519 key pair.\n2. Perform a Curve25519 Diffie-Hellman key exchange with the master\n   key to produce a shared secret.\n3. SHA-256 hash the shared secret to generate a 64-bit IV.\n4. Add the format number to the first byte of the IV.\n5. Initialize ChaCha20 with the shared secret as the key.\n6. Write the 8-byte IV.\n7. Write the 32-byte ephemeral public key.\n8. Encrypt the file with ChaCha20 and write the ciphertext.\n9. Write `HMAC(key, plaintext)`.\n\nThe process for decrypting a file:\n\n1. Read the 8-byte ChaCha20 IV.\n2. Read the 32-byte ephemeral public key.\n3. Perform a Curve25519 Diffie-Hellman key exchange with the ephemeral\n   public key.\n4. Validate the IV against the shared secret hash and format version.\n5. Initialize ChaCha20 with the shared secret as the key.\n6. Decrypt the ciphertext using ChaCha20.\n7. Verify `HMAC(key, plaintext)`.\n\n## Key derivation algorithm\n\nEnchive uses an scrypt-like algorithm for key derivation, requiring a\nlarge buffer of random access memory. Derivation is controlled by a\nsingle difficulty exponent *D*. Secret key derivation requires 512MB\nof memory (D=29) by default, and protection key derivation requires\n32MB by default (D=25). The salt for the secret key is all zeros.\n\n1. Allocate a `(1 \u003c\u003c D) + 32` byte buffer, *M*.\n2. Compute `HMAC_SHA256(salt, passphrase)` and write this 32-byte\n   result to the beginning of *M*.\n3. For each uninitialized 32-byte chunk in *M*, compute the SHA-256\n   hash of the previous 32-byte chunk.\n4. Initialize a byte pointer *P* to the last 32-byte chunk of *M*.\n5. Compute the SHA-256 hash, *H*, of the 32 bytes at *P*.\n6. Overwrite the memory at *P* with *H*.\n7. Take the first *D* bits of *H* and use this value to set a new *P*\n   pointing into *M*.\n8. Repeat from step 5 `1 \u003c\u003c (D - 5)` times.\n9. *P* points to the result.\n\n## Compilation\n\nTo build on any unix-like system, run `make`. The resulting binary has\nno dependencies or external data, so you can just copy/move this into\nyour `PATH`.\n\n    $ make\n\nThe easiest way to build with Visual Studio is to use the amalgamation\nbuild. On any unix-like system (requires `sed`):\n\n    $ make amalgamation\n\nThis will create `enchive-cli.c`, a standalone C program that you can\ncopy anywhere and compile. Over on Windows:\n\n    C:\\\u003e cl.exe -nologo -Ox enchive-cli.c advapi32.lib\n\nThe compile-time options below also apply to this amalgamation build.\n\n### Compile-time configuration\n\nVarious options and defaults can be configured at compile time using C\ndefines (`-D...`).\n\n#### `ENCHIVE_OPTION_AGENT`\n\nWhether to expose the `--agent` and `--no-agent` option. This option\nis 0 by default on Windows since agents are unsupported.\n\n#### `ENCHIVE_AGENT_TIMEOUT`\n\nThe default agent timeout in seconds. This can be configured at run\ntime with an optional argument to `--agent`.\n\n#### `ENCHIVE_AGENT_DEFAULT_ENABLED`\n\nWhether or not to enable the agent by default. This can be explicitly\noverridden at run time with `--agent` and `--no-agent`.\n\n#### `ENCHIVE_PINENTRY_DEFAULT`\n\nThe default program to use for `pinentry`.\n\n#### `ENCHIVE_PINENTRY_DEFAULT_ENABLED`\n\nWhether or not to use `pinentry` by default when reading passphrases.\n\n#### `ENCHIVE_FILE_EXTENSION`\n\nThe file extension to add when archiving and remove when extracting. The\ndefault is `.enchive`, as it appears in the examples.\n\n#### `ENCHIVE_KEY_DERIVE_ITERATIONS`\n\nPower-of-two exponent for protection key derivation. Can be configured\nat run time with `--iterations`.\n\n#### `ENCHIVE_SECKEY_DERIVE_ITERATIONS`\n\nPower-of-two exponent for secret key derivation. Can be configured at\nrun time with the optional argument to `--derive`.\n\n#### `ENCHIVE_PASSPHRASE_MAX`\n\nMaximum passphrase size in bytes, including null terminator.\n\n\n[myths]: http://www.2uo.de/myths-about-urandom/\n[djb]: https://blog.cr.yp.to/20140205-entropy.html\n[getrandom]: https://manpages.debian.org/testing/manpages-dev/getrandom.2.en.html\n[getentropy]: http://man.openbsd.org/OpenBSD-current/man2/getentropy.2\n[csp]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa380246(v=vs.85).aspx\n[bw]: https://en.bitcoin.it/wiki/Brainwallet\n[dw]: http://world.std.com/~reinhold/diceware.html\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskeeto%2Fenchive","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fskeeto%2Fenchive","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskeeto%2Fenchive/lists"}