API Reference

Ubiq Platform

Introduction

The Ubiq Platform Client Libraries involve three basic components, Credentials, Encryption, and Decryption in order to provide authentication and authorization, data encryption, and data decryption, respectively.

The Client Libraries are programming language specific and provide the interfaces necessary to interact with these components in order to accomplish the necessary tasks.

Credentials / Authentication

The Ubiq Dashboard allows users to create API Key Credentials that are used to authorize and authenticate encryption / decryption requests. Once the API Key Credentials have been created, the How to Use API Key Credentials guide explains the four different ways that the credentials can be set.

Your API Key Credentials carry many privileges, so be sure to keep them secure! Do not share these credentials in any publicly accessible areas such as GitHub, GitLab, client-side source code, and so forth.

Encryption / Decryption

There are two basic interfaces for encrypting / decrypting data:

  1. Simple Interfaces
  2. Piecewise Interfaces

1. Simple Interfaces

The Simple Interfaces are the simplest to incorporate into an application. The Simple Interfaces also require the entire block of data to be in memory at once, which may not be possible for large data elements or on resource constrained devices.

Pass credentials and the data and get back either the encrypted data or the plaintext data.

To Encrypt

import ubiq_security as ubiq

encrypted_data = ubiq.encrypt(credentials, plaintext_data)
require "ubiq-security"
include Ubiq

encrypted_data = encrypt(credentials, plaintext_data)
const ubiq = require('ubiq-security')

const encrypted_data = await ubiq.encrypt(credentials, plainntext_data)
#include <ubiq/platform.h>

struct ubiq_platform_credentials * creds = NULL;
void * ptbuf = NULL, * ctbuf = NULL;
size_t ptlen = 0, ctlen = 0;

/* initialize ptbuf and ptlen */
...

ubiq_platform_credentials_create(&creds);
ubiq_platform_encrypt(creds, ptbuf, ptlen, &ctbuf, &ctlen);
free(ctbuf);
ubiq_platform_credentials_destroy(creds);
#include <ubiq/platform.h>

ubiq::platform::credentials creds;
std::vector<std::uint8_t> ctbuf;
void * ptbuf;
size_t ptlen;

/* initialize ptbuf and ptlen */
...

ctbuf = ubiq::platform::encrypt(creds, ptbuf, ptlen);
using UbiqSecurity;

byte[] plainBytes = ...;
byte[] encryptedBytes = await UbiqEncrypt.EncryptAsync(credentials, plainBytes);
import ubiqsecurity.UbiqCredentials;
import ubiqsecurity.UbiqEncrypt;

UbiqCredentials credentials = ...;
byte[] plainBytes = ...;
byte[] encryptedBytes = UbiqEncrypt.encrypt(credentials, plainBytes);
var pt []byte = ...
credentials, err := ubiq.NewCredentials()
ct, err := ubiq.Encrypt(credentials, pt)
$credentials = new Ubiq\Credentials();
$ct = Ubiq\encrypt($credentials, $pt);

To Decrypt

import ubiq_security as ubiq

plaintext_data = ubiq.decrypt(credentials, encrypted_data)
require "ubiq-security"
include Ubiq

plaintext_data = decrypt(credentials, encrypted_data)
const ubiq = require('ubiq-security')

const plainttext_data = await ubiq.decrypt(credentials, encrypted_data)
#include <ubiq/platform.h>

struct ubiq_platform_credentials * creds = NULL;
void * ptbuf = NULL, * ctbuf = NULL;
size_t ptlen = 0, ctlen = 0;

/* initialize ctbuf and ctlen */
...

ubiq_platform_credentials_create(&creds);
ubiq_platform_decrypt(creds, ctbuf, ctlen, &ptbuf, &ptlen);
free(ptbuf);
ubiq_platform_credentials_destroy(creds);
#include <ubiq/platform.h>

ubiq::platform::credentials creds;
std::vector<std::uint8_t> ptbuf;
void * ctbuf;
size_t ctlen;

/* initialize ctbuf and ctlen */
...

ptbuf = ubiq::platform::decrypt(creds, ctbuf, ctlen);
using UbiqSecurity;

byte[] encryptedBytes = ...;
byte[] plainBytes = await UbiqDecrypt.DecryptAsync(credentials, encryptedBytes);
import ubiqsecurity.UbiqCredentials;
import ubiqsecurity.UbiqDecrypt;

