// 
// Decompiled by Procyon v0.6.0
// 

package com.google.crypto.tink.prf;

import com.google.protobuf.MessageLite;
import com.google.protobuf.Parser;
import com.google.crypto.tink.internal.LegacyKeyManagerImpl;
import com.google.crypto.tink.proto.KeyData;
import com.google.crypto.tink.internal.TinkBugException;
import com.google.crypto.tink.KeyTemplate;
import com.google.crypto.tink.internal.KeyManagerRegistry;
import com.google.crypto.tink.internal.MutableParametersRegistry;
import com.google.crypto.tink.internal.MutableKeyCreationRegistry;
import com.google.crypto.tink.internal.MutablePrimitiveRegistry;
import com.google.crypto.tink.prf.internal.HkdfPrfProtoSerialization;
import com.google.crypto.tink.config.internal.TinkFipsUtil;
import java.util.Collections;
import java.util.HashMap;
import com.google.crypto.tink.Parameters;
import java.util.Map;
import com.google.crypto.tink.AccessesPartialKey;
import com.google.crypto.tink.util.SecretBytes;
import javax.annotation.Nullable;
import com.google.crypto.tink.subtle.prf.PrfImpl;
import com.google.crypto.tink.subtle.prf.HkdfStreamingPrf;
import java.security.GeneralSecurityException;
import com.google.crypto.tink.internal.KeyCreator;
import com.google.crypto.tink.KeyManager;
import com.google.crypto.tink.subtle.prf.StreamingPrf;
import com.google.crypto.tink.internal.PrimitiveConstructor;

public class HkdfPrfKeyManager
{
    private static final PrimitiveConstructor<HkdfPrfKey, StreamingPrf> STREAMING_HKDF_PRF_CONSTRUCTOR;
    private static final PrimitiveConstructor<HkdfPrfKey, Prf> HKDF_PRF_CONSTRUCTOR;
    private static final KeyManager<Prf> legacyKeyManager;
    static final KeyCreator<HkdfPrfParameters> KEY_CREATOR;
    private static final int MIN_KEY_SIZE = 32;
    
    private static void validate(final HkdfPrfParameters parameters) throws GeneralSecurityException {
        if (parameters.getKeySizeBytes() < 32) {
            throw new GeneralSecurityException("Key size must be at least 32");
        }
        if (parameters.getHashType() != HkdfPrfParameters.HashType.SHA256 && parameters.getHashType() != HkdfPrfParameters.HashType.SHA512) {
            throw new GeneralSecurityException("Hash type must be SHA256 or SHA512");
        }
    }
    
    private static StreamingPrf createStreamingPrf(final HkdfPrfKey key) throws GeneralSecurityException {
        validate(key.getParameters());
        return HkdfStreamingPrf.create(key);
    }
    
    private static Prf createPrf(final HkdfPrfKey key) throws GeneralSecurityException {
        return PrfImpl.wrap(createStreamingPrf(key));
    }
    
    @AccessesPartialKey
    private static HkdfPrfKey newKey(final HkdfPrfParameters parameters, @Nullable final Integer idRequirement) throws GeneralSecurityException {
        if (idRequirement != null) {
            throw new GeneralSecurityException("Id Requirement is not supported for HKDF PRF keys");
        }
        validate(parameters);
        return HkdfPrfKey.builder().setParameters(parameters).setKeyBytes(SecretBytes.randomBytes(parameters.getKeySizeBytes())).build();
    }
    
    static String getKeyType() {
        return "type.googleapis.com/google.crypto.tink.HkdfPrfKey";
    }
    
    private static Map<String, Parameters> namedParameters() throws GeneralSecurityException {
        final Map<String, Parameters> result = new HashMap<String, Parameters>();
        result.put("HKDF_SHA256", PredefinedPrfParameters.HKDF_SHA256);
        return Collections.unmodifiableMap((Map<? extends String, ? extends Parameters>)result);
    }
    
    public static void register(final boolean newKeyAllowed) throws GeneralSecurityException {
        if (!TinkFipsUtil.AlgorithmFipsCompatibility.ALGORITHM_NOT_FIPS.isCompatible()) {
            throw new GeneralSecurityException("Registering HKDF PRF is not supported in FIPS mode");
        }
        HkdfPrfProtoSerialization.register();
        MutablePrimitiveRegistry.globalInstance().registerPrimitiveConstructor(HkdfPrfKeyManager.HKDF_PRF_CONSTRUCTOR);
        MutablePrimitiveRegistry.globalInstance().registerPrimitiveConstructor(HkdfPrfKeyManager.STREAMING_HKDF_PRF_CONSTRUCTOR);
        MutableKeyCreationRegistry.globalInstance().add(HkdfPrfKeyManager.KEY_CREATOR, HkdfPrfParameters.class);
        MutableParametersRegistry.globalInstance().putAll(namedParameters());
        KeyManagerRegistry.globalInstance().registerKeyManager(HkdfPrfKeyManager.legacyKeyManager, newKeyAllowed);
    }
    
    public static String staticKeyType() {
        return getKeyType();
    }
    
    public static final KeyTemplate hkdfSha256Template() {
        return TinkBugException.exceptionIsBug(() -> KeyTemplate.createFrom(HkdfPrfParameters.builder().setKeySizeBytes(32).setHashType(HkdfPrfParameters.HashType.SHA256).build()));
    }
    
    private HkdfPrfKeyManager() {
    }
    
    static {
        STREAMING_HKDF_PRF_CONSTRUCTOR = PrimitiveConstructor.create(HkdfPrfKeyManager::createStreamingPrf, HkdfPrfKey.class, StreamingPrf.class);
        HKDF_PRF_CONSTRUCTOR = PrimitiveConstructor.create(HkdfPrfKeyManager::createPrf, HkdfPrfKey.class, Prf.class);
        legacyKeyManager = LegacyKeyManagerImpl.create(getKeyType(), Prf.class, KeyData.KeyMaterialType.SYMMETRIC, com.google.crypto.tink.proto.HkdfPrfKey.parser());
        KEY_CREATOR = HkdfPrfKeyManager::newKey;
    }
}
