How to rotate keys?

1.1k Views Asked by At

I'm looking at the Tink documentation, but I don't see a clear way how to rotate a key. Basically, I would like to do somethink like:

KeyTemplate keyTemplate = AeadKeyTemplates.AES256_GCM;
KeysetHandle keysetHandle = KeysetHandle.generateNew(keyTemplate);
// Do some stuff... and then
keysetHandle.rotateKey(); // How to do the equivalent of this??

The documentation talks about how key rotation is a core feature of the library. However, there are no examples in the documentation for how to do this. What's the "correct" way to rotate keys using the library? I would also prefer to separate rotate and activate the new key.

1

There are 1 best solutions below

0
Michael Fehr On

The developers improved the documentation on the GitHub-docs (see https://github.com/google/tink/blob/master/docs/JAVA-HOWTO.md#key-rotation):

*Support for key rotation in Tink is provided via the KeysetManager class. You have to provide a KeysetHandle-object that contains the keyset that should be rotated, and a specification of the new key via a KeyTemplate message.

import com.google.crypto.tink.KeysetHandle;
import com.google.crypto.tink.KeysetManager;
import com.google.crypto.tink.proto.KeyTemplate;
KeysetHandle keysetHandle = ...;   // existing keyset
KeyTemplate keyTemplate = ...;     // template for the new key
KeysetHandle rotatedKeysetHandle = KeysetManager
    .withKeysetHandle(keysetHandle)
    .rotate(keyTemplate)
    .getKeysetHandle();

Some common specifications are available as pre-generated templates in examples/keytemplates, and can be accessed via the ...KeyTemplates.java classes of the respective primitives. After a successful rotation, the resulting keyset contains a new key generated according to the specification in keyTemplate, and the new key becomes the primary key of the keyset. For the rotation to succeed the Registry must contain a key manager for the key type specified in keyTemplate. Alternatively, you can use Tinkey to rotate or manage a keyset.*

Below you find a short example and the files generated by this program:

keyset_original.json is the (first) original key:

{
    "primaryKeyId": 937652358,
    "key": [{
        "keyData": {
            "typeUrl": "type.googleapis.com/google.crypto.tink.AesGcmKey",
            "keyMaterialType": "SYMMETRIC",
            "value": "GhC1iBVcPeQwNp9GcXfqpm8G"
        },
        "outputPrefixType": "TINK",
        "keyId": 937652358,
        "status": "ENABLED"
    }]
}

keyset_rotated.json is the rotated keyset - the primaryKeyId has changed and the (first) key is still available and enabled but no longer primary key:

{
    "primaryKeyId": 138119043,
    "key": [
        {
            "keyData": {
                "typeUrl": "type.googleapis.com/google.crypto.tink.AesGcmKey",
                "keyMaterialType": "SYMMETRIC",
                "value": "GhC1iBVcPeQwNp9GcXfqpm8G"
            },
            "outputPrefixType": "TINK",
            "keyId": 937652358,
            "status": "ENABLED"
        },
        {
            "keyData": {
                "typeUrl": "type.googleapis.com/google.crypto.tink.AesGcmKey",
                "keyMaterialType": "SYMMETRIC",
                "value": "GhBrr2JLPAMMi36n56RHGF2A"
            },
            "outputPrefixType": "TINK",
            "keyId": 138119043,
            "status": "ENABLED"
        }
    ]
}

code:

import com.google.crypto.tink.*;
import com.google.crypto.tink.aead.AeadKeyTemplates;
import com.google.crypto.tink.config.TinkConfig;
import com.google.crypto.tink.proto.KeyTemplate;

import java.io.File;
import java.io.IOException;
import java.security.GeneralSecurityException;

public class KeyRotation {
    public static void main(String[] args) throws GeneralSecurityException, IOException {
        System.out.println("Google Tink key rotation");
        TinkConfig.register();
        // key generation
        KeyTemplate keyTemplate = AeadKeyTemplates.AES128_GCM;
        KeysetHandle keysetHandle = KeysetHandle.generateNew(keyTemplate);
        // write it to a file
        String originalKeysetFilename = "keyset_original.json";
        CleartextKeysetHandle.write(keysetHandle, JsonKeysetWriter.withFile(
                new File(originalKeysetFilename)));
        // load the existing keysetHandle
        KeysetHandle keysetHandleLoaded = CleartextKeysetHandle.read(
                JsonKeysetReader.withFile(new File(originalKeysetFilename)));
        // generate a new key and make it primary key
        KeysetHandle rotatedKeysetHandle = KeysetManager
                .withKeysetHandle(keysetHandleLoaded)
                .rotate(keyTemplate)
                .getKeysetHandle();
        // write it to a file
        String rotatedKeysetFilename = "keyset_rotated.json";
        CleartextKeysetHandle.write(rotatedKeysetHandle, JsonKeysetWriter.withFile(
                new File(rotatedKeysetFilename)));
        System.out.println("key rotation done, new keyset in " + rotatedKeysetFilename);
    }
}