From df7cb474d0e68a4590bb40ce84a019dbc3ae32ca Mon Sep 17 00:00:00 2001 From: Julien Vehent Date: Mon, 26 Oct 2015 16:29:23 -0400 Subject: [PATCH] Fix in_place encryption/decryption of binary files, plus readme --- README.rst | 32 ++++++++++++++++++++++++++++++ sops/__init__.py | 51 +++++++++++++++++++----------------------------- 2 files changed, 52 insertions(+), 31 deletions(-) diff --git a/README.rst b/README.rst index f42d87d3e..1cead4878 100644 --- a/README.rst +++ b/README.rst @@ -275,6 +275,38 @@ original file after encrypting or decrypting it. $ sops -d -i /path/to/existing/file.yaml # file.yaml is back in cleartext +Encrypting binary files +~~~~~~~~~~~~~~~~~~~~~~~ + +`sops` primary use case is encrypting YAML and JSON configuration files, but it +also has the ability to manage binary files. When encrypting a binary, sops will +read the data as bytes, encrypt it, store the encrypted base64 under +`tree['data']` and write the result as JSON. + +Note that the base64 encoding of encrypted data can actually make the encrypted +file larger than the cleartext one. + +In-place encryption/decryption also works on binary files. + +.. code:: + + $ dd if=/dev/urandom of=/tmp/somerandom bs=1024 + count=512 + 512+0 records in + 512+0 records out + 524288 bytes (524 kB) copied, 0.0466158 s, 11.2 MB/s + + $ sha512sum /tmp/somerandom + 9589bb20280e9d381f7a192000498c994e921b3cdb11d2ef5a986578dc2239a340b25ef30691bac72bdb14028270828dad7e8bd31e274af9828c40d216e60cbe /tmp/somerandom + + $ sops -e -i /tmp/somerandom + please wait while a data encryption key is being generated and stored securely + + $ sops -d -i /tmp/somerandom + + $ sha512sum /tmp/somerandom + 9589bb20280e9d381f7a192000498c994e921b3cdb11d2ef5a986578dc2239a340b25ef30691bac72bdb14028270828dad7e8bd31e274af9828c40d216e60cbe /tmp/somerandom + Extract a sub-part of a document tree ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/sops/__init__.py b/sops/__init__.py index 3831af210..e8f6d9bbf 100644 --- a/sops/__init__.py +++ b/sops/__init__.py @@ -182,8 +182,13 @@ def main(): # Encrypt mode: encrypt, display and exit key, tree = get_key(tree, need_key) tree = walk_and_encrypt(tree, key) - finalize_output(tree, args.file, encrypt=True, in_place=args.in_place, - output_type=otype) + dest = '/dev/stdout' + if args.in_place: + dest = args.file + if otype == "bytes": + otype = "json" + write_file(tree, path=dest, filetype=otype) + sys.exit(0) if args.decrypt: # Decrypt mode: decrypt, display and exit @@ -191,8 +196,13 @@ def main(): tree = walk_and_decrypt(tree, key, ignoreMac=args.ignore_mac) if not args.show_master_keys: tree.pop('sops', None) - finalize_output(tree, args.file, decrypt=True, in_place=args.in_place, - output_type=otype, tree_path=args.tree_path) + dest = '/dev/stdout' + if args.in_place: + dest = args.file + if args.tree_path: + tree = truncate_tree(tree, args.tree_path) + write_file(tree, path=dest, filetype=otype) + sys.exit(0) # EDIT Mode: decrypt, edit, encrypt and save key, tree = get_key(tree, need_key) @@ -264,7 +274,12 @@ def main(): tree = update_master_keys(tree, key) os.remove(tmppath) - finalize_output(tree, args.file, output_type=otype) + # always store encrypted binary files in a json enveloppe + if otype == "bytes": + otype = "json" + path = write_file(tree, path=args.file, filetype=otype) + print("file written to %s" % (path), file=sys.stderr) + sys.exit(0) def detect_filetype(file): @@ -880,32 +895,6 @@ def encrypt_key_with_pgp(key, entry): return entry -def finalize_output(tree, path, encrypt=False, decrypt=False, in_place=False, - output_type="json", tree_path=None): - """ Write the final output of sops to a destination path """ - # if we're in -e or -d mode, and not in -i mode, display to stdout - if encrypt and not in_place: - if output_type == "bytes": - output_type = "json" - write_file(tree, path='/dev/stdout', filetype=output_type) - - elif decrypt and not in_place: - if tree_path: - tree = truncate_tree(tree, tree_path) - # don't show sops metadata in decrypt mode - - write_file(tree, path='/dev/stdout', filetype=output_type) - - # otherwise, write the tree to a file - else: - if output_type == "bytes": - output_type = "json" - path = write_file(tree, path=path, filetype=output_type) - print("file written to %s" % (path), file=sys.stderr) - # it's called "finalize" for a reason... - sys.exit(0) - - def write_file(tree, path=None, filetype=None): """Write the tree content in a file using filetype format.