Secure Data Sharing with TozStore

Last week, we covered how to collect, store, and process encrypted data using Tozny’s TozStore product. This week, we’ll dive in a bit deeper and demonstrate how the end-to-end secure data sharing mechanisms work.

TozStore’s End-to-End Encryption Model

TozStore itself is built atop Tozny’s end-to-end encrypted database platform, e3db. The platform itself uses a blend of symmetric and asymmetric encryption to keep data safe and secure in such a way that only explicitly authorized parties ever have access. Records stored within e3db are JSON documents where the field names are kept in plaintext (for efficient database queries) and the values are encrypted at rest.

Individual clients each have their own set of asymmetric encryption keys, which are used in turn to “wrap” the symmetric keys that protect the data itself. Even if the database itself were ever breached by a third party, the data is unusable without an authorized decryption key.

Record Access and Sharing

Before forms are submitted using TozStore, the data is encrypted in the browser using a dynamically-generated key. The protected record is stored on the server, then shared with the client you’ve configured the TozStore form to use. This sharing operation uses that client’s stored public key to re-wrap the symmetric key originally used to protect the record.

At no point is anyone other than the end user who submitted the data or your previously-authorized client ever given access to the data.

This sharing mechanism can also be used to permit other clients to access individual records. After writing a new piece of data, your client can elect to share this record with another client by preparing a copy of the data’s access key for that third party. As the original writer of the data, your client already has access to an unencrypted copy of the data’s symmetric access key. Your client can also retrieve the third party’s asymmetric public key from the e3db platform itself.

Your client then encrypts the data’s access key using the third party’s public key and sends the encrypted copy back to e3db. When the third party retrieves the protected data, they get this encrypted key along with it. They then use their asymmetric private key to decrypt it and, subsequently, decrypt the data itself.

TozStore Setup

Just like last week, we’re going to create both a TozStore Client and Form to process incoming setup. If you haven’t signed up for an account yet, the Tozny Platform Dashboard will help set you up with a free account.

The name of the client doesn’t matter that much, but keep track of the generated credentials as they’ll be required for the extraction and sharing steps. For the sake of this walkthrough, set the type of data your form will collect to “account.”

Data Collection

In this example, we’ll build an account sign up form for a new startup. The startup focuses on warehousing customer health information and providing proactive feedback and sponsored offers that might fit with a particular customer’s profile. Unfortunately, keeping all of this information – contact information, health data, online purchase history, etc – in one place makes the company’s database a huge potential target for attack.

The safest approach is to offload as much of the data storage as possible.

A secondary approach is to segment data into smaller components so third parties who need access (i.e. sponsors wanting to contact customers with product offers) have only the data needed to do their job.

Customers will enter a relationship with this startup by completing a straight-forward signup form that collects the required data. To prevent this information from being intercepted by a malicious party or potentially leaked in the event of a breach, we’ll use TozStore to collect the information:


<html>
<head>
  <script type="text/javascript" src="https://js.innovault.io/1.0.2/innovault-easy.min.js" integrity="sha384-0RHUIWE2AUtHboknEpzdRU6jIMuxKEOmGcgnZyhQsRmwTnVYttQFhldp6Be9chFD" crossorigin="anonymous"></script>

<body>
  <h1>Customer Sign Up</h1>
  <form data-innovault-token="..." method="post">
    <p>
      <label for="fullname">Full Name</label>
      <input data-innovault-type="fullname" />
    </p>

    <hr />

    <p>
      <label for="address1">Address</label>
      <input data-innovault-type="address1" />
      <input data-innovault-type="address2" />
    </p>
    <p>
      <label for="city">City</label>
      <input data-innovault-type="city" />
    </p>
    <p>
      <label for="state">State</label>
      <input data-innovault-type="state" />
    </p>
    <p>
      <label for="zip">Zip</label>
      <input data-innovault-type="zip" />
    </p>

    <hr />

    <p>
      <label for="age">Age</label>
      <input data-innovault-type="age" />
    </p>
    <p>
      <label for="height">Height</label>
      <input data-innovault-type="height" />
    </p>
    <p>
      <label for="weight">Weight</label>
      <input data-innovault-type="weight" />
    </p>

    <p>
      <label for="comments">Other Comments</label>
      <textarea data-innovault-type="comments"></textarea>
    </p>

    <p>
      <button type="submit" onclick="clearForm()">Get Started!</button>
    </p>
  </form>
  <script type="text/javascript">
    alert('Thanks for signing up!');
  </script>
