Hydan
Hydan is a command-line utility for encrypting and decrypting text and/or files. In addition to local crypto operations, Hydan can also defer to Amazon KMS for symmetric master keys. S3 uploads/downloads are also supported, and can leverage KMS for encryption/decryption.
TODO:
- [ ] Support multi-part uploads for S3
- [ ] Support SSE for S3 uploads
Installation
Add this line to your application's Gemfile:
gem 'hydan'
And then execute:
$ bundle
Or install it yourself as:
$ gem install hydan
Disclaimer
Hydan is open-source software - USE AT YOUR OWN RISK! The authors and all affiliates assume no responsibility for issues encountered with the use of of this software.
Usage
Local text encryption
Local text encryption returns a JSON object containing the cihpertext and randomly-generated data key. Plaintext can be piped into STDIN or passed on the CLI via the --text
flag.
# We'll grab 256 random bits for the master key
KEY=$(head -c 32 /dev/urandom | base64)
echo 'A secret on STDIN' | hydan encrypt --master-key $KEY
{
"ciphertext": {
"v": 1,
"adata": "",
"ks": 256,
"ct": "8VmGeR6+rtznK6Lu8vmr99PFmbxfu6FcyzWyiU17",
"ts": 96,
"mode": "gcm",
"cipher": "aes",
"iter": 100000,
"iv": "8Pj1RuenaRqV5BRc",
"salt": "mXfzMTw89lE="
},
"data_key": "eyJ2IjoxLCJhZGF0YSI6IiIsImtzIjoyNTYsImN0IjoiVlVDclRLUTV2WVpBMGFuTW9NTUQzWS9OQ0NYUkF0SWFpc3JYcFI1THVraHptUE1WeTVqRzBsbFJsM1k9IiwidHMiOjk2LCJtb2RlIjoiZ2NtIiwiY2lwaGVyIjoiYWVzIiwiaXRlciI6MTAwMDAwLCJpdiI6ImRUeTBPVUt2a3plaThkdnEiLCJzYWx0Ijoib1BQTXF2U1ZCN2c9In0="
}
Local decryption
KEY=$(head -c 32 /dev/urandom | base64)
echo 'The Krabby Patty secret recipe IS...' | hydan encrypt --master-key $KEY | hydan decrypt --master-key $KEY
The Krabby Patty secret recipe IS...
hydan encrypt --master-key $KEY --text 'This also works' | hydan decrypt --master-key $KEY
This also works
Env files
A common use case (actually, the reason that this utility was even written) for setting up credentials is through environment variables. To accomodate this, hydan
supports --env-formatted
text input. When this flag is passed in, K/V pairs are parsed from each line, and the value (V) is encrypted. This allows for a file to be partially encrypted in a way that hides sensitive information, while still allowing an administrator or operator to understand what the file is for.
KEY=$(head -c 32 /dev/urandom | base64)
cat test.env
FOO=bar
BAR=baz
BAZ=bat
A=B
ENV=ENV
K=V
hydan encrypt --env-formatted --master-key $KEY < test.env
FOO={"ciphertext":{"v":1,"adata":"","ks":256,"ct":"fnu8Ulyr5JLQArNp5rLz","ts":96,"mode":"gcm","cipher":"aes","iter":100000,"iv":"MOZzAZ/9qtHMCr/t","salt":"37WkVaQQxDA="},"data_key":"eyJ2IjoxLCJhZGF0YSI6IiIsImtzIjoyNTYsImN0IjoiMjFjZ21kM21PbUxBL20xdUt1bDJHNXV5VUhkaXFLQlZhSGlCQ2NzVnczbG5mUnY0Y05SSHRRMFFWVUE9IiwidHMiOjk2LCJtb2RlIjoiZ2NtIiwiY2lwaGVyIjoiYWVzIiwiaXRlciI6MTAwMDAwLCJpdiI6IkNRSkNJanlKVW9pR0kzbHQiLCJzYWx0IjoibS94a2trSm85Nzg9In0="}
BAR={"ciphertext":{"v":1,"adata":"","ks":256,"ct":"F9oTm34xCj5Ke68hB+rL","ts":96,"mode":"gcm","cipher":"aes","iter":100000,"iv":"uXP2BC9wyCyJiFy6","salt":"DLDWXIxsbv8="},"data_key":"eyJ2IjoxLCJhZGF0YSI6IiIsImtzIjoyNTYsImN0IjoiYWRRdC9reFQzS2FwSG9FWFlzclJ6bmhqdlcxYVVGdWtQd0xRZXJZTUdTMDF0WFY1RSsyRkRBZndndDA9IiwidHMiOjk2LCJtb2RlIjoiZ2NtIiwiY2lwaGVyIjoiYWVzIiwiaXRlciI6MTAwMDAwLCJpdiI6Ii9SbnFWWkZTR0EwQkw0UEEiLCJzYWx0IjoiSHYxeEd0eTZLcTQ9In0="}
BAZ={"ciphertext":{"v":1,"adata":"","ks":256,"ct":"VZ3qtRrRYVRIhJ3qIyku","ts":96,"mode":"gcm","cipher":"aes","iter":100000,"iv":"Ib19BVMCP3VqoeQ+","salt":"9DRsMkbtRvo="},"data_key":"eyJ2IjoxLCJhZGF0YSI6IiIsImtzIjoyNTYsImN0IjoieDcrdklNazBCYThnbWlMMGZ3WHE0TGpMVkNUYVBjaFhZWDFSUUkrL2oraGlBR2V0b3BxS0w2ZG5CbUU9IiwidHMiOjk2LCJtb2RlIjoiZ2NtIiwiY2lwaGVyIjoiYWVzIiwiaXRlciI6MTAwMDAwLCJpdiI6IkgzTXlEcXB4SXUrMGNoVTgiLCJzYWx0IjoiN0RSYzZmWkZWcFE9In0="}
A={"ciphertext":{"v":1,"adata":"","ks":256,"ct":"6Hqk69PLuImnpTWSjw==","ts":96,"mode":"gcm","cipher":"aes","iter":100000,"iv":"oy5lea/k99nsZz8/","salt":"yYrMK6MbXfQ="},"data_key":"eyJ2IjoxLCJhZGF0YSI6IiIsImtzIjoyNTYsImN0IjoiN3gySUZIZmk2NjB6VnpqWDd4MjJqTUlHeXdZclRuY3E1cGdOcHU1RTB2R2I3MWMvbVp3ZjR0cUxtSk09IiwidHMiOjk2LCJtb2RlIjoiZ2NtIiwiY2lwaGVyIjoiYWVzIiwiaXRlciI6MTAwMDAwLCJpdiI6IkJ1a1lBRGJhaHVvcDJuM2YiLCJzYWx0IjoiKzhVOWhiaUtCRmc9In0="}
ENV={"ciphertext":{"v":1,"adata":"","ks":256,"ct":"FQfnNaMl936fhZo3Ykrx","ts":96,"mode":"gcm","cipher":"aes","iter":100000,"iv":"12QqZqCxkvMbagzo","salt":"A3YypAcXUIQ="},"data_key":"eyJ2IjoxLCJhZGF0YSI6IiIsImtzIjoyNTYsImN0IjoiL2xpM0NnaG5BUmJCM3NmMlA5aTNLRXd3eFBITk9HQVFTdFBzVHFWUXRIZGRBRHNOL0wzV1Jrc3dIbGM9IiwidHMiOjk2LCJtb2RlIjoiZ2NtIiwiY2lwaGVyIjoiYWVzIiwiaXRlciI6MTAwMDAwLCJpdiI6ImFEK1dIZEwwWnlzbmJ5d0QiLCJzYWx0IjoiZ3hlL3dYVU9GRmM9In0="}
K={"ciphertext":{"v":1,"adata":"","ks":256,"ct":"wpSRhDud1zqxhlvqdQ==","ts":96,"mode":"gcm","cipher":"aes","iter":100000,"iv":"9WnyuuOx2q6J/KCR","salt":"kZNxqsQE8o0="},"data_key":"eyJ2IjoxLCJhZGF0YSI6IiIsImtzIjoyNTYsImN0IjoiWHpsSWEzZEVoeWNHQ0lDQTJvU2xZem93SFZUeU1CVGUyb1dwNkVZcm9JamR4azg4SnVXci9USlIxaUE9IiwidHMiOjk2LCJtb2RlIjoiZ2NtIiwiY2lwaGVyIjoiYWVzIiwiaXRlciI6MTAwMDAwLCJpdiI6IkUxdGNNT0E0YkpBSzlEdGMiLCJzYWx0IjoibzRZcjQ5U3NhVU09In0="}
# --env-formatted plays nicely with pipes too
hydan encrypt --env-formatted --master-key $KEY < test.env | hydan decrypt --env-formatted --master-key $KEY
FOO=bar
BAR=baz
BAZ=bat
A=B
ENV=ENV
K=V
# This can easily be used to construct export statements to be evaluated via eval
hydan encrypt --env-formatted --master-key $KEY < test.env | hydan decrypt --env-formatted --master-key $KEY | awk '{ print "export " $1 }'
export FOO=bar
export BAR=baz
export BAZ=bat
export A=B
export ENV=ENV
export K=V
Large files
When files are too large to read into memory, use the --in
and --out
flags. This will prompt hydan
to use logic that reads and encrypts the file line-by-line, as opposed to "slurping" the file beforehand. This also implies that it's not worth Base64 encoding the encrypted output, since it will also be large. Because of this, encryption that uses the --in
flag saves it's output in binary instead of Base64.
# Make a huge file
mkfile -n 10g ~/Desktop/LargeTestFile
hydan encrypt --in ~/Desktop/LargeTestFile --out ~/Desktop/LargeTestFile.bin --master-key $KEY
Data key (Base64): U2FsdGVkX18NG/y8sEFGyop79njj0R9omH+/UZ3Ijy1c8nYACE2UQt1NMvSL2Rh9GH4p+TSEZxSMqqWqzg7/Kw==
# We use the encrypted data key generated by the program in order to decrypt the file
# If `--key-out` is specified, the key will be saved to the supplied path instead of
# being printed to STDOUT.
hydan decrypt --in ~/Desktop/LargeTestFile.bin --out ~/Desktop/LargeTestFile.decrypted --master-key $KEY --data-key U2FsdGVkX18NG/y8sEFGyop79njj0R9omH+/UZ3Ijy1c8nYACE2UQt1NMvSL2Rh9GH4p+TSEZxSMqqWqzg7/Kw==
# Original
shasum -a 256 ~/Desktop/LargeTestFile
732377e7f4a2abdc13ddfa1eb4c9c497fd2a2b294674d056cf51581b47dd586d /Users/roberto/Desktop/LargeTestFile
# Decrypted
shasum -a 256 ~/Desktop/LargeTestFile.decrypted
732377e7f4a2abdc13ddfa1eb4c9c497fd2a2b294674d056cf51581b47dd586d /Users/roberto/Desktop/LargeTestFile.decrypted
Development
After checking out the repo, run bin/setup
to install dependencies. Then, run rake test
to run the tests. You can also run bin/console
for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install
. To release a new version, update the version number in version.rb
, and then run bundle exec rake release
, which will create a git tag for the version, push git commits and tags, and push the .gem
file to rubygems.org.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/hydan.
License
The gem is available as open source under the terms of the MIT License.