{"id":19388332,"url":"https://github.com/mk-fg/git-nerps","last_synced_at":"2025-10-26T11:06:26.485Z","repository":{"id":144996034,"uuid":"41633004","full_name":"mk-fg/git-nerps","owner":"mk-fg","description":"Tool to encrypt and manage selected files (or parts of files) under git repository","archived":false,"fork":false,"pushed_at":"2024-05-09T16:23:45.000Z","size":55,"stargazers_count":14,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-02T22:23:20.967Z","etag":null,"topics":["convenience","cryptography","git","nacl","python","secret-storage","security","tool"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"wtfpl","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mk-fg.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":null,"funding":null,"license":"COPYING","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":"2015-08-30T15:18:07.000Z","updated_at":"2024-05-09T16:23:48.000Z","dependencies_parsed_at":null,"dependency_job_id":"c947e2d7-821a-4741-ab00-40fcd561773a","html_url":"https://github.com/mk-fg/git-nerps","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mk-fg%2Fgit-nerps","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mk-fg%2Fgit-nerps/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mk-fg%2Fgit-nerps/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mk-fg%2Fgit-nerps/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mk-fg","download_url":"https://codeload.github.com/mk-fg/git-nerps/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250532053,"owners_count":21446107,"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":["convenience","cryptography","git","nacl","python","secret-storage","security","tool"],"created_at":"2024-11-10T10:12:28.433Z","updated_at":"2025-10-26T11:06:21.435Z","avatar_url":"https://github.com/mk-fg.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"git-nerps\n=========\n\nTool to encrypt and manage secret files in git repository.\n\nUses libsodium_ (wrapped by libnacl_ / PyNaCl_) encryption\n(`NaCl crypto_secretbox`_, see \"Crypto details\" section below for more info),\ngitattributes and git-config for configuration storage, which is partly shared\nwith git and can be edited/adjusted by hand as well.\n\nAll the stuff is implemented as one python script\n(python3, though repo history has python2 version as well),\nwhich has different subcommands.\nSee --help output for a full list of these.\n\n.. _libsodium: http://libsodium.org/\n.. _libnacl: http://libnacl.readthedocs.io/\n.. _PyNaCl: http://pynacl.readthedocs.io/\n.. _NaCl crypto_secretbox: http://nacl.cr.yp.to/secretbox.html\n\n|\n\n.. contents::\n  :backlinks: none\n\nRepository URLs:\n\n- https://github.com/mk-fg/git-nerps\n- https://codeberg.org/mk-fg/git-nerps\n- https://fraggod.net/code/git/git-nerps\n\n\n\nIdea\n----\n\nMain purpose of the tool is to make it easy to store configuration that has\nsome secrets in it within branches of a git repository.\n\nI.e. imagine a bunch of containers which share some/most configs and keep their\nconfiguration in git branches.\n\nYou'd like to easily pull, push, merge and cherry-pick between these\nrepositories/branches, but each container has occasional bits that should not be\nshared, e.g. passwords.txt file.\n\nOne solution is to keep such secret files out of repository or in a separate one,\nanother would be to transparently encrypt/decrypt these files in the repository.\n\nSuch secrets can even be shared between containers that have access to same key,\nwhile remaining inaccessible without one.\n\nThat way, only one short bit of data (key) has to be unique for a host,\nand presumably stored/backed-up in some trusted place(s) (e.g. dev machine),\nwhile the rest of the host configuration can be shared, well-replicated and/or public.\n\nModifying .git/config and .gitattributes to facilitate that by hand gets old fast,\nplus one needs to store keys and have a dedicated tool/wrapper for git filters anyway.\n\nThis tool can be used to do all that in a simple and relatively foolproof way.\n\n\n\n\nUsage\n-----\n\nSee ``git nerps --help`` for full list of all supported commands and common\noptions, and e.g. ``git nerps key-gen --help`` for args/opts to any particular\ncommand.\n\n\"git-nerps\" and \"git nerps\" commands be used interchangeably, when script is in $PATH.\n\n\nInitialize repository configuration\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nSame as with most commands below, only makes sense to run in a git repository.\n\n::\n\n  % git nerps init\n\nThis is done automatically on any meaningful action (e.g. \"key-gen\"),\nso can usually be skipped.\n\nRepository config \".git/config\" should have these additional sections after that::\n\n  [filter \"nerps\"]\n    clean = ~/.git-nerps git-clean\n    smudge = ~/.git-nerps git-smudge\n  [diff \"nerps\"]\n    textconv = ~/.git-nerps git-diff\n    cachetextconv = true\n  [nerps]\n    n-e-r-p-s = NERPS\n    version = 1\n\n| Any of these can be added and tweaked manually.\n| See \"git-config values\" section below for details on each parameter.\n\n\nGenerate encryption keys\n^^^^^^^^^^^^^^^^^^^^^^^^\n\n::\n\n  % git nerps key-gen\n\n  % tail -2 .git/config\n  [nerps \"key\"]\n    alfa = d2rmvoMBcPAcs-otYtbRH_WIIztXtg7ONcbGgzwcpQo=\n\nGenerated key with auto-picked name \"alfa\" was stored in \".git/config\", as\ndemonstrated above.\n\nIt will be used by default if it's the only key available.\n\nWith \u003e1 keys, \"key-set\" command can be used to pick which one to use for new\nfiles (and \"key-unset\" to reset that selection), otherwise first key found in\nthe config is used.\n\nDecryption uses all available keys by default.\n\nKey names get auto-picked from `phonetic alphabet`_, if not specified explicity -\ni.e. alfa, bravo, charlie, etc - a set of words designed to be fairly distinctive.\n\nKeys can also be stored in user's home directory (and selected via \"key-set\"\nwith -d/--homedir option), and these will be available for all repositories,\nbut key explicitly set as \"default\" in the current repo will take priority.\n\nExtended example (from a fresh repository)::\n\n  % git nerps key-gen\n  % git nerps key-gen\n\n  % git nerps key-gen -v\n  Generated new key 'charlie':\n    SZi85A55-RWKNFvDqTsq0T_ArANBoZw8DKEojtrLA8o=\n\n  % git nerps key-gen --homedir homer\n\n  % git nerps key-list\n  alfa [default]\n  bravo\n  charlie\n  homer\n\n  % git nerps key-set bravo\n  % git nerps key-list\n  alfa\n  bravo [default]\n  charlie\n  homer\n\n  % git nerps key-gen --set-as-default\n  % git nerps key-list\n  alfa\n  bravo\n  charlie\n  delta [default]\n  homer\n\n  % git nerps key-unset\n  % git nerps key-set --homedir homer\n  % git nerps key-list\n  alfa\n  bravo\n  charlie\n  delta\n  homer [default]\n\nIf another often-used secret - ssh private key - is already present in user's\nhomedir, it might be a good idea to derive git key from that instead.\n\nTool supports parsing such keys and deriving new ones from from them in a\nsecure and fully deterministic fashion (using PBKDF2, see \"Crypto details\"\nsection below) via --from-ssh-key option::\n\n  % git nerps key-gen -v --from-ssh-key\n  Key:\n    6ykkvuyS7gX9FpxtjGkntJFlGvk_t4oGsIJAPsy_Hn4=\n\nOption --from-ssh-key-pbkdf2-params can be used to tweak PBKDF2 parameters to\ne.g. derive several different keys from signle ssh key.\n\nThat way, while generated key will be stored in the config, it doesn't really\nhave to be preserved (e.g. can be removed with the repo or container), as it's\neasy to generate it again from the same ssh key (but be sure to keep ssh key\nsafe, if that is the case!).\n\nScripts like ssh-keyparse_ can help to reduce modern ssh keys (ed25519) to a\nshort password-like strings - similar to ones git-nerps uses - for an easy backup.\n\n.. _phonetic alphabet: https://en.wikipedia.org/wiki/NATO_phonetic_alphabet\n\n\nMark new files to be encrypted\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n::\n\n  % git ls-files\n  backup_script.sh\n\n  % cp ~/rsync_auth.txt .\n  % git nerps taint rsync_auth.txt\n  % git add rsync_auth.txt .gitattributes\n  % git commit -a -m 'Add rsync auth data'\n\n  % git ls-files\n  .gitattributes\n  backup_script.sh\n  rsync_auth.txt\n\n``git nerps taint`` will add ``/rsync_auth.txt filter=nerps diff=nerps`` line\nto \".gitattributes\" file (creating it, if necessary), so that contents of the\nfile in the repository will always be transparently encrypted.\n\nThis can be applied to files that are already in the repository, but that\ncommand will NOT rebase whole commit history to wipe or encrypt that file\nthere - this can be done manually, but might be tricky (e.g. with many branches).\n\n``git nerps taint`` also has -l/--local-only option to use\n\".git/info/attributes\" (which is not shared between repo clones)\ninstead to the same effect.\n\n``git nerps clear`` removes \"taint\" from file(s), if it's ever necessary.\n\nBoth \"taint\" and \"clear\" commands operate on gitattributes lines with patterns\nmatching repo-relative path to specified file(s), making sure that there's\nexactly one such match (see also --force and --silent options), so it's\nperfectly fine to add any valid patterns there by hand, these commands should\npick these up.\n\nNote that neither \"taint\" nor \"clear\" touch contents of actual file's in the\nlocal copy (i.e. on fs) at all - only set git attributes for future git commits.\n\n\nWipe accidentally-comitted secret from git repo\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nJust ``git rm`` on the file obviously won't get it done, as previous commits\nwill still have the file in plaintext.\n\nRebasing can wipe it from those, but one'd still be able to recover old tree via\ngit-reflog, so that has to be cleaned-up as well, and then git's\ngarbage-collection mechanism should be run to purge unlinked blobs.\n\nRemoving file(s) from **local** branches can be done like this::\n\n  % git filter-branch --index-filter \\\n    \"git rm -rf --cached --ignore-unmatch $files\" HEAD\n\n  % git filter-branch --index-filter \\\n    \"git rm -rf --cached --ignore-unmatch $files\" some-other-branch\n  ...\n\nAll combinations of branches and files should be processed by ``git\nfilter-branch`` above, including any branches that are currently present on\nremotes only (i.e. pull/filter/push -f all these as well)!\n\nBut note that local \".git\" dir will still contain these files in various caches\nand refs (think reflog).\n\nWhile it's possible to purge at least some of these with \"git reflog expire\" and\n\"git gc\" and some \"rm -rf\" commands, there is no guarantee that something won't\nremain (e.g. --textconv cache, unlinked file in objects, etc).\n\nTo get clean .git directory, cloning it anew from local or remote repo copy\nshould work.\n\nPushing rebase result to a *bare* remote repo (no local copy, as e.g. gitolite\ncreates these) might get rid of the file(s) there as well (or maybe with an\nextra ``git gc --aggressive --prune=now`` command), as those don't keep reflog\nhistory by default, but be sure to check for extra branches there and it can\nstill be unreliable and a subject to change.\n\nOne way to check for leftover secrets in the filtered/cloned repo branches can\nbe exporting it via \"git fast-export\", making sure data is not there (simple\ngrep should do it), and re-initializing both local and remote repos from that.\n\n\nEncrypt/decrypt local file\n^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nNote that this is the opposite of what \"taint\" does, where actual local file is\nnever touched, and it's only blobs in \".git\" that get encrypted.\n\nSo doesn't need to be run manually along with \"taint\" or anything like that,\njust an extra option for encrypting non-git stuff with the same key for whatever\nother purposes.\n\nThis tool is only designed to operate on small files (up to a megabyte or a few),\nfor larger files I'd suggest using gpg with assymetric keys instead.\n\n::\n\n  % echo password \u003esecret.conf\n  % git nerps encrypt secret.conf\n  % grep password secret.conf # encrypted file - no results\n\n  % git nerps encrypt secret.conf\n  % git nerps encrypt secret.conf # safe* to run multiple times\n\n  % git nerps decrypt secret.conf\n  % cat secret.conf\n  password\n\n  % git nerps decrypt secret.conf\n  % git nerps decrypt secret.conf # safe* to run on plaintext\n  % cat secret.conf\n  password\n\nOne caveat here that also makes it \"safe\" to run encrypt/decrypt multiple times\nis that both operations check \"magic\" at the start of a file and run/abort\ndepending on presence of those bytes.\n\nThis means that if file already has these weird bytes at the start (e.g. as a\nresult of some malicious tampering), \"encrypt\" won't do anything to it - see\n\"Crypto details\" section below for more info.\n\n\nConfirm that file was or will-be encrypted\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nGit does not (and probably should not) track which filters are used in which\ncommit, so only reliable way to tell if the file is encrypted in git-log or\ngit-index is by its contents.\n\nMost obvious ways to do that are:\n\n* ``git show`` and ``--no-textconv`` option.\n\n  For file from an arbitrary commit (e.g. 7b53fd0) in git history::\n\n    % git show 7b53fd0:etc/cjdroute.conf\n    ¯\\_ʻnerpsʻ_/¯ 1\n    ...binary data blob...\n\n  ``--no-textconv`` option can be added here, but should be default.\n\n  File added for commit in the working tree::\n\n    % git diff --no-textconv HEAD -- /etc/cjdroute.conf\n    diff --git a/etc/cjdroute.conf b/etc/cjdroute.conf\n    new file mode 100644\n    index 0000000..165fed5\n    Binary files /dev/null and b/etc/cjdroute.conf differ\n\n    % git show 165fed5\n    ¯\\_ʻnerpsʻ_/¯ 1\n    ...binary data blob...\n\n  Use ``diff --staged`` to see only changes that were queued via git-add.\n\n  ``git log --no-textconv`` can also be used in a similar fashion.\n\n* ``git log --stat`` / ``git diff --stat``.\n\n  Encrypted files in ``--stat`` output show up as binary blobs, which can be\n  easy enough to spot for an otherwise text files, without inspecting every file\n  with git-show.\n\n* ``git clone``.\n\n  git-clone can be used to get copy of a repo (e.g. ``git clone ~/path/to/myrepo\n  myrepo-copy``), as it is seen by someone without access to keys, where all\n  files should always be in their encrypted form.\n\n* There should probably be a git-nerps subcommand to make it easier.\n\n\n\n\nInstallation\n------------\n\nRequirements:\n\n* Python 3.6+ (dig up repo history for an old 2.7 version)\n\n* libnacl_ or PyNaCl_ python module - either one will work,\n  and they're interoperable with each other (use same libsodium),\n  so which one is used makes no difference whatsoever.\n\nBoth deps should be available in distro package repositories.\nPyNaCl/libnacl can also be installed from PyPI via pip.\n\nInstall git-nerps.py script to PATH and test if it works from there::\n\n  % install -m0755 git-nerps.py /usr/local/bin/git-nerps\n\n  % git nerps -h\n  usage: git nerps [-h] [-d] [-n key-name] [-s] ...\n  ...\n\nThat's it.\n\n\n\n\nDrawbacks, quirks and warnings\n------------------------------\n\n\n* DO NOT TRUST THIS TOOL TO BE UNIVERSALLY SECURE.\n\n  | I (author) don't use it to store data that is valuable,\n  | sensitive or can get me in trouble in any of my public git repositories.\n  | Not a single such file on my public git server or github.\n  | Think about it.\n\n  My use-case is to have shared configuration repositories, to which -\n  unless something goes wrong - there is no unsanctioned access anyway.\n\n  Protection there is from accidental leaks, scraper bots or mildly curious\n  hacker types, and it's fairly trivial to just change all secrets when/if\n  ciphertext gets into wrong hands (assuming it gets detected).\n\n  Secrets themselves are nothing valuable in my case too, just a PITA to rebuild\n  compromised stuff from scratch at most, hence this added bit of security with\n  little extra effort.\n\n  | **Your** threat model can be drastically different!!!\n  | Do not trust this tool with your life, it's not made for this at all.\n\n  And if any tool/tech/practice gets advertised as \"secure\" for everything and\n  against everything, please be first to call bullshit on that.\n\n  Plus I'm no security expert or cyptographer anyway, just a random coder, so\n  maybe don't trust me much either.\n\n\n* When encrypted with the same key, two exact copies of the same file will\n  produce exactly same ciphertext.\n\n  This is intentional for a git filter, since mixing-in info from filename is\n  kinda tricky, as it's not always available and can lead to some weird bugs\n  (e.g. \"git mv\" producing broken files), and using entirely random nonce will\n  produce spurious changes in ciphertext with no changes in plaintext.\n\n  So if it is important to not leak info about two files being identical, only\n  way with this tool is to actually make them non-identical - even one-bit\n  difference (whitespace, padding, BOM, etc) should make them unrecognizable.\n\n  It's not the same case as with \"salt\" in passwords at all though - should\n  still be impossible to bruteforce these ciphertexts without bruteforcing whole\n  symmetric cipher key, at which point one can use it to just decrypt the file.\n\n\n* As noted in `this letter by Junio C Hamano`_, it is unwise to fully encrypt\n  files that get modified all the time, as that defeats the whole purpose of git\n  (\"change\" will always be \"whole file\") and especially its attrs mechanism\n  (which is designed with almost opposite goals in mind).\n\n  In addition to the above, git isn't well suited to store binary blobs in\n  general, which encrypted files are.\n\n  But keeping only secrets encrypted, which can be e.g. separate\n  very-rarely-modified files of tiny size should be perfectly fine.\n\n\n* This tool is for secrecy, not consistency (or authentication).\n\n  While encrypted files will always be authenticated against tampering or\n  accidental corruption, use usual gpg-signed commits or keep track of history\n  hashes or such to make sure history/data in the repo is consistent with what\n  is expected.\n\n\n* If key is lost, encrypted data is useless.\n\n  git makes it easy to replicate repository history over many remotes - just\n  define a bunch of urls for \"origin\" and push.\n\n  Keep in mind that for any valuable secrets, it might be wise to keep roughly\n  same level of replication as with ciphertext itself, i.e. keep N copies of\n  keys for N copies of data, just maybe in different (more private) places.\n\n  This gets even more important consideration for git history - if any key will\n  be lost (or e.g. changed and old one discarded) in the future, everything\n  encrypted by it in the git-log will be lost forever.\n\n\n* Encryption keys are stored in \"repo/.git/config\" or \"~/.git-nerps-keys\".\n\n  It is very important to protect and NOT to loose or share/leak these files.\n\n  Be sure to keep that in mind when copying repository without \"git clone\" or\n  sharing dev copies/environments between users or machines.\n\n  Tool changes modes on \"repo/.git\" and \"repo/.git/config\" to make sure there's\n  no extra access there. Git should not mess these up, bit it might be worth to\n  keep modes on these paths in mind when messing with them.\n\n  Never allow access to \"repo/.git\" directory over http(s) - alas, fairly common\n  security issue, for many different reasons, but here especially so.\n\n\n* git caches plaintext --textconv results in local .git/objects/... files.\n\n  So even after loosing or deleting the key, it might be possible to recover cached\n  secrets from there, via ``git show --textconv`` or ``git log -u`` for example.\n\n  Hence it's unwise to ever share raw local \".git\" dir with anything, if any\n  secret was ever added or comitted there, with or without git-nerps filtering.\n\n  Clone/push/pull operations do not transfer or use these caches in any way.\n\n\n* Name of the tool literally makes no sense. NERPS.\n\n\n.. _this letter by Junio C Hamano: http://article.gmane.org/gmane.comp.version-control.git/113221\n\n\n\n\nAffected files and git-config params\n------------------------------------\n\nAll files are using git configuration formats,\nmore info on which can be found in `git-config(1)`_.\n\n\nFiles\n^^^^^\n\n* .git/config, $GIT_CONFIG or whatever git-config(1) detects.\n\n* ~/.git-nerps - symlink to the script, to be used in git configs.\n\n* ~/.git-nerps-keys - per-user git-config file for crypto keys only.\n\n\ngit-config values\n^^^^^^^^^^^^^^^^^\n\ngit splits these into sections in the config file, but flat key-value output can\nbe produced by ``git config --list`` (add ``--file /path/to/config`` for any\nrandom config path).\n\n* ``nerps.n-e-r-p-s`` - placeholder key to work around `long-standing git-config\n  bug with empty sections`_.\n\n* ``nerps.version`` - integer version of configuration, for easy (and hands-off)\n  future migrations from older ones when config format changes.\n\n* ``nerps.key.X`` - individual crypto keys, where X is the key name.\n\n* ``nerps.key-default`` - default crypto key **name** (stored as value).\n\n* ``filter.nerps.clean``\n\n  \"nerps\" filter driver command to \"clean\" files from local copy before\n  comitting them to repository, which in this case means \"encrypt\".\n\n  See `git-config(1)`_ and `gitattributes(5)`_ for more details on how these work.\n\n* ``filter.nerps.smudge``\n\n  Same as \"filter.nerps.clean\", but for decryption process when extracting file\n  from repository to a local copy.\n\n* ``diff.nerps.textconv``\n\n  Similar to \"filter.nerps.smudge\", to display \"git diff\" correctly for\n  plaintext instead of encryped blobs.\n\n  See `git-config(1)`_ and `gitattributes(5)`_ for details on\n  \"diff.\u003cdriver\u003e.textconv\".\n\n* ``diff.nerps.cachetextconv``\n\n  Related to \"diff.nerps.textconv\" - enables caching of plaintext for diff\n  purposes, which should be fine, as it's only done locally.\n\n.. _long-standing git-config bug with empty sections: http://stackoverflow.com/questions/15935624/how-do-i-avoid-empty-sections-when-removing-a-setting-from-git-config\n.. _git-config(1): https://git-scm.com/docs/git-config\n.. _gitattributes(5): https://git-scm.com/docs/gitattributes\n\n\n\n\nCrypto details\n--------------\n\n* File contents encryption.\n\n  Encryption process in pseudocode::\n\n    file_plaintext = git_input_data\n    secretbox_key, version_ascii = git_config_data\n\n    nonce_32b = HMAC(\n      key = 'nerps',\n      msg = file_plaintext,\n      digest = sha256 )\n\n    nonce = nonce_32b[:crypto_secretbox_NONCEBYTES]\n\n    ciphertext = crypto_secretbox(\n      key = secretbox_key,\n      msg = file_plaintext,\n      nonce = nonce )\n\n    magic = '¯\\_ʻnerpsʻ_/¯'\n    header = magic || ' ' || version_ascii\n\n    git_output_data = header || '\\n' || ciphertext\n\n  \"crypto_secretbox()\" corresponds to `NaCl crypto_secretbox`_ routine (with\n  libsodium/PyNaCl/libnacl wrappers), which is a combination of Salsa20 stream\n  cipher and and Poly1305 authenticatior in one easy-to-use and secure package,\n  implemented and maintained by very smart and skilled people (djb being the\n  main author).\n\n  Nonce here is derived from plaintext hash, which should exclude possibility of\n  reuse for different plaintexts, yet provide deterministic output for the same\n  file.\n\n  Note that key-id is not present in the output data, but since this is\n  authenticated encryption, it's still possible to determine which key ciphertext\n  should be decrypted with by just trying them all until authentication succeeds.\n\n  \"version_ascii\" is just \"1\" or such, encoded in there in case encryption\n  algorithm might change in the future.\n\n  Weird unicode stuff in the \"header\" is an arbitrary magic string to be able to\n  easily and kinda-reliably tell if file is encrypted by the presence of that.\n\n* Symmetric encryption key derivation from OpenSSH key.\n\n  Only used when running ``key-gen --from-ssh-key`` subcommand.\n\n  OpenSSH key gets parsed according to openssh format described in PROTOCOL.key\n  file (in OpenSSH repo), decrypting it beforehand by running \"ssh-keygen -p\" to\n  a temporary file (with a big warning when that happens, in case it's undesirable),\n  if necessary.\n\n  Once raw private key is extracted, it gets processed in the following fashion::\n\n    pbkdf2(\n      pseudo_random_func = sha256,\n      password = raw_private_key,\n      salt = '¯\\_ʻnerpsʻ_/¯',\n      iterations = 500_000,\n      derived_key_len = crypto_secretbox_KEYBYTES )\n\n  I.e. PBKDF2-SHA256 (as implemented in python's hashlib.pbkdf2_hmac) is used\n  with static salt (can be overidden via cli option) and 500k rounds (also\n  controllable via cli option), result is truncated to crypto_secretbox key\n  size.\n\n  Currently only ed25519 keys are supported, but that's mostly because I don't\n  see much reason to even allow other (mostly broken) types of keys - \"BEGIN\n  OPENSSH PRIVATE KEY\" format should be roughly same for all types of keys.\n\n\n\nLinks\n-----\n\n(from ~2015 when project was created - make sure to lookup more up-to-date tools)\n\n* `git-crypt project \u003chttps://www.agwa.name/projects/git-crypt/\u003e`__\n\n  Similar tool and a first thing I checked before writing this, probably the\n  best one around.\n\n  Crypto used there is AES-CTR with OpenSSL.\n\n  Some blog posts and notes on its usage:\n\n  * `Git Crypted \u003chttps://flatlinesecurity.com/posts/git-crypted/\u003e`__\n\n  * `Protect secret data in git repo\n    \u003chttps://coderwall.com/p/kucyaw/protect-secret-data-in-git-repo\u003e`__\n\n  * `Storing sensitive data in a git repository using git-crypt\n    \u003chttp://www.twinbit.it/en/blog/storing-sensitive-data-git-repository-using-git-crypt\u003e`__\n\n  * `HN comments on the previous post \u003chttps://news.ycombinator.com/item?id=7508734\u003e`__\n\n    These do have some useful info and feedback and comments from git-crypt\n    author himself, incl. description of some of its internals.\n\n  Decided against using it for variety of reasons - OpenSSL, not AEAD, somewhat\n  different use-case and tools for that, C++.\n\n\n* `git-encrypt \u003chttps://github.com/shadowhand/git-encrypt\u003e`__ (\"gitcrypt\" tool).\n\n  Look at \"gitcrypt\" bash script for these:\n\n  * ``DEFAULT_CIPHER=\"aes-256-ecb\"``\n\n    AES-ECB is plain insecure (and has been used as a \"doing it wrong\" example\n    for decades!!!), and there's no conceivable reason to ever use it for new\n    projects except a total lack of knowledge in the area, malice or maybe a joke.\n\n  * ``openssl enc -base64 -$CIPHER -S \"$SALT\" -k \"$PASS\"``\n\n    Yep, and every pid running in the same namespace (i.e. on the system), can\n    easily see this \"$PASS\" (e.g. run \"ps\" in a loop and you get it).\n\n  Just these two are enough to know where this project stands, but it also has\n  lacking and unusable trying-to-be-interactive interface and lot of other issues.\n\n  It's really bad.\n\n\n* `transcrypt \u003chttps://github.com/elasticdog/transcrypt\u003e`__\n\n  More competent \"simple bash wrapper\" implementation than git-encrypt above,\n  but lacking good configuration management cli IMO, e.g.::\n\n    ### Designate a File to be Encrypted\n\n    ...\n\n    $ cd \u003cpath-to-your-repo\u003e/\n    $ echo 'sensitive_file  filter=crypt diff=crypt' \u003e\u003e .gitattributes\n    $ git add .gitattributes sensitive_file\n    $ git commit -m 'Add encrypted version of a sensitive file'\n\n  Such manual changes to .gitattributes are exactly the kind of thing I'd rather\n  have the tool for, same as \"git add\" here doesn't require you to edit a few\n  configs to include new file there.\n\n  Key management is fairly easy and behind-the-scenes though, and code does\n  crypto mostly right, despite all the openssl shortcomings and with some\n  caveats (mentioned in the readme there).\n\n  Upside is that it doesn't require python or extra crytpo modules like\n  PyNaCl/libnacl - bash and openssl are available everywhere.\n\n\n* `git-remote-gcrypt \u003chttps://github.com/bluss/git-remote-gcrypt\u003e`__\n\n  Designed to do very different thing from git-crypt or this project, which is\n  to encrypt whole repository in bulk with gpg (when pushing to remote).\n\n  Probably much better choice than this project for that particular task.\n\n\n* `ejson \u003chttps://github.com/Shopify/ejson\u003e`__,\n  `jaeger \u003chttps://github.com/jyap808/jaeger\u003e`__ and such.\n\n  There's plenty of \"encrypt values in JSON\" tools, not really related to git,\n  but can be (and generally are) used for secrets in JSON configurations shared\n  between different machines/containers.\n\n\n* `ssh-keyparse \u003chttps://github.com/mk-fg/fgtk/#ssh-keyparse\u003e`_ script to\n  convert ed25519 ssh keys to short strings (with just 32 bytes in them).\n\n\n* `gitattributes(5) manpage \u003chttps://git-scm.com/docs/gitattributes\u003e`__\n\n\n* `Some other git filters that I use \u003chttps://github.com/mk-fg/fgtk/#dev\u003e`__\n\n\n\nTODO\n----\n\n* Taints for parts of file(s).\n\n* Change key used for tainted file(s).\n\n  Just re-comitting these should be enough, as old contents will be decrypted\n  with the old key and new ones encrypted with new one.\n\n* Command to find all encrypted files in local copy and auto-setup attrs.\n\n* Command to show if stuff is/was/will-be encrypted.\n\n* Address errors from e.g. git-show for commits in different-key branches,\n  or maybe just make these look nicer.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmk-fg%2Fgit-nerps","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmk-fg%2Fgit-nerps","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmk-fg%2Fgit-nerps/lists"}