After a Tanker session has been started, it can be used to encrypt and decrypt data.

In this section, we'll see how to use the encryption APIs to protect textual data (e.g pieces of text, fields of database records, json payloads).

The encryption of binary resources of any size (e.g. files, documents, photos, videos) is covered here.

Encrypting

To encrypt a piece of textual data, you need to call encrypt():

const clearText = "This is a secret message";
const encryptedData = await tanker.encrypt(clearText);

Note that the JavaScript API takes a string as input and returns binary data as a Uint8Array object.

In case the rest of your application cannot deal with Uint8Array, you can use the toBase64() utility function:

import { toBase64 } from '@tanker/client-browser';

const clearText = "This is a secret message";
const encryptedData = await tanker.encrypt(clearText);
const encryptedText = toBase64(encryptedData);

Note that the Java API takes binary input and returns binary output as byte[] objects.

String message = "This is a secret message";
byte[] encryptedData = tanker.encrypt(message.getBytes(), null).get();
NSString* message = @"This is a secret message";
[self.tanker encryptString:message
         completionHandler:^(NSData* encryptedData, NSError* err) {
                             if (err == nil) {
                               // handle encrypted data
                             }
                           }];

Note

Please note that Tanker does not transfer nor store the encrypted data. For it to be available to your users later and across devices, you need to store it yourself.

Tanker does not expose encryption keys. They will automatically be accessible to the users with whom the data is shared.

Sharing

By default, encrypt() ensures that a user's encrypted data can only be decrypted on all devices of this user. No one else can decrypt() those data.

You can specify additional recipients by providing their Tanker public identity to encrypt() options:

// Ask the application server for Bob and Charlie's public identities
const publicIdentities = await app.getPublicIdentities(['bob-id', 'charlie-id']);
const encryptedData = await tanker.encrypt(clearText, { shareWithUsers: publicIdentities });
NSString* message = @"This is a secret message";
NSArray<NSString*>* identities = [self.app getPublicIdentities:@[@"bob-id", @"charlie-id"]];
TKREncryptionOptions *encryptOptions = [TKREncryptionOptions options];
encryptOptions.shareWithUsers = identities;

[self.tanker encryptString:message,
                   options:encryptOptions,
         completionHandler:^(NSData* encryptedData, NSError* err) {
                             if (err == nil) {
                               // handle encrypted data
                             }
                           }];
// Ask the application server for Bob and Charlie's public identities
String[] publicIdentities = app.getPublicIdentities(new String[]{"bob-id", "charlie-id"});
EncryptOptions options = new EncryptOptions().shareWithUsers(publicIdentities);
byte[] encryptedData = tanker.encrypt(clearData, options).get();

This will allow Bob and Charlie, as well as Alice, to decrypt the encrypted data.

It is also possible to share data with user groups. See the groups tutorial for more information.

Postponing the share operation

Alternatively, if the recipients are not known when encrypt() is called, or if you need to share several resources at once, you can call share() with a list of resource IDs and a list of recipients.

const encryptedData = await tanker.encrypt(clearText);
const resourceId = await tanker.getResourceId(encryptedData);
const publicIdentities = await app.getPublicIdentities(['bob-id', 'charlie-id']);
const options = { shareWithUsers: publicIdentities };
await tanker.share([resourceId], options);
[self.tanker encryptString:clearTxt
                   options:encryptOptions
         completionHandler:^(NSData* encryptedData, NSError* err) {
   NSArray<NSString*>* identities = [self.app getPublicIdentities:@[@"bob-id", @"charlie-id"]];

   TKRShareOptions* shareOptions = [TKRShareOptions options];
   options.shareWithUsers = identities;

   NSString* resourceID = [self.tanker resourceIDOfEncryptedData:encryptedData error:&err];
   if (err == nil) {
     [self.tanker shareResourcesIDs:@[resourceID]
                            options:shareOptions
                  completionHandler:^(NSError* err) {
                    if (err != nil) {
                      // handle error
                    }
                  }];
   }
}];
byte[] encryptedData = tanker.encrypt(clearData).get();
String resourceId = tanker.getResourceId(encryptedData);
String[] publicIdentities = app.getPublicIdentities(new String[]{"bob-id", "charlie-id"});
ShareOptions options = new ShareOptions().shareWithUsers(publicIdentities);
tanker.share(new String[]{resourceId}, options).get();

