Crates.io | aws_kms_crypt |
lib.rs | aws_kms_crypt |
version | 0.1.0 |
source | src |
created_at | 2018-03-03 12:30:22.230533 |
updated_at | 2018-03-03 12:30:22.230533 |
description | Library for encrypting and decrypting secrets within the AWS ecosystem. |
homepage | |
repository | https://github.com/sjakthol/aws-kms-crypt |
max_upload_size | |
id | 53572 |
size | 13,548 |
Library for encrypting and decrypting secrets within the AWS ecosystem.
curl -LO https://raw.githubusercontent.com/sjakthol/aws-kms-crypt/master/shell/aws-kms-crypt.sh && chmod +x aws-kms-crypt.sh
npm install aws-kms-crypt
pip install aws-kms-crypt
In cargo.toml
[dependencies]
aws_kms_crypt = "0.1.0"
All implementations require access to AWS credentials.
When encrypting data, the credentials must allow the following actions:
kms:GenerateDataKey
kms:GenerateRandom
When decrypting data, the credentials must allow the following actions:
kms:Decrypt
In both cases, the access can (and should in the case of kms:Decrypt
) be
further limited with IAM policy conditions (see here
for details).
The shell script at shell/aws-kms-crypt.sh
provides an interface for shell
scripts to encrypt and decrypt data. The script needs the following commands /
tools to function:
aws
base64
cut
jq
od
openssl
sed
# No encryption context
echo -n "secretp4ssw0rd!" | ./aws-kms-crypt.sh encrypt --kms-key-id alias/common > encrypted-plan.json
# With encryption context
echo -n "secretp4ssw0rd!" | ./aws-kms-crypt.sh encrypt --kms-key-id alias/common --encryption-context type=plan,entity=admins > encrypted-plan.json
$ cat encrypted-plan.json | ./aws-kms-crypt.sh decrypt
secretp4ssw0rd!
The nodejs
directory contains a Node package that implements the KMS based encryption
and decryption functionality.
A recent version of Node (>= 4) is required.
Use the encrypt()
function of the module to encrypt any stringified data:
const kmscrypt = require('aws-kms-crypt')
kmscrypt.encrypt('secretp4ssw0rd!', {
key: 'alias/common', // Change your key here
region: 'eu-west-1', // AWS SDK needs to know this
encryptionContext: { purpose: 'automation' } // optional, can be left out
}, function (err, result) {
if (err) {
return console.log('Encryption failed:', err)
}
console.log(JSON.stringify(result, null, 2))
// Console output:
// {
// "EncryptedData": "DPQ0OZ8auGY6ohQb/pypAHJTAPaQre7RrEtziIhRgB8=",
// "EncryptedDataKey": "<snip>CBZogG5a",
// "EncryptionContext": {
// "purpose": "automation"
// },
// "Iv": "6f93b293f7f77ddf7525bf43038f01c4"
// }
})
To decrypt previously encrypted data, feed the parsed JSON document
into the decrypt()
function of the module:
const kmscrypt = require('aws-kms-crypt')
kmscrypt.decrypt({
'EncryptedData': 'TSHgAb4MYkacM9qtdO5OeLQax6jze3P7+zIeUDpakC4=',
'EncryptedDataKey': '<snip>KqnVhLZY+8',
'EncryptionContext': {
'purpose': 'automation'
},
'Iv': '6cfbac80d90df12a6357a8f91b57f907'
}, { region: 'eu-west-1' }, function (err, result) {
if (err) {
return console.log('Encryption failed:', err)
}
console.log(result)
// => secretp4ssw0rd!
})
The python
directory contains a Python package that implements the KMS based encryption
and decryption functionality. The module has been tested to work with both Python 2.7 and
Python 3.5.
import kmscrypt
res = kmscrypt.encrypt('secretp4ssw0rd!', key_id='alias/common', encryption_context={
'purpose': 'automation'
})
# res is now a dict of form
# {
# 'EncryptedData': 'Su00srm/ru5kd9DLDvi0EdEjjBGUrRBJ06vUmL8QHUU=',
# 'EncryptedDataKey': 'AQIDAHhyrbU/fP<snip>',
# 'EncryptionContext': {'purpose': 'automation'},
# 'Iv': 'd07acff1e2301c468cd3164b8858e477'
# }
secret = kmscrypt.decrypt(res)
print(secret) # => secretp4ssw0rd!
The rust
directory contains a rust crate that implements KMS based encryption
and decryption functionality.
extern crate aws_kms_crypt;
extern crate serde_json;
use std::collections::HashMap;
fn main() {
let mut encryption_context = HashMap::new();
encryption_context.insert("entity".to_owned(), "admin".to_owned());
let options = aws_kms_crypt::EncryptOptions {
encryption_context: encryption_context,
key: "alias/common".into(),
region: "eu-west-1".into()
};
let data = "secret".into();
let res = aws_kms_crypt::encrypt(&data, &options);
println!("{}", serde_json::to_string(&res.unwrap()).unwrap());
}
Here's a full example that uses serde_json to deserialize the JSON encoded secret into a struct:
extern crate aws_kms_crypt;
extern crate serde_json;
fn main() {
let raw = r#"{
"EncryptedData": "vRhu+D5LrwNctyhxDvUoqL51YH2LclgUKtDz/2Nxy6Y=",
"EncryptedDataKey": "<snip>KBFRpvDvpXNXu3e/tTO6Jfi",
"EncryptionContext": {
"entity": "admin"
},
"Iv": "31bf06a8e0d15a26f1325da6f4f33a9c"
}"#;
let data: aws_kms_crypt::EncryptedSecret = serde_json::from_str(raw).unwrap();
let options = aws_kms_crypt::DecryptOptions {
region: "eu-west-1".to_owned()
};
let res = aws_kms_crypt::decrypt(&data, &options);
println!("Secret is: {:?}", res.unwrap());
}
The following steps are taken when the data is encrypted:
{
"EncryptedData": "<base64>",
"EncryptedDataKey": "<base64>",
"EncryptionContext": {
"KeyName1": "1",
"KeyName2": "2"
},
"Iv": "<hex>"
}
This JSON output can be saved to a file and stored in (semi) publicly available location as it does not reveal anything about the encrypted data.
The decryption phase extracts the data from the JSON document the encryption phase produced and takes the following steps to decrypt the data: