All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.crypto.tink.KeysetManager Maven / Gradle / Ivy

// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////

package com.google.crypto.tink;

import com.google.crypto.tink.internal.KeyStatusTypeProtoConverter;
import com.google.crypto.tink.internal.Util;
import com.google.crypto.tink.proto.KeyData;
import com.google.crypto.tink.proto.KeyStatusType;
import com.google.crypto.tink.proto.Keyset;
import com.google.crypto.tink.proto.OutputPrefixType;
import com.google.crypto.tink.tinkkey.KeyAccess;
import com.google.crypto.tink.tinkkey.KeyHandle;
import com.google.crypto.tink.tinkkey.SecretKeyAccess;
import com.google.crypto.tink.tinkkey.internal.ProtoKey;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.google.errorprone.annotations.InlineMe;
import java.security.GeneralSecurityException;
import javax.annotation.concurrent.GuardedBy;

/**
 * Manages a {@link Keyset} proto, with convenience methods that rotate, disable, enable or destroy
 * keys.
 *
 * 

We do not recommend usage of this class. Instead, we recommend you to use a {@link * Keyset.Builder} which has an improved API (in that it e.g. returns the just added objects, * allowing you to manipulate them further). * * @since 1.0.0 */ public final class KeysetManager { @GuardedBy("this") private final Keyset.Builder keysetBuilder; private KeysetManager(Keyset.Builder val) { keysetBuilder = val; } /** @return a {@link KeysetManager} for the keyset manged by {@code val} */ public static KeysetManager withKeysetHandle(KeysetHandle val) { return new KeysetManager(val.getKeyset().toBuilder()); } /** @return a {@link KeysetManager} for an empty keyset. */ public static KeysetManager withEmptyKeyset() { return new KeysetManager(Keyset.newBuilder()); } /** @return a {@link KeysetHandle} of the managed keyset */ public synchronized KeysetHandle getKeysetHandle() throws GeneralSecurityException { return KeysetHandle.fromKeyset(keysetBuilder.build()); } /** * Generates and adds a fresh key generated using {@code keyTemplate}, and sets the new key as the * primary key. * * @throws GeneralSecurityException if cannot find any {@link KeyManager} that can handle {@code * keyTemplate} */ @CanIgnoreReturnValue public synchronized KeysetManager rotate(com.google.crypto.tink.proto.KeyTemplate keyTemplate) throws GeneralSecurityException { addNewKey(keyTemplate, true); return this; } /** * Generates and adds a fresh key generated using {@code keyTemplate}. * * @throws GeneralSecurityException if cannot find any {@link KeyManager} that can handle {@code * keyTemplate} */ @CanIgnoreReturnValue public synchronized KeysetManager add(com.google.crypto.tink.proto.KeyTemplate keyTemplate) throws GeneralSecurityException { addNewKey(keyTemplate, false); return this; } /** * Generates and adds a fresh key generated using {@code keyTemplate}. * * @throws GeneralSecurityException if cannot find any {@link KeyManager} that can handle {@code * keyTemplate} */ @CanIgnoreReturnValue public synchronized KeysetManager add(KeyTemplate keyTemplate) throws GeneralSecurityException { addNewKey(keyTemplate.getProtoMaybeThrow(), false); return this; } /** * Adds the input {@link KeyHandle} to the existing keyset. The KeyStatusType and key ID of the * {@link KeyHandle} are used as-is in the keyset. * * @throws UnsupportedOperationException if the {@link KeyHandle} contains a {@link TinkKey} which * is not a {@link ProtoKey}. * @throws GeneralSecurityException if the {@link KeyHandle}'s key ID collides with another key ID * in the keyset. * @deprecated We recommend to use the {@code KeysetHandle.Builder} API. */ @CanIgnoreReturnValue @Deprecated public synchronized KeysetManager add(KeyHandle keyHandle) throws GeneralSecurityException { ProtoKey pkey; try { pkey = (ProtoKey) keyHandle.getKey(SecretKeyAccess.insecureSecretAccess()); } catch (ClassCastException e) { throw new UnsupportedOperationException( "KeyHandles which contain TinkKeys that are not ProtoKeys are not yet supported.", e); } if (keyIdExists(keyHandle.getId())) { throw new GeneralSecurityException( "Trying to add a key with an ID already contained in the keyset."); } keysetBuilder.addKey( Keyset.Key.newBuilder() .setKeyData(pkey.getProtoKey()) .setKeyId(keyHandle.getId()) .setStatus(KeyStatusTypeProtoConverter.toProto(keyHandle.getStatus())) .setOutputPrefixType(KeyTemplate.toProto(pkey.getOutputPrefixType())) .build()); return this; } /** * Adds the input {@code KeyHandle} to the existing keyset with {@code OutputPrefixType.TINK}. * * @throws GeneralSecurityException if the given {@code KeyAccess} does not grant access to the * key contained in the {@code KeyHandle}. * @throws UnsupportedOperationException if the {@code KeyHandle} contains a {@code TinkKey} which * is not a {@code ProtoKey}. * @deprecated We recommend to use the {@code KeysetHandle.Builder} API. */ @CanIgnoreReturnValue @Deprecated public synchronized KeysetManager add(KeyHandle keyHandle, KeyAccess access) throws GeneralSecurityException { return add(keyHandle); } /** * Generates a fresh key using {@code keyTemplate} and returns the {@code keyId} of it. In case * {@code asPrimary} is true the generated key will be the new primary. */ @CanIgnoreReturnValue public synchronized int addNewKey( com.google.crypto.tink.proto.KeyTemplate keyTemplate, boolean asPrimary) throws GeneralSecurityException { Keyset.Key key = newKey(keyTemplate); keysetBuilder.addKey(key); if (asPrimary) { keysetBuilder.setPrimaryKeyId(key.getKeyId()); } return key.getKeyId(); } /** * Sets the key with {@code keyId} as primary. * * @throws GeneralSecurityException if the key is not found or not enabled */ @CanIgnoreReturnValue public synchronized KeysetManager setPrimary(int keyId) throws GeneralSecurityException { for (int i = 0; i < keysetBuilder.getKeyCount(); i++) { Keyset.Key key = keysetBuilder.getKey(i); if (key.getKeyId() == keyId) { if (!key.getStatus().equals(KeyStatusType.ENABLED)) { throw new GeneralSecurityException( "cannot set key as primary because it's not enabled: " + keyId); } keysetBuilder.setPrimaryKeyId(keyId); return this; } } throw new GeneralSecurityException("key not found: " + keyId); } /** * Sets the key with {@code keyId} as primary. * * @throws GeneralSecurityException if the key is not found or not enabled */ @InlineMe(replacement = "this.setPrimary(keyId)") @CanIgnoreReturnValue public synchronized KeysetManager promote(int keyId) throws GeneralSecurityException { return setPrimary(keyId); } /** * Enables the key with {@code keyId}. * * @throws GeneralSecurityException if the key is not found */ @CanIgnoreReturnValue public synchronized KeysetManager enable(int keyId) throws GeneralSecurityException { for (int i = 0; i < keysetBuilder.getKeyCount(); i++) { Keyset.Key key = keysetBuilder.getKey(i); if (key.getKeyId() == keyId) { if (key.getStatus() != KeyStatusType.ENABLED && key.getStatus() != KeyStatusType.DISABLED) { throw new GeneralSecurityException("cannot enable key with id " + keyId); } keysetBuilder.setKey(i, key.toBuilder().setStatus(KeyStatusType.ENABLED).build()); return this; } } throw new GeneralSecurityException("key not found: " + keyId); } /** * Disables the key with {@code keyId}. * * @throws GeneralSecurityException if the key is not found or it is the primary key */ @CanIgnoreReturnValue public synchronized KeysetManager disable(int keyId) throws GeneralSecurityException { if (keyId == keysetBuilder.getPrimaryKeyId()) { throw new GeneralSecurityException("cannot disable the primary key"); } for (int i = 0; i < keysetBuilder.getKeyCount(); i++) { Keyset.Key key = keysetBuilder.getKey(i); if (key.getKeyId() == keyId) { if (key.getStatus() != KeyStatusType.ENABLED && key.getStatus() != KeyStatusType.DISABLED) { throw new GeneralSecurityException("cannot disable key with id " + keyId); } keysetBuilder.setKey(i, key.toBuilder().setStatus(KeyStatusType.DISABLED).build()); return this; } } throw new GeneralSecurityException("key not found: " + keyId); } /** * Deletes the key with {@code keyId}. * * @throws GeneralSecurityException if the key is not found or it is the primary key */ @CanIgnoreReturnValue public synchronized KeysetManager delete(int keyId) throws GeneralSecurityException { if (keyId == keysetBuilder.getPrimaryKeyId()) { throw new GeneralSecurityException("cannot delete the primary key"); } for (int i = 0; i < keysetBuilder.getKeyCount(); i++) { Keyset.Key key = keysetBuilder.getKey(i); if (key.getKeyId() == keyId) { keysetBuilder.removeKey(i); return this; } } throw new GeneralSecurityException("key not found: " + keyId); } /** * Destroys the key material associated with the {@code keyId}. * * @throws GeneralSecurityException if the key is not found or it is the primary key */ @CanIgnoreReturnValue public synchronized KeysetManager destroy(int keyId) throws GeneralSecurityException { if (keyId == keysetBuilder.getPrimaryKeyId()) { throw new GeneralSecurityException("cannot destroy the primary key"); } for (int i = 0; i < keysetBuilder.getKeyCount(); i++) { Keyset.Key key = keysetBuilder.getKey(i); if (key.getKeyId() == keyId) { if (key.getStatus() != KeyStatusType.ENABLED && key.getStatus() != KeyStatusType.DISABLED && key.getStatus() != KeyStatusType.DESTROYED) { throw new GeneralSecurityException("cannot destroy key with id " + keyId); } keysetBuilder.setKey( i, key.toBuilder().setStatus(KeyStatusType.DESTROYED).clearKeyData().build()); return this; } } throw new GeneralSecurityException("key not found: " + keyId); } private synchronized Keyset.Key newKey(com.google.crypto.tink.proto.KeyTemplate keyTemplate) throws GeneralSecurityException { return createKeysetKey(Registry.newKeyData(keyTemplate), keyTemplate.getOutputPrefixType()); } private synchronized Keyset.Key createKeysetKey( KeyData keyData, OutputPrefixType outputPrefixType) throws GeneralSecurityException { int keyId = newKeyId(); if (outputPrefixType == OutputPrefixType.UNKNOWN_PREFIX) { throw new GeneralSecurityException("unknown output prefix type"); } return Keyset.Key.newBuilder() .setKeyData(keyData) .setKeyId(keyId) .setStatus(KeyStatusType.ENABLED) .setOutputPrefixType(outputPrefixType) .build(); } private synchronized boolean keyIdExists(int keyId) { for (Keyset.Key key : keysetBuilder.getKeyList()) { if (key.getKeyId() == keyId) { return true; } } return false; } private synchronized int newKeyId() { int keyId = Util.randKeyId(); while (keyIdExists(keyId)) { keyId = Util.randKeyId(); } return keyId; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy