Encrypt

The encrypt operation takes a document (which is any chunk of data - field, row, JSON object, etc) as bytes and encrypts it with a tenant-specific key using AES-256. To encrypt a new document for a tenant, you first define metadata for the document that is being encrypted. This metadata includes the unique ID of the tenant associated to the document, the service or user responsible for performing the encryption, and a label for the type of data being encrypted. These fields help build richer audit trails that provide more context to your customers about what data is being encrypted, by whom, and why.

tenantID: The Tenant Security Proxy expects to run in a multi-tenant environment where it will encrypt and decrypt documents associated to various tenants/customers. The tenantID should be a unique ID which will allow all of that tenant's sensitive data to be encrypted using that tenant's KMS.

requestingUserOrServiceID: A unique ID that denotes which user or service is making the request to encrypt data. This will be used to log access of the Tenant Security Proxy.

dataLabel: A label that can be used to properly classify the data being encrypted.

otherData: Any other String key/value pairs to apply to the encrypted data. This data will be sent to the Tenant Security Proxy for logging.

It's important to note that when encrypting data, the bytes to encrypt are never passed to the Tenant Security Proxy. The interaction with this service only passes keys back and forth, never actual data. All encryption is done directly in the Java client. All documents are encrypted with AES-256 in GCM mode.

DocumentMetadata metadata =
    new DocumentMetadata("TENANT_ID", "serviceOrUserId", "data label");

Create the document to be encrypted as a mapping from field names to the bytes to be encrypted. The encrypt call can be used to encrypt one or more plaintext fields at the same time. However, each of the fields in the provided map will be encrypted using the same key. You should only encrypt multiple fields in this way if the data being encrypted is all co-located, such as multiple fields in the same database row. If you need to encrypt multiple dissociated fields at the same time you should instead use the encryptBatch method.

Map<String, byte[]> document = new HashMap<>();
document.put("ssn", "000-12-2345".getBytes("UTF-8"));
document.put("address", "2825-519 Stone Creek Rd, Bozeman, MT 59715".getBytes("UTF-8"));
document.put("name", "Jim Bridger".getBytes("UTF-8"));

client.encrypt(document, metadata).thenCompose(encrypted -> {
    String edek = encrypted.getEdek();
    Map<String, byte[]> fields = encrypted.getEncryptedFields();
    //Store both edek and fields in your persistence layer
})

Based on the provided tenant ID, a document encryption key (DEK) and its associated encrypted version (EDEK) will be requested from the specific tenant’s KMS. That DEK will be used to encrypt the document in the client, and then it will be immediately discarded.

The encrypt operation returns a CompletableFuture which will resolve with an instance of the EncryptedDocument class. This class contains both a map of document id/name to encrypted bytes (getEncryptedFields()) and a base64 encoded encrypted document key (getEdek()) that was used to encrypt the document(s). Both of these values must be stored and associated together as they are both required in order to decrypt document content.

Since you never get access to the DEK (only the EDEK) the customer still has control over whether you can decrypt this document in the future.

See the Javadocs for more options and specifics.