tink icon indicating copy to clipboard operation
tink copied to clipboard

Enhance KeysetManager to make key rotation easy to do

Open asaikali opened this issue 2 years ago • 3 comments

In version 1.6.1 it is very awkward to perform a key rotation in code. The KeysetManager.rotate() method is deprecated and the suggestion is to call the add method of the KeySetManager shown below.

 /**
   * Generates and adds a fresh key generated using {@code keyTemplate}.
   *
   * @throws GeneralSecurityException if cannot find any {@link KeyManager} that can handle {@code
   *     keyTemplate}
   */
  public synchronized KeysetManager add(KeyTemplate keyTemplate) throws GeneralSecurityException {
    addNewKey(keyTemplate.getProto(), false);
    return this;
  }

Notice that the method returns the KeysetManager itself rather than the keyId of the newly created key. To set the primary key I have to call the setPrimary(int keyId) but I don't have access to the keyId of the newly created key that was generated when the add method above was called.

When adding a new key to a keyset it should be very easy to know what the keyId of the newly created key so that it is easy to set it as the primary key right away or at a later time.

The current workaround I am using to is to diff the list before and after a new is added as show below

      KeyTemplate sha512hmac = KeyTemplates.get("HMAC_SHA512_512BITTAG");
      KeysetHandle keysetHandle = KeysetHandle.generateNew(sha512hmac);
      
      KeysetManager keysetManager = KeysetManager.withKeysetHandle( keysetHandle);
      keysetManager.add(sha512hmac);

      var  keySetHandle2 = keysetManager.getKeysetHandle();

      var newKeys = new HashSet(keySetHandle2.getKeysetInfo().getKeyInfoList());
      var oldKeys = new HashSet(keysetHandle.getKeysetInfo().getKeyInfoList());

      newKeys.removeAll(oldKeys);

      Assertions.assertThat(newKeys.size()).isEqualTo(1);

      KeyInfo newKey = (KeyInfo) newKeys.toArray()[0];
      keysetManager.setPrimary(newKey.getKeyId());

Tink should have an easier way to figure out the id of a newly added key.

asaikali avatar Apr 25 '22 05:04 asaikali

This is an issue I'm working on in a larger context.

Code will look something like this:

  KeysetHandle.Builder builder = KeysetHandle.newBuilder(handle);
  builder.addEntry(KeysetHandle.newEntry(KeyTemplates.get("HMAC_SHA512_512BITTAG").withRandomId().makePrimary());
  KeysetHandle keysetHandle = builder.build();

  // Now you can access the newly added key with 
  keysetHandle.getAt(keysetHandle.size());

Obviously the names and other things may still change.

tholenst avatar May 03 '22 14:05 tholenst

Will this be part of the next release?

asaikali avatar May 03 '22 16:05 asaikali

I suspect not, but it will depend when the next release it. I would assume it will take minimum 6 months.

tholenst avatar May 05 '22 12:05 tholenst

Note that while this is still in alpha, you can in principle use it in 1.7. However, while I don't think it should be needed, there is a small chance we will need to break this again. So prefer not to use it in libraries.

See e.g. https://github.com/google/tink/blob/27b061bb9ed1af1a6f538410bff443290e427e66/java_src/src/test/java/com/google/crypto/tink/KeysetHandleTest.java#L783

tholenst avatar Aug 10 '22 07:08 tholenst