</body>
</html>

This example uses the easy variant of the TozStore SDK that automatically tokenizes string fields in the form submission. If radio buttons or select boxes were required, we’d need to use the web variant of the SDK instead (as we did last week).

When our new customers submit this form, the data is automatically collected into a JSON document, encrypted in the browser, then submitted to TozStore for storage. The form itself will submit a data item called innovault_record_id to whatever server is specified in the form’s action parameter – this can be used later to extract individual records, but isn’t necessary for this example itself.

Data Extraction and Sharing

While all of the data collected in the form above will be stored in an encrypted database, we want to share a subset of this data with a couple of other parties. To do that, we want to temporarily extract this data with a script and generate two different types of data we’ll write separately into the encrypted system.

The e3db platform will then empower us to securely share these new record types with a third party of our choice. The data is only ever encrypted by our script and then at the other end of the transaction by the third party who needs to use this data. For example, we want to separate data into marketing details (contact information) and anonymized health data. Each component will be written as a separate type.

For this example, all of the scripts will be written using the PHP SDK for e3db.

This first script parses the entire account record into two objects, one representing contact information and one just the health information (thus keeping the health data anonymous).


$config = new \Tozny\E3DB\Config(
    getenv('CLIENT_ID'),
    getenv('API_KEY_ID'),
    getenv('API_SECRET'),
    getenv('PUBLIC_KEY'),
    getenv('PRIVATE_KEY'),
    getenv('API_URL')
);

$connection = new \Tozny\E3DB\GuzzleConnection($config);
$client = new \Tozny\E3DB\Client($config, $connection);

$data = true;
$raw = false;
$writer = null;
$record = null;
$type = 'account';
$client->query($data, $raw, $writer, $record, $type);
foreach($records as $record) {
  $client->write('contact', [
    'name'     => $record->data['fullname'],
    'address1' => $record->data['address1'],
    'address2' => $record->data['address2'],
    'city'     => $record->data['city'],
    'state'    => $record->data['state'],
    'zip'      => $record->data['zip'],
  ]);

  $client->write('health', [
    'age'    => $record->data['age'],
    'height' => $record->data['height'],
    'weight' => $record->data['weight'],
  ]);
}

The last step is to share the data with a third party. Given the ID of an e3db client controlled by the marketing company, sharing the contact records becomes a matter of:


$config = new \Tozny\E3DB\Config(
    getenv('CLIENT_ID'),
    getenv('API_KEY_ID'),
    getenv('API_SECRET'),
    getenv('PUBLIC_KEY'),
    getenv('PRIVATE_KEY'),
    getenv('API_URL')
);

$connection = new \Tozny\E3DB\GuzzleConnection($config);
$client = new \Tozny\E3DB\Client($config, $connection);

$marketing_id = '11111111-1111-1111-1111-111111111111';
$health_id = '22222222-2222-2222-2222-222222222222';

$client->share('contact', $marketing_id);
$client->share('health', $health_id);

The only difference between the sharing operations is the client ID used during the share operation. Also, record types only need to be shared once. The next time a health or contact record are written by this particular client they’ll be available to these secondary clients immediately.

Next Steps

TozStore is a great piece of technology for securely collecting data from end users through a browser. When paired with the full e3db SDK on a secure server, it becomes both a data collection and secure collaboration platform.

A next step would be to leverage the Java SDK with a hosted utility like Amazon Lambda. A secure environment will allow for the extraction and re-sharing of data without ever exposing the full collection to any one person.

A next step for anyone just getting started, would be to create a TozStore account and give the platform a try. It’s free for the first 30 days to give developers a chance to get hands-on experience before making a commitment.