diff --git a/integrations/larky/crypto/AES_CCM_GCM/README.md b/integrations/larky/crypto/AES_CCM_GCM/README.md new file mode 100644 index 0000000..55b697e --- /dev/null +++ b/integrations/larky/crypto/AES_CCM_GCM/README.md @@ -0,0 +1,55 @@ +# AES CCM and GCM sample of encryption in Larky + +This sample includes: +1. Python script that generates an ectrypted message of an input data; +2. Larky test `.star` file that generates the same result of the same input data; +3. Ready-for-use YAML (Inbound Route) that produces the same result as previous scripts. + +## Testing part: + +#### 1. Python: + +Python script includes all hard-coded inside. As a result, it prints the encrypted message: +``` +$ python python_sample.py + +>>> Encrypted GCM: YXNkNDU2ZmdoMDEyql2O8UB53Ux94KWoIaIDarnm+6xKaXL2FNfHl5XOCtbv590W5x6ISEI3 + +>>> GCM decrypted: b'{"card_number":"4111111111111111"}' + +>>> Encrypted CCM: YXNkNDU2ZmdoMDEysNf+zbjlTcFG/q1TPyuLIJwELXp6pSwIx1bwpV8Zw92S6G2FpI3OpWEJ + +>>> CCM decrypted: b'{"card_number":"4111111111111111"}' + +``` + +#### 2. Larky test: + +To be able to run Larky locally, you'll need to setup your local environment: +https://www.verygoodsecurity.com/docs/larky/test-larky-locally + +Example of run: + +image + +#### 3. YAML file: + +Upload the YAML to your vault and run: +``` +curl https://tntbmt67sc7.sandbox.verygoodproxy.com/post -k \ + -H "Content-type: application/json" \ + -d '{"card_number":"4111111111111111"}' +``` + +Example of response: +``` +"json": { + "CCM": "YXNkNDU2ZmdoMDEysNf+zbjlTcFG/q1TPyuLIJwELXp6pSwIx1bwpV8Zw92S6G2FpI3OpWEJ", + "CCM_decrypted": { + "card_number": "4111111111111111" + }, + "GCM": "YXNkNDU2ZmdoMDEyql2O8UB53Ux94KWoIaIDarnm+6xKaXL2FNfHl5XOCtbv590W5x6ISEI3", + "GCM_decrypted": { + "card_number": "4111111111111111" + } +``` diff --git a/integrations/larky/crypto/AES_CCM_GCM/python_sample.py b/integrations/larky/crypto/AES_CCM_GCM/python_sample.py new file mode 100644 index 0000000..b3203ed --- /dev/null +++ b/integrations/larky/crypto/AES_CCM_GCM/python_sample.py @@ -0,0 +1,35 @@ +import builtins +import json +from requests.auth import HTTPProxyAuth +import base64 +from Crypto.Cipher import AES + +TAG_LENGTH = 8 + +session_key = b'vbfhg768ghvbfhg768ghvbfhg768gh12' +nonce = b'asd456fgh012' + +body = b'{"card_number":"4111111111111111"}' + +cipher_aes = AES.new(session_key, AES.MODE_GCM, nonce=nonce, mac_len=TAG_LENGTH) +ciphertext, tag = cipher_aes.encrypt_and_digest(body) +ciphertext_tag = b"".join([cipher_aes.nonce, ciphertext, tag]) +result_GCM = base64.b64encode(ciphertext_tag).decode('utf-8') +print('\n>>> Encrypted GCM: ', result_GCM) + +#decrypt GCM: +cipher = AES.new(session_key, AES.MODE_GCM, nonce=nonce) +plaintext = cipher.decrypt(ciphertext) +print("\n>>> GCM decrypted: " + str(plaintext)) + +cipher_aes = AES.new(session_key, AES.MODE_CCM, nonce=nonce, mac_len=TAG_LENGTH) +ciphertext, tag = cipher_aes.encrypt_and_digest(body) +ciphertext_tag = b"".join([cipher_aes.nonce, ciphertext, tag]) +result_CCM = base64.b64encode(ciphertext_tag).decode('utf-8') +print('\n>>> Encrypted CCM: ', result_CCM) + +#decrypt CCM: +cipher = AES.new(session_key, AES.MODE_CCM, nonce=nonce) +plaintext = cipher.decrypt(ciphertext) +print("\n>>> CCM decrypted: " + str(plaintext) + '\n') + diff --git a/integrations/larky/crypto/AES_CCM_GCM/test_aes_ccm_gcm.star b/integrations/larky/crypto/AES_CCM_GCM/test_aes_ccm_gcm.star new file mode 100644 index 0000000..534ad5a --- /dev/null +++ b/integrations/larky/crypto/AES_CCM_GCM/test_aes_ccm_gcm.star @@ -0,0 +1,63 @@ +load("@stdlib//unittest", "unittest") +load("@vendor//asserts", "asserts") +load("@vgs//http/request", "VGSHttpRequest") +load("@stdlib//json", json="json") +load("@stdlib//builtins", builtins="builtins") +load("@vendor//Crypto/Cipher/AES", AES="AES") +load("@stdlib//base64", base64="base64") + + +def process(input, ctx): + TAG_LENGTH = 8 + session_key = b'vbfhg768ghvbfhg768ghvbfhg768gh12' + nonce = b'asd456fgh012' + + body_str = str(input.body) + body = json.loads(body_str) + + # GCM: + cipher_aes = AES.new(session_key, AES.MODE_GCM, nonce=nonce, mac_len=TAG_LENGTH) + ciphertext, tag = cipher_aes.encrypt_and_digest(builtins.bytes(body_str, 'utf-8')) + ciphertext_tag = b"".join([cipher_aes.nonce, ciphertext, tag]) + ciphertext_b64_GCM = base64.b64encode(ciphertext_tag).decode('utf-8') + # decrypt: + cipher = AES.new(session_key, AES.MODE_GCM, nonce=nonce) + plaintext = cipher.decrypt(ciphertext) + body['GCM'] = ciphertext_b64_GCM + body['GCM_decrypted'] = json.loads(str(plaintext)) + + # CCM: + cipher_aes = AES.new(session_key, AES.MODE_CCM, nonce=nonce, mac_len=TAG_LENGTH) + ciphertext, tag = cipher_aes.encrypt_and_digest(builtins.bytes(body_str, 'utf-8')) + ciphertext_tag = b"".join([cipher_aes.nonce, ciphertext, tag]) + ciphertext_b64_CCM = base64.b64encode(ciphertext_tag).decode('utf-8') + # decrypt: + cipher = AES.new(session_key, AES.MODE_CCM, nonce=nonce) + plaintext = cipher.decrypt(ciphertext) + body['CCM'] = ciphertext_b64_CCM + body['CCM_decrypted'] = json.loads(str(plaintext)) + + body.pop('card_number') + input.body = builtins.bytes(json.dumps(body)) + return input + + +def test_process(): + headers = {} + body = b'{"card_number":"4111111111111111"}' + input = VGSHttpRequest("https://test.com", data=body, headers=headers, method='POST') + response = process(input, None) + expected_body = b'{"CCM":"YXNkNDU2ZmdoMDEysNf+zbjlTcFG/q1TPyuLIJwELXp6pSwIx1bwpV8Zw92S6G2FpI3OpWEJ","CCM_decrypted":{"card_number":"4111111111111111"},"GCM":"YXNkNDU2ZmdoMDEyql2O8UB53Ux94KWoIaIDarnm+6xKaXL2FNfHl5XOCtbv590W5x6ISEI3","GCM_decrypted":{"card_number":"4111111111111111"}}' + print(response.body) + print(expected_body) + asserts.assert_that(response.body).is_equal_to(expected_body) + + +def _testsuite(): + _suite = unittest.TestSuite() + _suite.addTest(unittest.FunctionTestCase(test_process)) + return _suite + +_runner = unittest.TextTestRunner() +_runner.run(_testsuite()) + diff --git a/integrations/larky/crypto/AES_CCM_GCM/testing-CCM-vs-GCM.yml b/integrations/larky/crypto/AES_CCM_GCM/testing-CCM-vs-GCM.yml new file mode 100644 index 0000000..2587791 --- /dev/null +++ b/integrations/larky/crypto/AES_CCM_GCM/testing-CCM-vs-GCM.yml @@ -0,0 +1,92 @@ +data: + - attributes: + created_at: '2021-04-26T09:55:37' + destination_override_endpoint: 'https://echo.apps.verygood.systems' + entries: + - classifiers: {} + config: + condition: AND + rules: + - condition: null + expression: + field: PathInfo + operator: matches + type: string + values: + - /post + - condition: null + expression: + field: ContentType + operator: equals + type: string + values: + - application/json + id: 3e4ca047-23e2-4397-9a67-d673cedf4cc8 + id_selector: null + operation: REDACT + operations: + - name: github.com/verygoodsecurity/common/compute/larky/http/Process + parameters: + script: |- + load("@stdlib//base64", base64="base64") + load("@stdlib//builtins", builtins="builtins") + load("@stdlib//json", json="json") + load("@stdlib//larky", larky="larky") + load("@vendor//Crypto/Cipher/AES", AES="AES") + load("@vgs//vault", "vault") + + def process(input, ctx): + TAG_LENGTH = 8 + session_key = b'vbfhg768ghvbfhg768ghvbfhg768gh12' + nonce = b'asd456fgh012' + + body_str = str(input.body) + body = json.loads(body_str) + + # GCM: + cipher_aes = AES.new(session_key, AES.MODE_GCM, nonce=nonce, mac_len=TAG_LENGTH) + ciphertext, tag = cipher_aes.encrypt_and_digest(builtins.bytes(body_str, 'utf-8')) + ciphertext_tag = b"".join([cipher_aes.nonce, ciphertext, tag]) + ciphertext_b64_GCM = base64.b64encode(ciphertext_tag).decode('utf-8') + # decrypt: + cipher = AES.new(session_key, AES.MODE_GCM, nonce=nonce) + plaintext = cipher.decrypt(ciphertext) + body['GCM'] = ciphertext_b64_GCM + body['GCM_decrypted'] = json.loads(str(plaintext)) + + # CCM: + cipher_aes = AES.new(session_key, AES.MODE_CCM, nonce=nonce, mac_len=TAG_LENGTH) + ciphertext, tag = cipher_aes.encrypt_and_digest(builtins.bytes(body_str, 'utf-8')) + ciphertext_tag = b"".join([cipher_aes.nonce, ciphertext, tag]) + ciphertext_b64_CCM = base64.b64encode(ciphertext_tag).decode('utf-8') + # decrypt: + cipher = AES.new(session_key, AES.MODE_CCM, nonce=nonce) + plaintext = cipher.decrypt(ciphertext) + body['CCM'] = ciphertext_b64_CCM + body['CCM_decrypted'] = json.loads(str(plaintext)) + + body.pop('card_number') + input.body = builtins.bytes(json.dumps(body)) + return input + phase: REQUEST + public_token_generator: UUID + targets: + - body + token_manager: PERSISTENT + transformer: JSON_PATH + transformer_config: + - $.email + transformer_config_map: null + host_endpoint: (.*)\.verygoodproxy\.com + id: c891d346-0e1b-49b8-99ac-0754d34f14f2 + ordinal: null + port: 80 + protocol: http + source_endpoint: '*' + tags: + name: echo.apps.verygood.systems-steel-blue-parallelogram + source: RouteContainer + updated_at: '2021-05-07T11:45:32' + id: c891d346-0e1b-49b8-99ac-0754d34f14f2 + type: rule_chain +version: 1 diff --git a/integrations/larky/crypto/AES_CTR/inbound-AES-CTR.yml b/integrations/larky/crypto/AES_CTR/inbound-AES-CTR.yml index 000099f..118632e 100644 --- a/integrations/larky/crypto/AES_CTR/inbound-AES-CTR.yml +++ b/integrations/larky/crypto/AES_CTR/inbound-AES-CTR.yml @@ -67,7 +67,7 @@ data: encString = base64.urlsafe_b64encode(chipertext).decode() payload = '&encryptedData=' + encString + '&iv=' + ivv - # final result to be send to dev.finexusgroup.com + # final result to be sent to upstream enc = bytes(payload, encoding='utf-8') final = base64.b64encode(enc).decode()