diff --git a/HISTORY.rst b/HISTORY.rst
index f4be37f..8b242d6 100644
--- a/HISTORY.rst
+++ b/HISTORY.rst
@@ -9,6 +9,7 @@ Pending Release
 
 * (Insert new release notes below this line)
 * Add ``--json`` argument to ``print`` command.
+* Make 'edit' reuse previous encrypted values that weren't changed.
 
 1.1.0 (2017-04-05)
 ------------------
diff --git a/treehugger/kms.py b/treehugger/kms.py
index 47cc221..bb02d68 100644
--- a/treehugger/kms.py
+++ b/treehugger/kms.py
@@ -11,6 +11,9 @@ from .ec2 import get_current_region
 
 class KMSAgent(object):
 
+    def __init__(self):
+        self.cache = {}
+
     key_id = 'alias/treehugger'
 
     @property
@@ -29,9 +32,14 @@ class KMSAgent(object):
             CiphertextBlob=cipher_blob,
             EncryptionContext=encryption_context,
         )
-        return response['Plaintext'].decode('utf-8')
+        plaintext = response['Plaintext'].decode('utf-8')
+        self.cache[plaintext] = base64_ciphertext
+        return plaintext
 
     def encrypt(self, plaintext, encryption_context):
+        if plaintext in self.cache:
+            return self.cache[plaintext]
+
         response = self.kms_client.encrypt(
             KeyId=self.key_id,
             Plaintext=plaintext.encode('utf-8'),

diff --git a/tests/test_cli.py b/tests/test_cli.py
index c24ae65..1357704 100644
--- a/tests/test_cli.py
+++ b/tests/test_cli.py
@@ -191,11 +191,34 @@ class TestCLI:
                 'Plaintext': b'quux',
             }
         )
+
+        def fake_call(command):
+            assert len(command) == 2
+            assert command[0] == 'nano'
+            filename = command[1]
+            with open(filename, 'r') as fp:
+                obj = yaml.safe_load(fp.read())
+            assert obj == {
+                'MY_ENCRYPTED_VAR': {'to_encrypt': 'quux'},
+                'MY_UNENCRYPTED_VAR': 'bar',
+                'TREEHUGGER_APP': 'baz',
+                'TREEHUGGER_STAGE': 'qux',
+            }
+
+            with open(filename, 'w') as fp:
+                fp.write(textwrap.dedent('''\
+                    MY_ENCRYPTED_VAR: {to_encrypt: quux2}
+                    MY_UNENCRYPTED_VAR: bar
+                    TREEHUGGER_APP: baz
+                    TREEHUGGER_STAGE: qux
+                '''))
+            return 0
+
         kms_stub.add_response(
             'encrypt',
             expected_params={
                 'KeyId': 'alias/treehugger',
-                'Plaintext': b'quux',
+                'Plaintext': b'quux2',
                 'EncryptionContext': {
                     'treehugger_app': 'baz',
                     'treehugger_key': 'MY_ENCRYPTED_VAR',
@@ -207,6 +230,34 @@ class TestCLI:
                 'CiphertextBlob': b'foo',
             }
         )
+        with mock.patch.dict(os.environ, {'EDITOR': 'nano'}), mock.patch('subprocess.call', new=fake_call):
+            main(['edit', six.text_type(tmpfile)])
+
+    def test_edit_no_change(self, tmpdir, kms_stub):
+        tmpfile = tmpdir.join('test.yml')
+        encrypted_var = base64.b64encode(b'foo')
+        tmpfile.write(textwrap.dedent('''\
+            MY_ENCRYPTED_VAR:
+              encrypted: {encrypted_var}
+            MY_UNENCRYPTED_VAR: bar
+            TREEHUGGER_APP: baz
+            TREEHUGGER_STAGE: qux
+        '''.format(encrypted_var=encrypted_var.decode('utf-8'))))
+        kms_stub.add_response(
+            'decrypt',
+            expected_params={
+                'CiphertextBlob': b'foo',
+                'EncryptionContext': {
+                    'treehugger_app': 'baz',
+                    'treehugger_key': 'MY_ENCRYPTED_VAR',
+                    'treehugger_stage': 'qux',
+                }
+            },
+            service_response={
+                'KeyId': 'treehugger',
+                'Plaintext': b'quux',
+            }
+        )
 
         with mock.patch.dict(os.environ, {'EDITOR': 'nano'}), mock.patch('subprocess.call') as mock_call:
             mock_call.return_value = 0

Make 'edit' reuse previous encrypted values that weren't changed
When editing a file, every `to_encrypt` value gets re-encrypted, which changes all the encrypted values as the encrypted blob KMS uses seems to include a timestamp. This is less than ideal as it means changing one password changes the whole file, leading to horrible diffs.

It would be nice if when running 'edit', treehugger compared the before/after, and reused the `encrypted` values for all those things that haven't changed their `to_encrypt` forms. This could maybe be done with a cache layer around the decrypt/encrypt calls to KMS, such that re-encrypting reuses the value found when decrypting to edit.
tests/test_cli.py::TestCLI::test_edit_no_change
tests/test_cli.py::TestCLI::test_edit tests/test_cli.py::TestCLI::test_help tests/test_cli.py::TestCLI::test_print_json tests/test_cli.py::TestCLI::test_print_single_line tests/test_cli.py::TestCLI::test_exec_no_command_but_dashes tests/test_cli.py::TestCLI::test_print_file tests/test_cli.py::TestCLI::test_exec_no_command tests/test_cli.py::TestCLI::test_print_only_unencrypted tests/test_cli.py::TestCLI::test_print_json_single_line tests/test_cli.py::TestCLI::test_print_no_var_with_quote tests/test_cli.py::TestCLI::test_exec_file