1. Docs


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.

requestId: Unique ID that ties host application request ID to Tenant Security Proxy logs.

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");
const metadata = new DocumentMetadata("TENANT_ID", "serviceOrUserId", "data label");
$metadata = new RequestMetadata("TENANT_ID", new IclFields("serviceOrUserId", "data label"), []);
metadata := tsc.RequestMetadata{TenantID: "TENANT_ID", IclFields: tsc.IclFields{RequestingID: "serviceOrUserId", DataLabel: "data label"}, CustomFields: nil}

Create the document to be encrypted as a mapping from field names to the bytes to be encrypted. The call to encrypt 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 batch methods instead.

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 })
const document = { ssn: Buffer.from("000-12-2345", "utf-8"), address: Buffer.from("2825-519 Stone Creek Rd, Bozeman, MT 59715", "utf-8"), name: Buffer.from("Jim Bridger", "utf-8"), }; client.encrypt(document, metadata).then((encrypted) => { const edek = encrypted.edek; const encryptedFields = encrypted.encryptedDocument; // Store both edek and fields in your persistence layer });
$document = [ "ssn" => new Bytes("000-12-2345"), "address" => new Bytes("2825-519 Stone Creek Rd, Bozeman, MT 59715"), "name" => new Bytes("Jim Bridger") ]; $encrypted = $client->encrypt($document, $metadata); $edek = $encrypted->getEdek(); $encryptedFields = $encrypted->getEncryptedFields(); // Store both edek and fields in your persistence layer
document := tsc.PlaintextDocument{ "ssn": []byte("000-12-2345"), "address": []byte("2825-519 Stone Creek Rd, Bozeman, MT 59715"), "name": []byte("Jim Bridger"), } encrypted, err := tenantSecurityClient.Encrypt(ctx, document, &metadata) edek := encrypted.Edek encryptedFields := encrypted.EncryptedFields // 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 encryption operation is asynchronous, and when it resolves it returns both a map of document id/name to encrypted bytes and a base64 encoded encrypted document key (EDEK) 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.

Was this page helpful?