Key/Backend Rotation

CipherSweet aims to make key rotation and/or backend migration as pain-free as possible.

To use these APIs, first instantiate two CipherSweet instances. They can have different backends (e.g. FIPSCrypto to BoringCrypto), different keys, or both.

FieldRotator

<?php
use ParagonIE\CipherSweet\CipherSweet;
use ParagonIE\CipherSweet\KeyRotation\FieldRotator;
use ParagonIE\CipherSweet\EncryptedField;

/**
 * @var string $ciphertext
 * @var CipherSweet $old
 * @var CipherSweet $new
 */
$oldField = new EncryptedField($old, 'contacts', 'ssn');
$newField = new EncryptedField($new, 'contacts', 'ssn');

$rotator = new FieldRotator($oldField, $newField);
if ($rotator->needsReEncrypt($ciphertext)) {
    list($ciphertext, $indices) = $rotator->prepareForUpdate($ciphertext);
}

You can optionally also provide additional authenticated data to this API, like so:

if ($rotator->needsReEncrypt($ciphertext, 'old AAD')) {
    list($ciphertext, $indices) = $rotator->prepareForUpdate($ciphertext, 'old AAD', 'new AAD');
}

The end result will be re-encrypted, and the ciphertext tag will be tied to "new AAD".

RowRotator

<?php
use ParagonIE\CipherSweet\CipherSweet;
use ParagonIE\CipherSweet\KeyRotation\RowRotator;
use ParagonIE\CipherSweet\EncryptedRow;

/**
 * @var array<string, string> $ciphertext
 * @var CipherSweet $old
 * @var CipherSweet $new
 */
$oldRow = new EncryptedRow($old, 'contacts');
$newRow = new EncryptedRow($new, 'contacts');

$rotator = new RowRotator($oldRow, $newRow);
if ($rotator->needsReEncrypt($ciphertext)) {
    list($ciphertext, $indices) = $rotator->prepareForUpdate($ciphertext);
}

MultiRowsRotator

<?php
use ParagonIE\CipherSweet\CipherSweet;
use ParagonIE\CipherSweet\KeyRotation\MultiRowsRotator;
use ParagonIE\CipherSweet\EncryptedMultiRows;

/**
 * @var array<string, array<string, string>> $ciphertext
 * @var CipherSweet $old
 * @var CipherSweet $new
 */
$oldMultiRows = new EncryptedMultiRows($old);
$newMultiRows = new EncryptedMultiRows($new);

$rotator = new MultiRowsRotator($oldMultiRows, $newMultiRows);
if ($rotator->needsReEncrypt($ciphertext)) {
    list($ciphertext, $indices) = $rotator->prepareForUpdate($ciphertext);
}

Next: EncryptedFile