As for simple encryption, Tanker never transfers nor stores the encrypted data. You need to take care of sending it to Bob and Charlie.

Decrypting

To decrypt some encrypted data, simply give it to decrypt(). It will work the same whether the content was encrypted by the current user, or shared with them.

const clearText = await tanker.decrypt(encryptedData);

decrypt() will throw an error if the user does not have access to this data (i.e. if the data was not shared with them).

Note that if you used toBase64() as mentioned in the previous section, you should convert encrypted text to binary data first using fromBase64():

import { fromBase64  } from '@tanker/client-browser';

const encryptedData = fromBase64(encryptedText);
const clearText = await tanker.decrypt(encryptedData);
byte[] clearData = tanker.decrypt(encryptedData, null).get();
[self.tanker decryptStringFromData:encryptedData
                 completionHandler:^(NSString* decryptedString, NSError* err) {
                                     if (err == nil) {
                                       // handle decrypted string
                                     }
                                   }];

Code summary

You have now learned how to encrypt data using Tanker. Your code may look like the following:

import { Tanker } from '@tanker/client-browser';

const startTanker() = async() => {
  // See implementation on previous page
}

const run() = async () => {
  const tanker = await startTanker();

  // Encrypt text and share it with Bob and Charlie
  const clearText = 'This is a secret message';

  // Ask the application server for Bob and Charlie's public identities
  const publicIdentities = await app.getPublicIdentities(['bob-id', 'charlie-id']);
  const options = { shareWithUsers: publicIdentities };
  const encryptedData = await tanker.encrypt(clearText, options);

  // Decrypt text
  const decryptedText = await tanker.decrypt(encryptedData);

  // Check
  decryptedText === clearText; // true

  await tanker.stop();
}

- (void)startTanker(TKRStartHandler startHandler)
{
   // See implementation on previous page
}

- (void)encryptDecryptFile(NSString* filePath, NSArray<NSString*>* recipientsUIds)
{
  // Encrypt data and share it with the recipients
  TKREncryptionOptions* encryptionOptions = [TKREncryptionOptions options];
  NSArray<NSString*>* recipientsIdentities = [self.app getPublicIdentities:recipientsUIds]];
  encryptionOptions.shareWithUsers = recipientsIdentities;

  // Get the binary content of a local file:
  NSData* clearFileData = [NSData dataWithContentsOfFile:filePath];

  [self.tanker encryptData:clearFileData
                   options:encryptOptions
         completionHandler:encryptedDataHandler];
}

TKREncryptedDataHandler encryptedDataHandler = ^(NSData* encryptedData, NSError* err) {
  if (err == nil) {
    // Decrypt data
    [self.tanker decryptData:encryptedFileData
           completionHandler:^(NSData* decryptedData, NSError* err) {
             if (err == nil) {
               NSLog(@"File is decrypted");
             }
           }];
  }
};
public class LoginActivity extends AppCompatActivity {
    private static final String TAG = "LoginActivity";
    private Tanker tanker;
    private String userId = "user-id";
    private String password = "Tanker";
    private String emailAddress = "user@example.com";

    public void startTanker() {
        // See implementation on previous page
    }

    public void encryptDecrypt() {
        // Encrypt text and share it with Bob and Charlie
        byte[] clearData = "This is a secret message".getBytes();

        // Ask the application server for Bob and Charlie's public identities
        String[] publicIdentities = app.getPublicIdentities(new String[]{"bob-id", "charlie-id"});
        EncryptOptions options = new EncryptOptions().shareWithUsers(publicIdentities);
        byte[] encryptedData = tanker.encrypt(clearData, options).get();

        // Decrypt text
        byte[] decryptedData = tanker.decrypt(encryptedData).get();

        // Check
        decryptedData.equals(clearData); // true
    }
}