{"id":13441678,"url":"https://github.com/elasticdog/transcrypt","last_synced_at":"2025-05-14T02:08:10.998Z","repository":{"id":13938578,"uuid":"16638318","full_name":"elasticdog/transcrypt","owner":"elasticdog","description":"transparently encrypt files within a git repository","archived":false,"fork":false,"pushed_at":"2025-05-07T11:30:39.000Z","size":644,"stargazers_count":1539,"open_issues_count":29,"forks_count":106,"subscribers_count":20,"default_branch":"main","last_synced_at":"2025-05-13T01:55:28.511Z","etag":null,"topics":["encryption","git","gitattributes","secrets","shell"],"latest_commit_sha":null,"homepage":null,"language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/elasticdog.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","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,"zenodo":null}},"created_at":"2014-02-08T07:18:33.000Z","updated_at":"2025-05-11T10:27:17.000Z","dependencies_parsed_at":"2023-11-27T14:25:52.603Z","dependency_job_id":"43c88a01-55a3-45e7-931a-2225b6ff54f5","html_url":"https://github.com/elasticdog/transcrypt","commit_stats":{"total_commits":247,"total_committers":19,"mean_commits":13.0,"dds":0.4736842105263158,"last_synced_commit":"016b2e4b31951be5ea96233d8d2badef9c9836b6"},"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elasticdog%2Ftranscrypt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elasticdog%2Ftranscrypt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elasticdog%2Ftranscrypt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elasticdog%2Ftranscrypt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/elasticdog","download_url":"https://codeload.github.com/elasticdog/transcrypt/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254052962,"owners_count":22006717,"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":["encryption","git","gitattributes","secrets","shell"],"created_at":"2024-07-31T03:01:36.831Z","updated_at":"2025-05-14T02:08:05.979Z","avatar_url":"https://github.com/elasticdog.png","language":"Shell","readme":"# transcrypt\n\nA script to configure transparent encryption of sensitive files stored in a Git\nrepository. Files that you choose will be automatically encrypted when you\ncommit them, and automatically decrypted when you check them out. The process\nwill degrade gracefully, so even people without your encryption password can\nsafely commit changes to the repository's non-encrypted files.\n\ntranscrypt protects your data when it's pushed to remotes that you may not\ndirectly control (e.g., GitHub, Dropbox clones, etc.), while still allowing you\nto work normally on your local working copy. You can conveniently store things\nlike passwords and private keys within your repository and not have to share\nthem with your entire team or complicate your workflow.\n\n![Tests](https://github.com/elasticdog/transcrypt/workflows/Tests/badge.svg)\n\n## Overview\n\ntranscrypt is in the same vein as existing projects like\n[git-crypt](https://github.com/AGWA/git-crypt) and\n[git-encrypt](https://github.com/shadowhand/git-encrypt), which follow Git's\ndocumentation regarding the use of clean/smudge filters for encryption. In\ncomparison to those other projects, transcrypt makes substantial improvements in\nthe areas of usability and safety.\n\n- transcrypt is just a Bash script and does not require compilation\n- transcrypt uses OpenSSL's symmetric cipher routines rather than implementing\n  its own crypto\n- transcrypt does not have to remain installed after the initial repository\n  configuration\n- transcrypt generates a unique salt for each encrypted file\n- transcrypt uses safety checks to avoid clobbering or duplicating configuration\n  data\n- transcrypt facilitates setting up additional clones as well as rekeying\n- transcrypt adds an alias `git ls-crypt` to list all encrypted files\n\n### Salt Generation\n\nThe _decryption -\u003e encryption_ process on an unchanged file must be\ndeterministic for everything to work transparently. To do that, the same salt\nmust be used each time we encrypt the same file. Rather than use a static salt\ncommon to all files, transcrypt first has OpenSSL generate an HMAC-SHA256\ncryptographic hash-based message authentication code for each decrypted file\n(keyed with a combination of the filename and transcrypt password), and then\nuses the last 16 bytes of that HMAC for the file's unique salt. When the content\nof the file changes, so does the salt. Since an\n[HMAC has been proven to be a PRF](https://web.archive.org/web/20090706011828/cseweb.ucsd.edu/~mihir/papers/hmac-new.html),\nthis method of salt selection does not leak information about the original\ncontents, but is still deterministic.\n\n## Usage\n\nThe requirements to run transcrypt are minimal:\n\n- Bash\n- Git\n- OpenSSL\n- `column` and `hexdump` commands (on Ubuntu/Debian install `bsdmainutils`)\n- if using OpenSSL 3+ one of: `xxd` (on Ubuntu/Debian is included with `vim`)\n  or `printf` command (with %b directive) or `perl`\n\n...and optionally:\n\n- GnuPG - for secure configuration import/export\n\nYou also need access to the _transcrypt_ script itself. You can add it directly\nto your repository, or just put it somewhere in your \\$PATH:\n\n    $ git clone https://github.com/elasticdog/transcrypt.git\n    $ cd transcrypt/\n    $ sudo ln -s ${PWD}/transcrypt /usr/local/bin/transcrypt\n\n#### Installation via Packages\n\nA number of packages are available for installing transcrypt directly on your\nsystem via its native package manager. Some of these packages also include man\npage documentation as well as shell auto-completion scripts.\n\n- Arch Linux\n- Heroku (via [Buildpacks](https://devcenter.heroku.com/articles/buildpacks))\n- NixOS\n- OS X (via [Homebrew](http://brew.sh/))\n\n...see the [INSTALL document](INSTALL.md) for more details.\n\n### Initialize an Unconfigured Repository\n\ntranscrypt will interactively prompt you for the required information, all you\nhave to do run the script within a Git repository:\n\n    $ cd \u003cpath-to-your-repo\u003e/\n    $ transcrypt\n\nIf you already know the values you want to use, you can specify them directly\nusing the command line options. Run `transcrypt --help` for more details.\n\n### Designate a File to be Encrypted\n\nOnce a repository has been configured with transcrypt, you can designate for\nfiles to be encrypted by applying the \"crypt\" filter, diff, and merge to a\n[pattern](https://www.kernel.org/pub/software/scm/git/docs/gitignore.html#_pattern_format)\nin the top-level _[.gitattributes](http://git-scm.com/docs/gitattributes)_\nconfig. If that pattern matches a file in your repository, the file will be\ntransparently encrypted once you stage and commit it:\n\n    $ cd \u003cpath-to-your-repo\u003e/\n    $ transcrypt --add sensitive_file\n    $ git add .gitattributes sensitive_file\n    $ git commit -m 'Add encrypted version of a sensitive file'\n\nThe _.gitattributes_ file should be committed and tracked along with everything\nelse in your repository so clones will be aware of what is encrypted. Make sure\nyou don't accidentally add a pattern that would encrypt this file :-)\n\n\u003e For your reference, if you find the above description confusing, you'll find\n\u003e that this repository has been configured following these exact steps.\n\n### Listing the Currently Encrypted Files\n\nFor convenience, transcrypt also adds a Git alias to allow you to list all of\nthe currently encrypted files in a repository:\n\n    $ git ls-crypt\n    sensitive_file\n\nAlternatively, you can use the `--list` command line option:\n\n    $ transcrypt --list\n    sensitive_file\n\nYou can also use this to verify your _.gitattributes_ patterns when designating\nnew files to be encrypted, as the alias will list pattern matches as long as\neverything has been staged (via `git add`).\n\nAfter committing things, but before you push to a remote repository, you can\nvalidate that files are encrypted as expected by viewing them in their raw form:\n\n    $ git show HEAD:\u003cpath-to-file\u003e --no-textconv\n\nThe `\u003cpath-to-file\u003e` in the above command must be relative to the _top-level_ of\nthe repository. Alternatively, you can use the `--show-raw` command line option\nand provide a path relative to your current directory:\n\n    $ transcrypt --show-raw sensitive_file\n\n### Initialize a Clone of a Configured Repository\n\nIf you have just cloned a repository containing files that are encrypted, you'll\nwant to configure transcrypt with the same cipher and password as the origin\nrepository. The owner of the origin repository can dump the credentials for you\nby running the `--display` command line option:\n\n    $ transcrypt --display\n    The current repository was configured using transcrypt v0.2.0\n    and has the following configuration:\n\n      CONTEXT:  default\n      CIPHER:   aes-256-cbc\n      PASSWORD: correct horse battery staple\n\n    Copy and paste the following command to initialize a cloned repository:\n\n      transcrypt -c aes-256-cbc -p 'correct horse battery staple'\n\nOnce transcrypt has stored the matching credentials, it will force a checkout of\nany exising encrypted files in order to decrypt them.\n\n### Rekeying\n\nPeriodically, you may want to change the encryption cipher or password used to\nencrypt the files in your repository. You can do that easily with transcrypt's\nrekey option:\n\n    $ transcrypt --rekey\n\n\u003e As a warning, rekeying will remove your ability to see historical diffs of the\n\u003e encrypted files in plain text. Changes made with the new key will still be\n\u003e visible, and you can always see the historical diffs in encrypted form by\n\u003e disabling the text conversion filters:\n\u003e\n\u003e     $ git log --patch --no-textconv\n\nAfter rekeying, all clones of your repository should flush their transcrypt\ncredentials, fetch and merge the new encrypted files via Git, and then\nre-configure transcrypt with the new credentials.\n\n    $ transcrypt --flush-credentials\n    $ git fetch origin\n    $ git merge origin/main\n    $ transcrypt -c aes-256-cbc -p 'the-new-password'\n\n### Command Line Options\n\nCompletion scripts for both Bash and Zsh are included in the _contrib/_\ndirectory.\n\n    transcrypt [option...]\n\n      -c, --cipher=CIPHER\n             the symmetric cipher to utilize for encryption;\n             defaults to aes-256-cbc\n\n      -p, --password=PASSWORD\n             the password to derive the key from;\n             defaults to 30 random base64 characters\n\n      --set-openssl-path=PATH_TO_OPENSSL\n             use OpenSSL at this path; defaults to 'openssl' in $PATH\n\n      -y, --yes\n             assume yes and accept defaults for non-specified options\n\n      --add, --add=pattern\n             add a file pattern to encrypt to the .gitattributes file\n\n      -d, --display\n             display the current repository's cipher and password\n\n      -r, --rekey\n             re-encrypt all encrypted files using new credentials\n\n      -f, --flush-credentials\n             remove the locally cached encryption credentials and  re-encrypt\n             any files that had been previously decrypted\n\n      -F, --force\n             ignore whether the git directory is clean, proceed with the\n             possibility that uncommitted changes are overwritten\n\n      -u, --uninstall\n             remove  all  transcrypt  configuration  from  the repository and\n             leave files in the current working copy decrypted\n\n       --upgrade\n             uninstall and re-install transcrypt configuration in the repository\n             to apply the newest scripts and .gitattributes configuration\n\n      -l, --list\n             list all of the transparently encrypted files in the repository,\n             relative to the top-level directory\n\n      -s, --show-raw=FILE\n             show  the  raw file as stored in the git commit object; use this\n             to check if files are encrypted as expected\n\n      -e, --export-gpg=RECIPIENT\n             export  the  repository's cipher and password to a file encrypted\n             for a gpg recipient\n\n      -i, --import-gpg=FILE\n             import the password and cipher from a gpg encrypted file\n\n      -C, --context=CONTEXT_NAME\n             name for a context  with a different passphrase  and cipher from\n             the  'default' context;   use this  advanced option  to  encrypt\n             different files with different passphrases\n\n      --list-contexts\n             list all contexts configured in the  repository,  and warn about\n             incompletely configured contexts\n\n      -v, --version\n             print the version information\n\n      -h, --help\n             view this help message\n\n## Caveats\n\n### Overhead\n\nThe method of using filters to selectively encrypt/decrypt files does add some\noverhead to Git by regularly forking OpenSSL processes and removing Git's\nability to efficiently cache file changes. That said, it's not too different\nfrom tracking binary files, and when used as intended, transcrypt should not\nnoticeably impact performance. There are much better options if your goal is to\nencrypt the entire repository.\n\n### Localhost\n\nNote that the configuration and encryption information is stored in plain text\nwithin the repository's _.git/config_ file. This prevents them from being\ntransferred to remote clones, but they are not protected from inquisitive users\non your local machine.\n\nFor safety, you may prefer to only have the credentials stored when actually\nupdating encrypted files, and then flush them with `--flush-credentials` once\nyou're done (make sure you have the credentials backed up elsewhere!). This will\nalso revert any decrypted files back to their encrypted form in your local\nworking copy.\n\n### Cipher Selection\n\nLast up, regarding the default cipher choice of `aes-256-cbc`...there aren't any\nfantastic alternatives without pulling in outside dependencies. Ideally, we\nwould use an authenticated cipher mode like `id-aes256-GCM` by default, but\nthere are a couple of issues:\n\n1. I'd like to support OS X out of the box, and unfortunately they are the\n   lowest common denominator when it comes to OpenSSL. For whatever reason, they\n   still include OpenSSL 0.9.8y rather than a newer release. Unfortunately,\n   GCM-based ciphers weren't added until OpenSSL 1.0.1 (back in early 2012).\n\n2. Even with newer versions of OpenSSL, the authenticated cipher modes\n   [don't work exactly right](http://openssl.6102.n7.nabble.com/id-aes256-GCM-command-line-encrypt-decrypt-fail-td27187.html)\n   when utilizing the command line `openssl enc`.\n\nI'm contemplating if transcrypt should append an HMAC to the `aes-256-cbc`\nciphertext to provide authentication, or if we should live with the\n[malleability issues](http://www.jakoblell.com/blog/2013/12/22/practical-malleability-attack-against-cbc-encrypted-luks-partitions/)\nas a known limitation. Essentially, malicious comitters without the transcrypt\npassword could potentially manipulate the plaintext in limited ways (given that\nthe attacker knows the original plaintext). Honestly, I'm not sure if the added\ncomplexity here would be worth it given transcrypt's use case.\n\n## Advanced\n\n### Contexts\n\nContext names let you encrypt some files with different passwords for a\ndifferent audience, such as super-users. The 'default' context applies unless\nyou set a context name.\n\nAdd a context by reinitialising transcrypt with a context name then add a\npattern with crypt-\u003cCONTEXT*NAME\u003e attributes to *.gitattributes*. For example,\nto encrypt a file \\_top-secret* in a \"super\" context:\n\n    # Initialise a new \"super\" context, and set a different password\n    $ transcrypt --context=super\n\n    # Add a pattern to .gitattributes with \"crypt-super\" values\n    $ transcrypt --context=super --add=top-secret\n\n    # Add and commit your top-secret and .gitattribute files\n    $ git add .gitattributes top-secret\n    $ git commit -m \"Add top secret file for super-users only\"\n\n    # List all contexts\n    $ transcrypt --list-contexts\n\n    # Display the cipher and password for the \"super\" context\n    $ transcrypt --context=super --display\n\n## License\n\ntranscrypt is provided under the terms of the\n[MIT License](https://en.wikipedia.org/wiki/MIT_License).\n\nCopyright \u0026copy; 2019-2025, James Murty \u003cmailto:james@murty.co\u003e.  \nCopyright \u0026copy; 2014-2020, [Aaron Bull Schaefer](mailto:aaron@elasticdog.com).\n\n## Contributing\n\n### Linting and formatting\n\nPlease use:\n\n- the [shellcheck](https://www.shellcheck.net) tool to check for subtle bash\n  scripting errors in the _transcrypt_ file, and apply the recommendations when\n  possible. E.g: `shellcheck transcrypt`\n- the [shfmt](https://github.com/mvdan/sh) tool to apply consistent formatting\n  to the _transcrypt_ file, e.g: `shfmt -w transcrypt`\n- the [Prettier](https://prettier.io) tool to apply consistent formatting to the\n  _README.md_ file, e.g: `prettier --write README.md`\n\n### Tests\n\nTests are written using [bats-core](https://github.com/bats-core/bats-core)\nversion of \"Bash Automated Testing System\" and stored in the _tests/_ directory.\n\nTo run the tests:\n\n- [install bats-core](https://github.com/bats-core/bats-core#installation)\n- run all tests with: `bats tests/`\n- run an individual test with e.g: `bats tests/test_crypt.bats`\n","funding_links":[],"categories":["HarmonyOS","Secret Management","Shell","shell","Encrypted Storage"],"sub_categories":["Windows Manager"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felasticdog%2Ftranscrypt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Felasticdog%2Ftranscrypt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felasticdog%2Ftranscrypt/lists"}