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

com.google.crypto.tink.keyderivation.internal.PrfBasedDeriverKeyManager Maven / Gradle / Ivy

// Copyright 2020 Google LLC
//
// 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.keyderivation.internal;

import com.google.crypto.tink.AccessesPartialKey;
import com.google.crypto.tink.InsecureSecretKeyAccess;
import com.google.crypto.tink.Key;
import com.google.crypto.tink.KeyManager;
import com.google.crypto.tink.Parameters;
import com.google.crypto.tink.internal.KeyManagerRegistry;
import com.google.crypto.tink.internal.MutableKeyCreationRegistry;
import com.google.crypto.tink.internal.MutablePrimitiveRegistry;
import com.google.crypto.tink.internal.MutableSerializationRegistry;
import com.google.crypto.tink.internal.PrimitiveConstructor;
import com.google.crypto.tink.internal.ProtoKeySerialization;
import com.google.crypto.tink.internal.ProtoParametersSerialization;
import com.google.crypto.tink.keyderivation.PrfBasedKeyDerivationKey;
import com.google.crypto.tink.keyderivation.PrfBasedKeyDerivationParameters;
import com.google.crypto.tink.prf.PrfKey;
import com.google.crypto.tink.proto.KeyData;
import com.google.crypto.tink.proto.KeyTemplate;
import com.google.crypto.tink.proto.OutputPrefixType;
import com.google.crypto.tink.proto.PrfBasedDeriverKey;
import com.google.crypto.tink.proto.PrfBasedDeriverKeyFormat;
import com.google.protobuf.ByteString;
import com.google.protobuf.ExtensionRegistryLite;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.MessageLite;
import java.security.GeneralSecurityException;
import javax.annotation.Nullable;

/**
 * {@link com.google.crypto.tink.internal.KeyTypeManager} for {@link PrfBasedDeriverKey}.
 *
 * 

This is implemented directly as a KeyManager. Usually, we use {@code LegacyKeyManagerImpl} to * provide an implementation of a KeyManager based on the individual registries based on the key * objects. However, at the moment for key derivation this does not work. * *

The reason is that the KeysetHandle still generates new keys by going through the KeyManagers * (instead of going directly to the key creation registry). I don't want to change this right now * -- it would require some fallback code which is always brittle. * *

Unfortunately, implement the required behavior of the KeyManager based on the KeyCreation * registry is not generic. * *

Usually, the behavior of the key manager is simply this: assume that the input to * generateNewKey() is a serialization with OutputPrefixType = RAW, and build the corresponding * parameter serialization. Then, parse this, and give this to the key creation registry. * *

For key creation, the behavior is slightly different: the serialization of key derivation * parameters has been defined to always satisfy that the outer OutputPrefixType is equal to the one * given in the proto PrfBasedDeriverKeyFormat, field prf_key_template. Hence we cannot assume raw * -- instead, we have to parse it and use this one. * *

Similar things hold for the creating a primitive from a Key -- but here Tink already uses the * PrimitiveCreationRegistry fully, so we don't need to worry about it here. Instead, we just throw * when these functions are called. */ public final class PrfBasedDeriverKeyManager implements KeyManager { private static final PrimitiveConstructor PRIMITIVE_CONSTRUCTOR = PrimitiveConstructor.create( PrfBasedKeyDeriver::create, PrfBasedKeyDerivationKey.class, KeyDeriver.class); @AccessesPartialKey private static final PrfBasedKeyDerivationKey createNewKey( PrfBasedKeyDerivationParameters parameters, @Nullable Integer idRequirement) throws GeneralSecurityException { Key prfKey = MutableKeyCreationRegistry.globalInstance() .createKey(parameters.getPrfParameters(), /* idRequirement= */ null); if (!(prfKey instanceof PrfKey)) { throw new GeneralSecurityException( "Failed to create PrfKey from parameters" + parameters.getPrfParameters() + ", instead got " + prfKey.getClass()); } return PrfBasedKeyDerivationKey.create(parameters, (PrfKey) prfKey, idRequirement); } @SuppressWarnings("InlineLambdaConstant") // We need a correct Object#equals in registration. private static final MutableKeyCreationRegistry.KeyCreator KEY_CREATOR = PrfBasedDeriverKeyManager::createNewKey; private static final String TYPE_URL = "type.googleapis.com/google.crypto.tink.PrfBasedDeriverKey"; PrfBasedDeriverKeyManager() {} @Override public Void getPrimitive(ByteString serializedKey) throws GeneralSecurityException { throw new GeneralSecurityException( "Cannot use the KeyManager to get a primitive for KeyDerivation"); } @Override public final Void getPrimitive(MessageLite key) throws GeneralSecurityException { throw new GeneralSecurityException( "Cannot use the KeyManager to get a primitive for KeyDerivation"); } @Override @SuppressWarnings("UnusedException") public final MessageLite newKey(ByteString serializedKeyFormat) throws GeneralSecurityException { KeyData keyData = newKeyData(serializedKeyFormat); try { return PrfBasedDeriverKey.parseFrom( keyData.getValue(), ExtensionRegistryLite.getEmptyRegistry()); } catch (InvalidProtocolBufferException e) { throw new GeneralSecurityException("Unexpectedly failed to parse key"); } } @Override public final MessageLite newKey(MessageLite keyFormat) throws GeneralSecurityException { return newKey(keyFormat.toByteString()); } @Override public final boolean doesSupport(String typeUrl) { return typeUrl.equals(getKeyType()); } @Override public final String getKeyType() { return TYPE_URL; } @Override public int getVersion() { return 0; } private static OutputPrefixType getOutputPrefixTypeFromSerializedKeyFormat( ByteString serializedKeyFormat) throws GeneralSecurityException { try { PrfBasedDeriverKeyFormat format = PrfBasedDeriverKeyFormat.parseFrom( serializedKeyFormat, ExtensionRegistryLite.getEmptyRegistry()); return format.getParams().getDerivedKeyTemplate().getOutputPrefixType(); } catch (InvalidProtocolBufferException e) { throw new GeneralSecurityException("Unexpectedly failed to parse key format", e); } } @Override public final KeyData newKeyData(ByteString serializedKeyFormat) throws GeneralSecurityException { OutputPrefixType outputPrefixType = getOutputPrefixTypeFromSerializedKeyFormat(serializedKeyFormat); ProtoParametersSerialization parametersSerialization = ProtoParametersSerialization.checkedCreate( KeyTemplate.newBuilder() .setTypeUrl(TYPE_URL) .setValue(serializedKeyFormat) .setOutputPrefixType(outputPrefixType) .build()); Parameters parameters = MutableSerializationRegistry.globalInstance().parseParameters(parametersSerialization); @Nullable Integer idRequirement = null; if (!outputPrefixType.equals(OutputPrefixType.RAW)) { // The actual id requirement doesn't matter here: we just need to set something. We then // later serialize the generated key as KeyData (which doesn't have the ID) and then it // will be put into a keyset with the correct ID. // // This of course assumes that we can get a valid key by first creating one with the wrong // id requirement, then serializing it, and then replacing the id in the proto key // serialization. idRequirement = 123; } Key key = MutableKeyCreationRegistry.globalInstance().createKey(parameters, idRequirement); ProtoKeySerialization keySerialization = MutableSerializationRegistry.globalInstance() .serializeKey(key, ProtoKeySerialization.class, InsecureSecretKeyAccess.get()); return KeyData.newBuilder() .setTypeUrl(keySerialization.getTypeUrl()) .setValue(keySerialization.getValue()) .setKeyMaterialType(keySerialization.getKeyMaterialType()) .build(); } @Override public final Class getPrimitiveClass() { return Void.class; } public static void register(boolean newKeyAllowed) throws GeneralSecurityException { KeyManagerRegistry.globalInstance() .registerKeyManager(new PrfBasedDeriverKeyManager(), newKeyAllowed); MutableKeyCreationRegistry.globalInstance() .add(KEY_CREATOR, PrfBasedKeyDerivationParameters.class); MutablePrimitiveRegistry.globalInstance().registerPrimitiveConstructor(PRIMITIVE_CONSTRUCTOR); PrfBasedKeyDerivationKeyProtoSerialization.register(); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy