Virtru SDK for JavaScript

The Virtru SDK allows developers to securely and easily encrypt and manage authenticated access to sensitve data. This comprehensive documentation serves as the source of truth for the functionality and usage of the Virtru JavaScript SDK.

TDF Architecture

For more information, please see the Virtru Developer Hub or join us on Slack.

Core Concepts

  • TDF Ciphertext - Ciphertext encrypted using the open TDF specification. Each TDF ciphertext is created using a unique data key and managed with independent access controls. See the Developer Hub for more information.
  • Virtru Policy - A policy specifying access controls that will be enforced on encrypted data, such as expiration and authorized users.
  • User - An entity authenticated with Virtru. SDK users can grant and revoke other users' access to encrypted data. For instance, alice@example.com can authorize bob@example.com access to some encrypted data, either at encryption-time or any time afterwords.

Getting Started (Node)

The SDK is available on the global npm registry. First, install the virtru-sdk npm package:

npm install virtru-sdk
# Optionally verify installation:
node -e "console.log(require('virtru-sdk').Version)" 

Virtru credentials can be generated from the Virtru dashboard's developer settings. These credentials can be used to construct a Client and start encrypting data. For a complete walkthrough, please see the NodeJs Getting Started page on the Developer Hub.

async function sampleFunc() {
  const email = 'dathon@tamarian.gov';
  const appId = '12345678-1234-1234-1234-1234567890ab'; // Generated from the Virtru dashboard.
  const client = new Virtru.Client({email, appId});

  const encryptParams = new Virtru.EncryptParamsBuilder()
    .withStringSource('Sokath, his eyes open!')
    .withDisplayFilename('darmok.txt')
    .build();
  const ct = await client.encrypt(encryptParams);
  await ct.toFile('encrypted.html');
}

Getting Started (Browser)

The SDK is also available in minified, browser-ready form via a Virtru CDN. It can be included using the <script> tags shown below. This will load both the SDK itself as well as an auth widget to handle authenticating browser users with Virtru. For a complete walkthrough, please see the Browser Getting Started page on the Developer Hub.

<!DOCTYPE html>
<html>
<head>
    <title>Virtru SDK for JavaScript - Sample Application</title>
    <link href="https://sdk.virtru.com/js/latest/auth-widget/index.css" rel="stylesheet"/>
    <script src="https://sdk.virtru.com/js/latest/auth-widget/index.js"></script>
    <script src="https://sdk.virtru.com/js/latest/virtru-sdk.min.js"></script>
</head>

<body>
  <div id="virtru-auth-widget-mount"></div>
  <script type="text/javascript">
    async function afterAuth(email) {
      // Run all client code from here. 
      // This will only be called when the user is successfully authentciated.
      const client = new Virtru.Client({email});
      const encryptParams = new Virtru.EncryptParamsBuilder()
        .withStringSource('Sokath, his eyes open!')
        .withDisplayFilename('darmok.txt')
        .build();
      ct = await client.encrypt(encryptParams);
      await ct.toFile('encrypted.html');
    }
    // Set up the auth widget.
    Virtru.AuthWidget('virtru-auth-widget-mount', {afterAuth});
  </script>
</body>
</html>

Encrypting Data

When encrypting data you can use withUsersWithAccess() to specify the authenticated users to share the data with. In this example, the encrypted data will be available for picard@enterprise.fed to decrypt.

// Configure and execute an encrypt.
// The creator (dathon@tamarian.gov) always has access, so we don't need to specify him as an authorized user.
const encryptParams = new Virtru.EncryptParamsBuilder()
  .withStringSource('Sokath, his eyes open!')
  .withUsersWithAccess(['picard@enterprise.fed'])
  .build();
const ct = await client.encrypt(encryptParams);

You can use the builtin helper functions to write out the ciphertext or use standard stream processing techniques.

await ct.toFile('encrypted.html');

Decrypting Data

Data encrypted with the TDF HTML format (the default) can be decrypted by opening up the file in your browser and authenticating with Secure Reader. The SDK also supports programmatic decryption for both HTML and zip formats (automatically detected).

If the client is authorized for access, decrypt returns a Readable stream containing the decrypted plaintext and helper methods for writing.

// Configure the parameters to decrypt a local file.
const decryptParams = new Virtru.DecryptParamsBuilder()
  .withFileSource('encrypted.html')
  .build();

// Run the decrypt.
const pt = await client.decrypt(decryptParams);

// Write the plaintext result to the console.
console.log(await pt.toString()); // Prints "Sokath, his eyes open!"

Common Use-Cases

This section lists some example usages using the Virtru SDK. See the Developer Hub for full examples of a wide range of common use-cases.

Example: Encrypting data with expiration.

// Initialize the client and destination directory.
const client = new Virtru.Client({email, appId});
// Construct an authorization policy to apply to the encrypted data.
// Note that *expiration only applies to other users*, not the creator.
const policy = new Virtru.PolicyBuilder()
  .enableExpirationDeadlineFromNow(60) // Expires in one minute.
  .build();

// Configure the encrypt parameters to encrypt a provided string.
const encryptParams = new Virtru.EncryptParamsBuilder()
  .withStringSource('I expire in 60 seconds')
  .withUsersWithAccess(['bob@example.com', 'charlie@example.com'])
  .withPolicy(policy)
  .build();

// Run the encrypt and write the result to stdout.
const ct = await client.encrypt(encryptParams);
await ct.toFile('expiresSoon.html');

Example: Encrypting and uploading a file to S3.

// Initialize the Virtru and S3 clients.
const client = new Virtru.Client({email, appId});
const s3 = new AWS.S3();
// Derive the object key to use by appending .html for easy browser support.
const key = `${localFilename}.html`;
const encryptParams = new Virtru.EncryptParamsBuilder()
    .withFileSource(localFilename)
    .withDisplayFilename(localFilename)
    .build();
// The returned stream can be passed directly to s3.upload().
client.encrypt(encryptParams).then(ct =>
 s3.upload({Body: ct, Bucket: bucketName, Key: key, ContentType: 'html/text'}, onComplete));

function onComplete(err, data) {
  console.log(`${localFilename} encrypted and uploaded to S3 as ${key}`);
}

Example: Setting users to be authorized after encryption.

// Configure the encrypt parameters to encrypt a provided string.
const client = new Virtru.Client({email, appId});
const encryptParams = new Virtru.EncryptParamsBuilder()
  .withStringSource('Secrets!')
  .build();
const policyId = encryptParams.getPolicyId();

// Run the encrypt and write the result to stdout.
const ct = await client.encrypt(encryptParams);
await ct.toFile('secrets.html');

// Time passes...

// Some time later we decide to grant bob access to the data.

// First we fetch the Policy. This MUST be done before updating it.
// We assume the policyId is still in memory - if not it can be pulled from the TDF ciphertext
// using `client.getPolicyId(decryptParams)`.
const policy = await client.fetchPolicy(policyId)

// Update the policy locally, adding the new user.
const updatedPolicy = policy.builder().addUsersWithAccess('bob@example.com').build();

// Commit the update to the Virtru backend.
await client.updatePolicy(updatedPolicy);

// Now bob can decrypt!

Getting Help

There are many ways to get our attention.

  • You can join Virtru's Developer Hub Community Slack channel to get your questions answered.
  • You can open a support ticket here.