Cryptographically Signed HTTP Lambda invocations
Combining cryptography with authorisation objects at the function level, might produce interesting results, "reversing" the responsibility in regards to who provides code
Join the DZone community and get the full member experience.Join For Free
I have written about this before. However, since I've done some major changes to Magic, I figure it would probably be valuable to describe the thing again - This time in more details. Anyways, onwards to the future.
This is one of those oddball things you have probably never seen before, arguably turning your Magic server into a crypto wallet and a financial transaction server, by allowing you to securely execute Hyperlambda code created by a 3rd party client - And have receipts giving you a guarantee of that the executed code was in fact created by one specific client. In many ways, it could be argued that this creates a "blockchain" type of technology for generic HTTP lambda invocations, providing code to your server, that you can securely execute, while getting a cryptographic receipt of that the code that was executed was indeed created by a specific client. Watch the video below for a walkthrough of how this actually works.
The internals of the process
If we start out imagining a client creating an invocation the process becomes as follows.
- The client's payload is cryptographically signed with his private key
- The payload is transmitted to the server
- The server verifies that the cryptography signature is valid
- The server looks up the execution rights associated with the public key
- The Hyperlambda in the payload is executed, only allowing for the slots that are "whitelisted" to be executed
- A receipt containing the entire payload is persisted on the server
- Whatever result the client requested is returned to the client
If any of the above steps are failing for some reasons, the execution is aborted. Fail conditions might be for instance.
- The payload has been tampered with after having been cryptographically signed
- The public key the payload was signed with does not exist on the server
- The payload tries to invoke a slot it is not allowed to invoke according to its "whitelist"
- The public key is disabled on the server
- The payload has been successfully executed previously
This allows you to import a public key in your Magic server, associate an authorisation object with the key, for then to have the owner of that key pair create Hyperlambda code that your server securely executes. Arguably "reversing the responsibility of code", where the server is no longer responsible for declaring its code, but rather the client provides a lambda object your server executes.
Use the "Evaluator" menu item from your Magic Dashboard and execute the following code.
If you open your "Crypto" menu item, and expand the "Receipts" tab, you will see something resembling the following.
The ID above is the value returned from [guid.new], and simply a randomly generated ID associated with your request, created by the client - Allowing the client to persist the invocation any ways he wants to on his side - But of course more importantly from the server's perspective becoming the equivalent of a "transaction identifier". Since the ID is also a part of the payload itself, and hence a part of the message the cryptographic signature was generated from, this prevents "replay attacks", where an adversary can pick up your payload, and replay the same payload again. This is accomplished by checking if the [.request-id] parts of the payload has been previously executed, and if so, aborting the execution, returning an error to the client.
Micro services and super scalable distributed systems
In addition to the obvious use cases, such as financial transactions, document signing, legal things, etc - This also allows you to create a micro service environment, publicly exposing endpoints over an insecure connection, such as the World Wide Web - While still providing guarantees of that nobody except those clients explicitly given permissions on your server are legally allowed to invoke your endpoints.
Since the whole idea also is that the client supplies the code, this also allows your system to go through evolutionary iterations, changing its behaviour, without having to patch or change your servers in any ways - Since the client is the party providing the actual code to be executed. Hence, upgrading your client, effectively changes the behaviour of your server. Needless to say, but in a Micro Service environment where you might have dozens, and sometimes thousands of heterogeneous server instances, this approach eliminates an entire axiom in regards to maintaining your system(s) - Simplifying things significantly, since you no longer need to patch your servers, but only your clients.
Warning! Don't go berserk
Yes, I know, once you get it, these guys are incredible - But they also carry some overhead. For instance, the payloads needs to be cryptographically signed by the client. The server needs to verify the signature and parse the Hyperlambda, building a lambda object from it. Execution rights needs to be retrieved from the database, and a receipt for the execution of the lambda object needs to be persisted into the database. Hence, you should not use these guys for things where execution speed is crucial, but rather smaller payloads, occasionally transmitted between clients and servers, and not for things needing to handle thousands of requests per second.
However, when you need them, you really need them - And if used correctly, and sparsely may I add, these guys are an incredible tool for you, to both scale out (securely) and more easily build heterogeneous server environments, without having to try to predict what the future might hold in regards to its requirements.
In this article we looked at how you can securely transmit lambda object from the client to the server, for then to have the server execute the code, and store a cryptographic receipt of the execution of the code. We also looked at how this process reverses the responsibility between the client and the server, allowing the client to provide the code, and how this simplifies maintenance of your server farm. Then we walked through how this could be accomplished in a secure environment, due to associating a bunch of execution rights with a public cryptography key.
Published at DZone with permission of Thomas Hansen. See the original article here.
Opinions expressed by DZone contributors are their own.