0.1.1 • Published 5 years ago

@tera-insights/tc-form-utilities v0.1.1

Weekly downloads
-
License
ISC
Repository
-
Last release
5 years ago

tiFormEncrypt

This is an encryption/decryption library that can be used together with the tiForms mechanism in tiCrypt to allow secure form submission. Once encrypted, the form data can only be decrypted using the form private key.

Overview

The main usage scenario for tiFormEncrypt is the folliwing:

  1. The tiCrypt client creates a publicKey-privateKey key pair, a formID and one apiID for each independent web server. The privateKey is encrypted and kept secret (i.e. it is available only through tiCrypt frontend interface).
  2. The web server stores internally (e.g. in config files) the publicKey, formID and apiID. Only publicKey is made available to the web client (e.g it is injected in the javascript code as a global constant).
  3. The web client is provided the publicKey. It harvests data (e.g. form data), and encrypts the data using Eliptic Curve Diffie-Helman (ECDH) with a randomly generated provate key and the provide publicKey. The public part of the generated key and the encrypted payload are handed over to the web server.
  4. The web server gets the data from the web client and adds formID and apiID and submits it to the tiCrypt backent.
  5. Latter, through the tiCrypt client, the privateKey is recovered and the form data accessed and decrypted (via ECDH).

Client Interface

First, the encryption library has to be included in the html sources:

<script type="text/javascript" src="dist/tiForms.js"></script>

The form publicKey is made available by the web server, for example by injecting

<script> 
    var formPublicKey = "kjsaldfjjsfljas|asdfasdfasdfasdf";
</script>

in the main html code.

Assuming the web server accepts POSTS on /submit route and using jquery (raw AJAX or other frameworks can be used as well), the client code to submit any data object can be:

function submitMyData(obj){
    var objAsString = JSON.stringify(obj);
    tiForms.ready( function(){
        var encryptor = tiForms.MakeEncryptor(formPublicKey);
        // make sure the encryptor is ready
        encryptor.ready( function(){
            encryptor.encryptStringCB(objAsString, 
                function(data){ // success
                    $.post('/submit', data);
                }, function(err){ // post failed
                    console.error(err);
                }
            );
        });
    });
}

Notice the use of tiForms.ready(). Without it, the shimming for Edge and Safari will not work properly. ready() can be called as many times as desired; it will detect the capabilities only once.

Alternatively, the above code can be written more elegantly using promises:

// submits the encrypted form and return a promise that indicates success or failure
function submitMyData(obj){
    tiForms.ready( function(){
        var encryptor = tiForms.MakeEncryptor(formPublicKey);
        // make sure the encryptor is ready
        return encryptor.ready().then( function(){
            return encryptor.encryptString(JSON.stringify(obj))
                .then( function(data){
                    return $.post('/submit', data);
                })
        });
    });
}

$('#myButton').click( function(){
    submitMyData( $('myForm').serializeArray() )
        .then( function(){
            $('#successmsg').show();
        }, function(){
            $('#failmsg').show();
        })
});

Note The AES encryption key and the private key of the Elliptic Curve generated by the tiForms.js library is non-extractable. Under no circusmstance should you change the tiForms.js library and make the keys extractable since that would break the security model. The AES decryption key can be recovered by the tiCrypt client from the public part of the Elliptic Curve key and the form private key.

Web server Interface

The web server has minimal requirements:

  1. It must implement authentication (if desired)
  2. It must implement a POST route on which the data gets submitted from the client. For example /submit
  3. It must be able to manipulate the client submited data and add the formID and apiID fields;

The object received from the client has the form:

{
    "publicKey": "akljdsflkjasdlkfjasdjf|lalaksdfkjsldfjalsj",
    "payload": "ldaksjflkasjjkjklajsldkfjlkasjdflkjasdlkfjlaskdjflkasjdflkjasldfkjas"
}

The object is send to the tiCrypt server must look like:

{
    "formID": "kjlkjlakjlkdfjalskajd", 
    "appID": "asdefkaldsfalsdfkadfsf",
    "publicKey": "akljdsflkjasdlkfjasdjf|lalaksdfkjsldfjalsj",
    "payload": "ldaksjflkasjjkjklajsldkfjlkasjdflkjasdlkfjlaskdjflkasjdflkjasldfkjas"
}

The data is send as a POST on the route /forms/.

The web server can submit the data to the tiCrypt backend withtout any session or credentials except correct formID and matching appID.

Note 1 It is absolutely critical that the web server does not store or logs the content received from the client.

Note 2 The formID and the appID should not be made available to the client and shoudl be guarded with the same care that the SSL/TLS certificate is handled.

Development

Installation

Make sure the following packages are installed globaly

  • webpack
  • karma

Then npm install to get the remaining packages.

Instructions

  • To run tests, do karma test
  • To start example server do cd examples/formSubmit; node server.js then navigate to localhost:3000 or localhost:3000/bulk
  • To rebuild library do webpack
  • To rebuild server do webpack --config server.wp.config.js