diff --git a/kmip/demos/pie/decrypt.py b/kmip/demos/pie/decrypt.py new file mode 100644 index 0000000..1b10aa6 --- /dev/null +++ b/kmip/demos/pie/decrypt.py @@ -0,0 +1,77 @@ +# Copyright (c) 2017 The Johns Hopkins University/Applied Physics Laboratory +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import binascii +import logging +import sys + +from kmip.core import enums +from kmip.demos import utils +from kmip.pie import client + +# Real world example, assuming 'test' is a valid configuration: +# +# $ python kmip/demos/pie/encrypt.py -c test -m "My test message." +# INFO - Successfully created a new encryption key. +# INFO - Secret ID: 470 +# INFO - Successfully activated the encryption key. +# INFO - Successfully encrypted the message. +# INFO - Cipher text: b'49cfacbb62659180c20dfbf9f7553488b3ea9ebeecd70ce2e5c4d4 +# ece6def0d4' +# INFO - No autogenerated IV expected, since one was provided. +# INFO - Autogenerated IV: None +# $ python kmip/demos/pie/decrypt.py -c test -i 470 -m b'49cfacbb62659180c20df +# bf9f7553488b3ea9ebeecd70ce2e5c4d4ece6def0d4' +# INFO - Successfully decrypted the message. +# INFO - Plain text: 'My test message.' + + +if __name__ == '__main__': + logger = utils.build_console_logger(logging.INFO) + + # Build and parse arguments + parser = utils.build_cli_parser(enums.Operation.DECRYPT) + opts, args = parser.parse_args(sys.argv[1:]) + config = opts.config + uuid = opts.uuid + message = opts.message + + if not message.startswith("b"): + raise ValueError("The message should be a byte string (e.g., b'...').") + else: + message = binascii.unhexlify(message[1:]) + + # Build the client and connect to the server + with client.ProxyKmipClient(config=config) as client: + # Decrypt the cipher text with the encryption key. + try: + plain_text = client.decrypt( + message, + uid=uuid, + cryptographic_parameters={ + 'cryptographic_algorithm': + enums.CryptographicAlgorithm.AES, + 'block_cipher_mode': enums.BlockCipherMode.CBC, + 'padding_method': enums.PaddingMethod.ANSI_X923 + }, + iv_counter_nonce=( + b'\x01\x7D\x45\xA0\x88\x08\x11\x11' + b'\xF0\x00\x12\xFF\x7A\x3A\x36\x90' + ) + ) + logger.info("Successfully decrypted the message.") + logger.info("Plain text: '{0}'".format(plain_text.decode('utf-8'))) + except Exception as e: + logger.error(e) diff --git a/kmip/demos/pie/encrypt.py b/kmip/demos/pie/encrypt.py new file mode 100644 index 0000000..1946eeb --- /dev/null +++ b/kmip/demos/pie/encrypt.py @@ -0,0 +1,103 @@ +# Copyright (c) 2017 The Johns Hopkins University/Applied Physics Laboratory +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import binascii +import logging +import sys + +from kmip.core import enums +from kmip.demos import utils +from kmip.pie import client + +# Real world example, assuming 'test' is a valid configuration: +# +# $ python kmip/demos/pie/encrypt.py -c test -m "My test message." +# INFO - Successfully created a new encryption key. +# INFO - Secret ID: 470 +# INFO - Successfully activated the encryption key. +# INFO - Successfully encrypted the message. +# INFO - Cipher text: b'49cfacbb62659180c20dfbf9f7553488b3ea9ebeecd70ce2e5c4d4 +# ece6def0d4' +# INFO - No autogenerated IV expected, since one was provided. +# INFO - Autogenerated IV: None +# $ python kmip/demos/pie/decrypt.py -c test -i 470 -m b'49cfacbb62659180c20df +# bf9f7553488b3ea9ebeecd70ce2e5c4d4ece6def0d4' +# INFO - Successfully decrypted the message. +# INFO - Plain text: 'My test message.' + + +if __name__ == '__main__': + logger = utils.build_console_logger(logging.INFO) + + # Build and parse arguments + parser = utils.build_cli_parser(enums.Operation.ENCRYPT) + opts, args = parser.parse_args(sys.argv[1:]) + config = opts.config + message = opts.message + + message = bytes(message, 'utf-8') + + # Build the client and connect to the server + with client.ProxyKmipClient(config=config) as client: + # Create an encryption key. + try: + key_id = client.create( + enums.CryptographicAlgorithm.AES, + 128, + cryptographic_usage_mask=[ + enums.CryptographicUsageMask.ENCRYPT, + enums.CryptographicUsageMask.DECRYPT + ] + ) + logger.info("Successfully created a new encryption key.") + logger.info("Secret ID: {0}".format(key_id)) + except Exception as e: + logger.error(e) + sys.exit(-1) + + # Activate the encryption key so that it can be used. + try: + client.activate(key_id) + logger.info("Successfully activated the encryption key.") + except Exception as e: + logger.error(e) + sys.exit(-1) + + # Encrypt some data with the encryption key. + try: + cipher_text, autogenerated_iv = client.encrypt( + message, + uid=key_id, + cryptographic_parameters={ + 'cryptographic_algorithm': + enums.CryptographicAlgorithm.AES, + 'block_cipher_mode': enums.BlockCipherMode.CBC, + 'padding_method': enums.PaddingMethod.ANSI_X923 + }, + iv_counter_nonce=( + b'\x01\x7D\x45\xA0\x88\x08\x11\x11' + b'\xF0\x00\x12\xFF\x7A\x3A\x36\x90' + ) + ) + logger.info("Successfully encrypted the message.") + logger.info( + "Cipher text: {0}".format(binascii.hexlify(cipher_text)) + ) + logger.info( + "No autogenerated IV expected, since one was provided." + ) + logger.info("Autogenerated IV: {0}".format(autogenerated_iv)) + except Exception as e: + logger.error(e) diff --git a/kmip/demos/utils.py b/kmip/demos/utils.py index b6d7796..fd54e1d 100644 --- a/kmip/demos/utils.py +++ b/kmip/demos/utils.py @@ -240,6 +240,36 @@ def build_cli_parser(operation=None): default=None, dest="algorithm", help="Encryption algorithm for the secret (e.g., AES)") + elif operation is Operation.ENCRYPT: + parser.add_option( + "-m", + "--message", + action="store", + type="str", + default="This is a secret message.", + dest="message", + help="The message to encrypt." + ) + elif operation is Operation.DECRYPT: + parser.add_option( + "-i", + "--uuid", + action="store", + type="str", + default=None, + dest="uuid", + help="The unique ID of the decryption key to use to decrypt the " + "cipher text." + ) + parser.add_option( + "-m", + "--message", + action="store", + type="str", + default=None, + dest="message", + help="The cipher text to decrypt." + ) return parser diff --git a/kmip/services/kmip_client.py b/kmip/services/kmip_client.py index e8241e8..8ab39a4 100644 --- a/kmip/services/kmip_client.py +++ b/kmip/services/kmip_client.py @@ -584,9 +584,15 @@ class KMIPProxy(KMIP): result['data'] = payload.data result['iv_counter_nonce'] = payload.iv_counter_nonce - result['result_status'] = batch_item.result_status - result['result_reason'] = batch_item.result_reason - result['result_message'] = batch_item.result_message + result['result_status'] = batch_item.result_status.value + try: + result['result_reason'] = batch_item.result_reason.value + except: + result['result_reason'] = batch_item.result_reason + try: + result['result_message'] = batch_item.result_message.value + except: + result['result_message'] = batch_item.result_message return result @@ -653,9 +659,15 @@ class KMIPProxy(KMIP): result['unique_identifier'] = payload.unique_identifier result['data'] = payload.data - result['result_status'] = batch_item.result_status - result['result_reason'] = batch_item.result_reason - result['result_message'] = batch_item.result_message + result['result_status'] = batch_item.result_status.value + try: + result['result_reason'] = batch_item.result_reason.value + except: + result['result_reason'] = batch_item.result_reason + try: + result['result_message'] = batch_item.result_message.value + except: + result['result_message'] = batch_item.result_message return result diff --git a/kmip/tests/unit/services/test_kmip_client.py b/kmip/tests/unit/services/test_kmip_client.py index cfddde3..dded6d5 100644 --- a/kmip/tests/unit/services/test_kmip_client.py +++ b/kmip/tests/unit/services/test_kmip_client.py @@ -839,7 +839,7 @@ class TestKMIPClient(TestCase): self.assertEqual(None, result.get('iv_counter_nonce')) self.assertEqual( ResultStatusEnum.SUCCESS, - result.get('result_status').value + result.get('result_status') ) self.assertEqual(None, result.get('result_reason')) self.assertEqual(None, result.get('result_message')) @@ -901,7 +901,7 @@ class TestKMIPClient(TestCase): ) self.assertEqual( ResultStatusEnum.SUCCESS, - result.get('result_status').value + result.get('result_status') ) self.assertEqual(None, result.get('result_reason')) self.assertEqual(None, result.get('result_message'))