Circle API Demos

Circle Data

Circle Data

End-to-End Data Protection

A secure way to send an encrypted email, secured by Circle Data

What this demo shows

Most encrypted email systems claim to be secure since they leverage an external key store to hold the keys used to encrypt and decrypt the email. The problem is when the message needs to be displayed; the server needs to ask the external key store for the decryption key, which means that while the server doesn't store the key locally, it can still get it.

How is that secure? It's not. 

Introducing a better way: end-to-end data encryption with Circle Data API.

Video

This video provides a quick explanation and introduction of what the Authorization APIs do.

Code tips

The code shown here is designed for Outlook 365 but the flow should be basically the same for any other client. We are going to show the parts of the add-in that deal with Circle since this is about using Circle API not how to write an Outlook add-in.

 

Here is an Outlook task panel boilerplate project following this.

https://docs.microsoft.com/en-us/office/dev/add-ins/quickstarts/outlook-quickstart?tabs=yeomangenerator.

const appKey = "FROM YOUR CONFIGURATION";

const circleId = "ENTER CIRCLE ID HERE";
const topicId = "ENTER TOPIC ID HERE";

Office.onReady(async (info) => {
  if (info.host === Office.HostType.Outlook) {

    let isRunning = await Circle.isServiceRunning();
    if (isRunning)
    {
      let token = await getCircleToken();
      let iniResult = await Circle.initialize(appKey, token);

      if (iniResult && iniResult.Status.Result) {
        console.log("Initialized.");

        // CircleService is running and token is authorized
        let circles = await Circle.enumCircles();
        console.log("enumCircles done.");
      }
      else {
        document.getElementById('runningResult').innerText = 'Failed to get permission.';
        console.log("initialized failed.");
      }
    }
  }
});

// this is just for this testing, the actual token should be coming from your web server
async function getCircleToken() {
    const url = "https://us-central1-serious-app-273117.cloudfunctions.net/circleLicense/api/demo/token?t=1";
    return fetch(url).then((res) => res.json()).then((objJson) => { return objJson.Token; });
}

 

Button is added to the task pane called encrypt and hooked up this handler

export async function encrypt() {
  // Get a reference to the current message
  var item = Office.context.mailbox.item;
  item.body.getAsync("html", encryptSetbody);  // get the body of the email 
}

async function encryptSetbody(asyncResult) {
// convert the body to base64 so we can encrypt it let base64String = utf8_to_b64(asyncResult.value);
// use the Circle and topic ID you want to encrypt with let r = await Circle.secureContents(circleId, topicId, base64String, true); // now generate the new body that includes the URL of the encrypted file let emailHtml = "<div style='text-align: center;'> <p>Click the Cirlce Logo below to view the email.</p>
<a href=https://demosupport20220414211325.azurewebsites.net/Home/Render?url="+ r.SecureFileUrl+">
<img src='https://circleauth.circlesecurity.ai/demo/files/circle-logo-nocompromise.svg'</a><p><br/>This email is secured by Circle.</p>
</div>" // Get a reference to the current message var item = Office.context.mailbox.item; try { await item.body.setAsync(emailHtml, { coercionType: Office.CoercionType.Html, asyncContext: { var3: 1, var4: 2 } }); } catch(ex) { console.log(ex); } }

 

Later, when we need to render the document on our web server, here’s the Javascript that we use. The URL to the encrypted email (from the encrypt phase above) is passed in.

async function checkCircleServiceIsRunning() {
    let isRunning = await Circle.isServiceRunning();
    if (isRunning) {
        document.getElementById('status').innerText = 'Requesting permission, please wait.';
    } else {
        document.getElementById('status').innerText = 'Could not find CircleService';
        return false;
    }

    let token = await getCircleToken();
    document.getElementById('status').innerText = 'Initializing Circle Service for Circle Data functions.';

    let iniResult = await Circle.initialize(appKey, token);
    if (iniResult && iniResult.Status.Result) {
        console.log("Initialized.");
        document.getElementById('status').innerText = 'Initialized';
    }
    return true;
}

async function DecryptAndLoad(circleFileUrl) {
    console.log(fileUrl);
    document.getElementById('status').innerText = 'Circle Service is decrypting message. Please wait...';
    document.getElementById('spinner').visibility = "visible";

    var v = await Circle.getSecureFileContents("", circleFileUrl); // get the decrypted Base64 
    var html = atob(v.FileData); 
    document.open();  // replace the entire document with the email contents.
    document.write(html);
    document.close();
}

async function RenderORama(circleFileUrl)
{
    await checkCircleServiceIsRunning();
    await DecryptAndLoad(circleFileUrl);

}

window.onload = function () {
    RenderORama(fileUrl);
}

 

Want to see more?

There are more sophisticated features that we can show, including the console and code walkthrough. If you are interested, please contact us for a demo.