UbiqCredentials credentials = ...;
byte[] encryptedBytes = ...;
byte[] plainBytes = UbiqDecrypt.decrypt(credentials, encryptedBytes);
var ct []byte = ...
credentials, err := ubiq.NewCredentials()
pt, err := ubiq.Decrypt(credentials, ct)
$credentials = new Ubiq\Credentials();
$pt = Ubiq\decrypt($credentials, $ct);

2. Piecewise Interfaces

Piecewise Interfaces must be used when a data element cannot be loaded into memory at one time either because it is too large or it is not all available at once such as data from a streaming video feed.

Piecewise Interfaces can also be faster in some cases when encrypting data, such as bulk data import, if the encryption key can be reused but with a different initialization vector.

To Encrypt

Correct implementation using the Piecewise Interfaces will be:

  1. Create an encryption object using the API Key Credentials
  2. Call the encryption instance begin method
  3. Call the encryption instance update method repeatedly until all the data is processed
  4. Call the encryption instance end method

If separate data elements need to be encrypted using the same data key, repeat steps 2-4 above

import ubiq_security as ubiq

# Process 1 MiB of plaintext data at a time
BLOCK_SIZE = 1024 * 1024

# Rest of the program
....

   # Step 1 - The uses parameter indicates the maximum number of
   # times this encryption object can be used to encrypt data.
   encryption = ubiq.encryption(creds = credentials, uses = 2)

   # Step 2 - Start the encryption Process
   # Write out the header information
   encrypted_data = encryption.begin()
    
   # Loop until the end of the input file is reached
   while True:
       data = infile.read(BLOCK_SIZE)
       # Step 3 - Call update() repeatedly until all the data is processed
       encrypted_data += encryption.update(data)
       if (len(data) != BLOCK_SIZE):
          break

   # Step 4 - Call the end() method when this data element is complete.
   # Make sure any additional encrypted data is retrieved from encryption instance
   # and resources are freed
   encrypted_data += encryption.end()
   
   
   # Repeat steps 2 - 4 for new data elements
   encrypted_data2 = encryption.begin()
   # Loop until the end of the input file is reached
   while True:
       data = infile2.read(BLOCK_SIZE)
       # Step 3 - Call update() repeatedly until all the data is processed
       encrypted_data2 += encryption.update(data)
       if (len(data) != BLOCK_SIZE):
          break

   # Step 4 - Call the end() method when this data element is complete.
   # Make sure any additional encrypted data is retrieved from encryption instance
   # and resources are freed
   encrypted_data2 += encryption.end()
require "ubiq-security"
include Ubiq

# Process 1 MiB of plaintext data at a time
BLOCK_SIZE = 1024 * 1024

# Rest of the program
....
   encryption = Encryption.new(credentials, 1)

   # Write out the header information
   encrypted_data = encryption.begin()
    
   # Loop until the end of the input file is reached
    until infile.eof?
      chunk = infile.read BLOCK_SIZE
      encrypted_data += encryption.update(chunk)
    end
    # Make sure any additional encrypted data is retrieved from encryption instance
    encrypted_data += encryption.end()
   
    # Make sure to release any resources used during the encryption process
    encryption.close()
const ubiq = require('ubiq-security')

// Process 1 MiB of plaintext data at a time
const BLOCK_SIZE = 1024 * 1024

//Rest of the program
...
  var readStream = fs.createReadStream(input_file,{ highWaterMark: BLOCK_SIZE  });

  let enc = await new ubiq.Encryption(credentials, 1);
 // Write out the header information
  let encrypted_data = enc.begin()
  
  readStream.on('data', function(chunk) {
    encrypted_data += enc.update(chunk)
  }).on('end', function() {
      encrypted_data += enc.end()
      enc.close()
  });
#include <ubiq/platform.h>

/* Process 1 MiB of plaintext data at a time */
#define BLOCK_SIZE  (1024 * 1024)

struct ubiq_platform_credentials * credentials = NULL;
struct ubiq_platform_encryption * enc = NULL;
void * ctbuf = NULL, * buf = NULL;
size_t ctlen = 0, len = 0;

ubiq_platform_credentials_create(&credentials);
ubiq_platform_encryption_create(credentials, 1, &enc);

