gosecret
This repository provides the gosecret
package for encrypting and decrypting all or part of a []byte
using AES-256-GCM. gosecret was written to work with tools such as git2consul, fsconsul, and envconsul, providing a mechanism for storing and moving secure secrets around the network and decrypting them on target systems via a previously installed key.
Details on the Galois/Counter Mode algorithm can be found here.
Installation
Pre-compiled builds can be directly downloaded from Bintray.
Optionally, gosecret can be built and installed from source by cloning the repository and executing go install
, which will install both the gosecret
CLI to $GOPATH/bin
and github.com/cimpress-mcp/gosecret/api
to $GOPATH/pkg
.
Using the native template system
Gosecret supports using native template tags. The tag format is different from the one previously used by gosecret, which is currently deprecated and will be removed in the next major release.
Encrypting and decrypting keys require appropriate tags. In the case of encryption, gosecret will turn all goEncrypt
tags to goDecrypt
tags. Running gosecret in decryption mode will turn goDecrypt
tags into plaintext data. Please note that quotes will need to be escaped if they are part of the plaintext.
The goEncrypt tag
{{goEncrypt "Auth data" "Plaintext" "Key name"}}
To encrypt:
$ ./gosecret -mode encrypt -keystore ./test_keys -key myteamkey-2014-09-19 ./test_data/template/config.json
{
"dbpassword" : "{{goDecrypt "MySql Password" "LcKxOXJa2qx1Riof0tLKzXvKW93ukxgOOBhspoc=" "fpY9FRvJ+8Z7ko6M" "myteamkey-2014-09-19"}}"
}
The goDecrypt tag
{{goDecrypt "Auth data" "Cipher text" "Initialization vector" "Key name"}}
To decrypt:
$ ./gosecret -mode decrypt -keystore ./test_keys ./test_data/template/encrypted.json
{
"dbpassword" : "kadjf454nkklz"
}
Key generation
To generate a AES-256 key:
gosecret -mode keygen ./test_keys/myteamkey-2014-09-19
Documentation (deprecated)
Caveats
- Security in gosecret is predicated upon the security of the target machines. gosecret uses symmetric encryption, so any user with access to the key can decrypt all secrets encrypted with that key.
- gosecret is built on the assumption that only part of any given file should be encrypted: in most configuration files, there are few fields that need to be encrypted and the rest can safely be left as plaintext. gosecret can be used in a mode where the entire file is a single encrypted tag, but you should examine whether there's a good reason to do so.
How It Works
Imagine that you have a file called config.json
, and this file contains some secure data, such as DB connection strings, but that most data can be world readable. You would use gosecret
to encrypt the private fields with a specific key. You can then check that version of config.json
into git and move it around the network using git2consul
. fsconsul
will detect the encrypted portion of the file and automatically decrypt it provided that the encryption key is present on the target machine.
To signify that you wish a portion of a file to be encrypted, you need to denote that portion of the file with a tag. Imagine that your file contains this bit of JSON:
{ 'dbpassword': 'kadjf454nkklz' }
To have gosecret encrypt just the password, you might create a tag like this:
{ 'dbpassword': '[gosecret|my mongo db password|kadjf454nkklz]' }
The components of the tag are, in order:
- The gosecret header
- An auth data string. Note that this can be any string (as long as it doesn't contain the pipe character,
|
). This tag is hashed and included as part of the ciphertext. It's helpful if this tag has some semantic meaning describing the encrypted data.
- The plaintext we wish to encrypt.
With this tag in place, you can encrypt the file via the gosecret
executable. The result will yield something that looks like this, assuming you encrypted it with a keyfile named myteamkey-2014-09-19
:
{ 'dbpassword': '[gosecret|my mongo db password|TtRotEctptR1LfA5tSn3kAtzjyWjAp+dMOHe6lc=|FJA7qz+dUdubwv9G|myteamkey-2014-09-19]' }
The components of the tag are, in order:
- The gosecret header
- The auth data string
- The ciphertext, in Base64
- The initialization vector, in Base64
- The key name
When this is decrypted by a system that contains key myteamkey-2014-09-19
, the key and initialization vector are used to both authenticate the auth data string and (if authentic) decrypt the ciphertext back to plaintext. This will result in the encrypted tag being replaced by the plaintext, returning us to our original form:
{ 'dbpassword': 'kadjf454nkklz' }
Note that the auth data string is not private data. It is hashed and used as part of the ciphertext such that decryption will fail if any of auth data, initialization vector, and key are incorrect for a specific piece of ciphertext. This increases the security of the encryption algorithm by obviating attacks that seek to learn about the key and initialization vector through repeated decryption attempts.
The CLI
gosecret
supports 3 modes of operation: keygen
, encrypt
, and decrypt
.
keygen
gosecret -mode=keygen path/to/keyfile
The above command will generate a new AES-256 key and store it, Base64 encoded, in path/to/keyfile
encrypt
gosecret -mode=encrypt -keystore=path/to/keystore -key=name_of_keyfile path/to/plaintext_file
The above command will encrypt any unencrypted tags in path/to/plaintext_file
using the key stored at path/to/keyfile
. The encrypted file is printed to stdout.
decrypt
gosecret -mode=decrypt -keystore=path/to/keystore path/to/encrypted_file
The above command will decrypt any encrypted tags in path/to/encrypted_file
, using the directory path/to/keystore
as the home for any key named in an encrypted tag. The decrypted file is printed to stdout.
Notes
Deprecation notice: Old templating system is deprecated and will be removed in future versions of gosecret.
Builds are automatically ran by Travis on any push or pull request.
Tagged builds are automatically published to bintray for OS X, Linux, and Windows.
Licensed under Apache 2.0