ubiq_platform_encryption_begin(enc, &buf, &len);
ctbuf = realloc(ctbuf, ctlen + len);
memcpy(ctbuf + ctlen, buf, len);
ctlen += len;
free(buf);

while (!feof(infp)) {
    char ptbuf[BLOCK_SIZE];
    size_t ptsize;

    ptsize = fread(ptbuf, 1, BLOCK_SIZE, infp);
    ubiq_platform_encryption_update(enc, ptbuf, ptsize, &buf, &len);
    ctbuf = realloc(ctbuf, ctlen + len);
    memcpy(ctbuf + ctlen, buf, len);
    ctlen += len;
    free(buf);
}

ubiq_platform_encryption_end(enc, &buf, &len);
ctbuf = realloc(ctbuf, ctlen + len);
memcpy(ctbuf + ctlen, buf, len);
ctlen += len;
free(buf);

ubiq_platform_encryption_destroy(enc);
ubiq_platform_credentials_destroy(credentials);
#include <ubiq/platform.h>

/* Process 1 MiB of plaintext data at a time */
#define BLOCK_SIZE  (1024 * 1024)

ubiq::platform::credentials credentials;
ubiq::platform::encryption enc(credentials, 1);
std::vector<std::uint8_t> ctbuf, buf;

ctbuf = enc.begin();

while (!infile.eof()) {
    std::vector<char> ptbuf(BLOCK_SIZE);

    infile.read(ptbuf.data(), ptbuf.size());
    ptbuf.resize(infile.gcount());
    buf = enc.update(ptbuf.data(), ptbuf.size());
    ctbuf.insert(ctbuf.end(), buf.begin(), buf.end());
}

buf = enc.end();
ctbuf.insert(ctbuf.end(), buf.begin(), buf.end());
async Task PiecewiseEncryptionAsync(string inFile, string outFile, IUbiqCredentials ubiqCredentials)
{
    using (var plainStream = new FileStream(inFile, FileMode.Open))
    {
        using (var cipherStream = new FileStream(outFile, FileMode.Create))
        {
            using (var ubiqEncrypt = new UbiqEncrypt(ubiqCredentials, 1))
            {
                // start the encryption
                var cipherBytes = await ubiqEncrypt.BeginAsync();
                cipherStream.Write(cipherBytes, 0, cipherBytes.Length);

                // process 128KB at a time
                var plainBytes = new byte[0x20000];

                // loop until the end of the input file is reached
                int bytesRead = 0;
                while ((bytesRead = plainStream.Read(plainBytes, 0, plainBytes.Length)) > 0)
                {
                    cipherBytes = ubiqEncrypt.Update(plainBytes, 0, bytesRead);
                    cipherStream.Write(cipherBytes, 0, cipherBytes.Length);
                }

                // finish the encryption
                cipherBytes = ubiqEncrypt.End();
                cipherStream.Write(cipherBytes, 0, cipherBytes.Length);
            }
        }
    }
}
static void piecewiseEncryption(String inFile, String outFile, UbiqCredentials ubiqCredentials)
        throws IOException, IllegalStateException, InvalidCipherTextException {
    try (FileInputStream plainStream = new FileInputStream(inFile)) {
        try (FileOutputStream cipherStream = new FileOutputStream(outFile)) {
            try (UbiqEncrypt ubiqEncrypt = new UbiqEncrypt(ubiqCredentials, 1)) {
                // start the encryption
                byte[] cipherBytes = ubiqEncrypt.begin();
                cipherStream.write(cipherBytes);

                // process 128KB at a time
                var plainBytes = new byte[0x20000];

                // loop until the end of the input file is reached
                int bytesRead = 0;
                while ((bytesRead = plainStream.read(plainBytes, 0, plainBytes.length)) > 0) {
                    cipherBytes = ubiqEncrypt.update(plainBytes, 0, bytesRead);
                    cipherStream.write(cipherBytes);
                }

                // finish the encryption
                cipherBytes = ubiqEncrypt.end();
                cipherStream.write(cipherBytes);
            }
        }
    }
}
var pt []byte = make([]byte, 128*1024)

credentials, _ := ubiq.NewCredentials()
encryption, _ := ubiq.NewEncryption(credentials, 1)
defer encryption.Close()

ct, _ := encryption.Begin()
for {
        n, e := infile.Read(pt)
        if e == io.EOF {
                break
        }
        t, _ := encryption.Update(pt[:n])
        ct = append(ct, t...)
}
t, _ := encryption.End()
$credentials = new Ubiq\Credentials();
$encryption = new Ubiq\Encryption($credentials, 1);

$pt = fread($infile, $filesize);

$ct  = $encryption->begin();
$ct .= $encryption->update($pt);
$ct .= $encryption->end();

To Decrypt

Correct implementation using the Piecewise Interfaces will be:

  1. Create a decryption object using the API Key Credentials
  2. Call the decryption instance begin method
  3. Call the decryption instance update method repeatedly until all the data is processed
  4. Call the decryption instance end method
import ubiq_security as ubiq

# Process 1 MiB of encrypted data at a time
BLOCK_SIZE = 1024 * 1024

# Rest of the program
....

    # Step 1 - Create the decryption object
    decryption = ubiq.decryption(creds)

    # Step 2 - Start the decryption process
    # Start the decryption and get any header information
    plaintext_data = decryption.begin()

    # Loop until the end of the input file is reached
    while True:
        data = infile.read(BLOCK_SIZE)
        # Step 3 - Call the decryption process repeatedly until all data is processed
        plaintext_data += decryption.update(data)
        if (len(data) != BLOCK_SIZE):
            break

    # Step 4 - Call the end() method when this data element is complete.
    # Make sure an additional plaintext data is retrieved and
    # release any allocated resources
    plaintext_data += decryption.end()
require "ubiq-security"
include Ubiq

# Process 1 MiB of encrypted data at a time
BLOCK_SIZE = 1024 * 1024

# Rest of the program
....

    decryption = Decryption(credentials)

    # Start the decryption and get any header information
    plaintext_data = decryption.begin()

    # Loop until the end of the input file is reached
    until infile.eof?
      chunk = infile.read BLOCK_SIZE
      plaintext_data += decryption.update(chunk)
    end
    
    # Make sure an additional plaintext data is retrieved from decryption instance
    plaintext_data += decryption.end()
    
    # Make sure to release any resources used during the decryption process
    decryption.close()
const ubiq = require('ubiq-security')

// Process 1 MiB of plaintext data at a time
const BLOCK_SIZE = 1024 * 1024

  let dec = new ubiq.Decryption(credentials)
  let plainttext_data = dec.begin()

  readStream.on('data', async function(chunk) {
    readStream.pause()
    await dec.update(chunk).then(function(response){
    if(response){
        plainttext_data += response
      }
    })
    readStream.resume()
  }).on('end', async function() {
      plainttext_data += dec.end()
      dec.close()
  });
#include <ubiq/platform.h>

/* Process 1 MiB of plaintext data at a time */
#define BLOCK_SIZE  (1024 * 1024)

struct ubiq_platform_credentials * credentials = NULL;
struct ubiq_platform_decryption * dec = NULL;
void * ptbuf = NULL, * buf = NULL;
size_t ptlen = 0, len = 0;

ubiq_platform_credentials_create(&credentials);
ubiq_platform_decryption_create(credentials, &dec);

ubiq_platform_decryption_begin(dec, &buf, &len);
ptbuf = realloc(ptbuf, ptlen + len);
memcpy(ptbuf + ptlen, buf, len);
ptlen += len;
free(buf);

while (!feof(infp)) {
    char ctbuf[BLOCK_SIZE];
    size_t ctsize;

    ctsize = fread(ctbuf, 1, BLOCK_SIZE, infp);
    ubiq_platform_decryption_update(dec, ctbuf, ctsize, &buf, &len);
    ptbuf = realloc(ptbuf, ptlen + len);
    memcpy(ptbuf + ptlen, buf, len);
    ptlen += len;
    free(buf);
}

ubiq_platform_decryption_end(dec, &buf, &len);
ptbuf = realloc(ptbuf, ptlen + len);
memcpy(ptbuf + ptlen, buf, len);
ptlen += len;
free(buf);

ubiq_platform_decryption_destroy(dec);
ubiq_platform_credentials_destroy(credentials);
#include <ubiq/platform.h>

/* Process 1 MiB of plaintext data at a time */
#define BLOCK_SIZE  (1024 * 1024)

ubiq::platform::credentials credentials;
ubiq::platform::decryption dec(credentials);
std::vector<std::uint8_t> ptbuf, buf;

ptbuf = dec.begin();

while (!infile.eof()) {
    std::vector<char> ctbuf(BLOCK_SIZE);

    infile.read(ctbuf.data(), ctbuf.size());
    ctbuf.resize(infile.gcount());
    buf = dec.update(ctbuf.data(), ctbuf.size());
    ptbuf.insert(ptbuf.end(), buf.begin(), buf.end());
}

buf = dec.end();
ptbuf.insert(ptbuf.end(), buf.begin(), buf.end());
async Task PiecewiseDecryptionAsync(string inFile, string outFile, IUbiqCredentials ubiqCredentials)
{
    using (var cipherStream = new FileStream(inFile, FileMode.Open))
    {
        using (var plainStream = new FileStream(outFile, FileMode.Create))
        {
            using (var ubiqDecrypt = new UbiqDecrypt(ubiqCredentials))
            {
                // start the decryption
                var plainBytes = ubiqDecrypt.Begin();
                plainStream.Write(plainBytes, 0, plainBytes.Length);

                // process 128KB at a time
                var cipherBytes = new byte[0x20000];

                // loop until the end of the input file is reached
                int bytesRead = 0;
                while ((bytesRead = cipherStream.Read(cipherBytes, 0, cipherBytes.Length)) > 0)
                {
                    plainBytes = await ubiqDecrypt.UpdateAsync(cipherBytes, 0, bytesRead);
                    plainStream.Write(plainBytes, 0, plainBytes.Length);
                }

                // finish the decryption
                plainBytes = ubiqDecrypt.End();
                plainStream.Write(plainBytes, 0, plainBytes.Length);
            }
        }
    }
}
static void piecewiseDecryption(String inFile, String outFile, UbiqCredentials ubiqCredentials)
        throws FileNotFoundException, IOException, IllegalStateException, InvalidCipherTextException {
    try (FileInputStream cipherStream = new FileInputStream(inFile)) {
        try (FileOutputStream plainStream = new FileOutputStream(outFile)) {
            try (UbiqDecrypt ubiqDecrypt = new UbiqDecrypt(ubiqCredentials)) {
                // start the decryption
                byte[] plainBytes = ubiqDecrypt.begin();
                plainStream.write(plainBytes);

                // process 128KB at a time
                var cipherBytes = new byte[0x20000];

                // loop until the end of the input file is reached
                int bytesRead = 0;
                while ((bytesRead = cipherStream.read(cipherBytes, 0, cipherBytes.length)) > 0) {
                    plainBytes = ubiqDecrypt.update(cipherBytes, 0, bytesRead);
                    plainStream.write(plainBytes);
                }

                // finish the decryption
                plainBytes = ubiqDecrypt.end();
                plainStream.write(plainBytes);
            }
        }
    }
}
var ct []byte = make([]byte, 128*1024)

credentials, _ := ubiq.NewCredentials()
decryption, _ := ubiq.NewDecryption(credentials)
defer decryption.Close()

pt, _ := decryption.Begin()
for {
        n, e := infile.Read(ct)
        if e == io.EOF {
                break
        }
        t, _ := decryption.Update(ct[:n])
        pt = append(pt, t...)
}
t, _ := decryption.End()
$credentials = new Ubiq\Credentials();
$encryption = new Ubiq\Decryption($credentials, 1);

$ct = fread($infile, $filesize);

$pt  = $decryption->begin();
$pt .= $decryption->update($ct);
$pt .= $decryption->end();

Exceptions

While communicating with the Ubiq Platform, encrypting and decrypting data will normally complete without any exceptions. However, the Ubiq Client Library and associated libraries it uses can raise exceptions under certain circumstances and good programming practice would include enclosing the Ubiq Client Library commands within a try / except block.

Example:

try:
       ct = ubiq.encrypt(creds, data)
       outfile.write(ct)
    except Exception as err:
       print("Error performing encryption: ", repr(err))

The following are some of the typical exceptions that can raised during the encryption or decryption process due to incorrect credentials, data, or library use:

In the above example presented, for example in Python, the repr() function will provide some details regarding the actual error.