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

package com.google.crypto.tink;

import java.util.Collections;
import java.util.concurrent.ConcurrentHashMap;
import com.google.crypto.tink.internal.MutableParametersRegistry;
import java.util.List;
import com.google.protobuf.ByteString;
import com.google.protobuf.MessageLite;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.ExtensionRegistryLite;
import com.google.crypto.tink.proto.KeyData;
import com.google.crypto.tink.proto.KeyTemplate;
import com.google.crypto.tink.config.internal.TinkFipsUtil;
import com.google.crypto.tink.prf.Prf;
import java.util.HashSet;
import java.security.GeneralSecurityException;
import java.util.Locale;
import com.google.crypto.tink.internal.MutablePrimitiveRegistry;
import com.google.crypto.tink.internal.KeyManagerRegistry;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
import java.util.logging.Logger;

public final class Registry
{
    private static final Logger logger;
    private static final ConcurrentMap<String, Catalogue<?>> catalogueMap;
    private static final Set<Class<?>> ALLOWED_PRIMITIVES;
    
    static synchronized void reset() {
        KeyManagerRegistry.resetGlobalInstanceTestOnly();
        MutablePrimitiveRegistry.resetGlobalInstanceTestOnly();
        Registry.catalogueMap.clear();
    }
    
    @Deprecated
    public static synchronized void addCatalogue(final String catalogueName, final Catalogue<?> catalogue) throws GeneralSecurityException {
        if (catalogueName == null) {
            throw new IllegalArgumentException("catalogueName must be non-null.");
        }
        if (catalogue == null) {
            throw new IllegalArgumentException("catalogue must be non-null.");
        }
        if (Registry.catalogueMap.containsKey(catalogueName.toLowerCase(Locale.US))) {
            final Catalogue<?> existing = Registry.catalogueMap.get(catalogueName.toLowerCase(Locale.US));
            if (!catalogue.getClass().getName().equals(existing.getClass().getName())) {
                Registry.logger.warning("Attempted overwrite of a catalogueName catalogue for name " + catalogueName);
                throw new GeneralSecurityException("catalogue for name " + catalogueName + " has been already registered");
            }
        }
        Registry.catalogueMap.put(catalogueName.toLowerCase(Locale.US), catalogue);
    }
    
    @Deprecated
    public static Catalogue<?> getCatalogue(final String catalogueName) throws GeneralSecurityException {
        if (catalogueName == null) {
            throw new IllegalArgumentException("catalogueName must be non-null.");
        }
        final Catalogue<?> catalogue = Registry.catalogueMap.get(catalogueName.toLowerCase(Locale.US));
        if (catalogue == null) {
            String error = String.format("no catalogue found for %s. ", catalogueName);
            if (catalogueName.toLowerCase(Locale.US).startsWith("tinkaead")) {
                error += "Maybe call AeadConfig.register().";
            }
            if (catalogueName.toLowerCase(Locale.US).startsWith("tinkdeterministicaead")) {
                error += "Maybe call DeterministicAeadConfig.register().";
            }
            else if (catalogueName.toLowerCase(Locale.US).startsWith("tinkstreamingaead")) {
                error += "Maybe call StreamingAeadConfig.register().";
            }
            else if (catalogueName.toLowerCase(Locale.US).startsWith("tinkhybriddecrypt") || catalogueName.toLowerCase(Locale.US).startsWith("tinkhybridencrypt")) {
                error += "Maybe call HybridConfig.register().";
            }
            else if (catalogueName.toLowerCase(Locale.US).startsWith("tinkmac")) {
                error += "Maybe call MacConfig.register().";
            }
            else if (catalogueName.toLowerCase(Locale.US).startsWith("tinkpublickeysign") || catalogueName.toLowerCase(Locale.US).startsWith("tinkpublickeyverify")) {
                error += "Maybe call SignatureConfig.register().";
            }
            else if (catalogueName.toLowerCase(Locale.US).startsWith("tink")) {
                error += "Maybe call TinkConfig.register().";
            }
            throw new GeneralSecurityException(error);
        }
        return catalogue;
    }
    
    public static synchronized <P> void registerKeyManager(final KeyManager<P> manager) throws GeneralSecurityException {
        registerKeyManager(manager, true);
    }
    
    private static Set<Class<?>> createAllowedPrimitives() {
        final HashSet<Class<?>> result = new HashSet<Class<?>>();
        result.add(Aead.class);
        result.add(DeterministicAead.class);
        result.add(StreamingAead.class);
        result.add(HybridEncrypt.class);
        result.add(HybridDecrypt.class);
        result.add(Mac.class);
        result.add(Prf.class);
        result.add(PublicKeySign.class);
        result.add(PublicKeyVerify.class);
        return result;
    }
    
    public static synchronized <P> void registerKeyManager(final KeyManager<P> manager, final boolean newKeyAllowed) throws GeneralSecurityException {
        if (manager == null) {
            throw new IllegalArgumentException("key manager must be non-null.");
        }
        if (!Registry.ALLOWED_PRIMITIVES.contains(manager.getPrimitiveClass())) {
            throw new GeneralSecurityException("Registration of key managers for class " + manager.getPrimitiveClass() + " has been disabled. Please file an issue on https://github.com/tink-crypto/tink-java");
        }
        if (!TinkFipsUtil.AlgorithmFipsCompatibility.ALGORITHM_NOT_FIPS.isCompatible()) {
            throw new GeneralSecurityException("Registering key managers is not supported in FIPS mode");
        }
        KeyManagerRegistry.globalInstance().registerKeyManager(manager, newKeyAllowed);
    }
    
    @Deprecated
    public static synchronized <P> void registerKeyManager(final String typeUrl, final KeyManager<P> manager) throws GeneralSecurityException {
        registerKeyManager(typeUrl, manager, true);
    }
    
    @Deprecated
    public static synchronized <P> void registerKeyManager(final String typeUrl, final KeyManager<P> manager, final boolean newKeyAllowed) throws GeneralSecurityException {
        if (manager == null) {
            throw new IllegalArgumentException("key manager must be non-null.");
        }
        if (!typeUrl.equals(manager.getKeyType())) {
            throw new GeneralSecurityException("Manager does not support key type " + typeUrl + ".");
        }
        registerKeyManager(manager, newKeyAllowed);
    }
    
    @Deprecated
    public static <P> KeyManager<P> getKeyManager(final String typeUrl, final Class<P> primitiveClass) throws GeneralSecurityException {
        return KeyManagerRegistry.globalInstance().getKeyManager(typeUrl, primitiveClass);
    }
    
    @Deprecated
    public static KeyManager<?> getUntypedKeyManager(final String typeUrl) throws GeneralSecurityException {
        return KeyManagerRegistry.globalInstance().getUntypedKeyManager(typeUrl);
    }
    
    @Deprecated
    public static synchronized KeyData newKeyData(final KeyTemplate keyTemplate) throws GeneralSecurityException {
        final KeyManager<?> manager = KeyManagerRegistry.globalInstance().getUntypedKeyManager(keyTemplate.getTypeUrl());
        if (KeyManagerRegistry.globalInstance().isNewKeyAllowed(keyTemplate.getTypeUrl())) {
            return manager.newKeyData(keyTemplate.getValue());
        }
        throw new GeneralSecurityException("newKey-operation not permitted for key type " + keyTemplate.getTypeUrl());
    }
    
    @Deprecated
    public static synchronized KeyData newKeyData(final com.google.crypto.tink.KeyTemplate keyTemplate) throws GeneralSecurityException {
        final byte[] serializedKeyTemplate = TinkProtoParametersFormat.serialize(keyTemplate.toParameters());
        try {
            return newKeyData(KeyTemplate.parseFrom(serializedKeyTemplate, ExtensionRegistryLite.getEmptyRegistry()));
        }
        catch (final InvalidProtocolBufferException e) {
            throw new GeneralSecurityException("Failed to parse serialized parameters", e);
        }
    }
    
    @Deprecated
    public static synchronized MessageLite newKey(final KeyTemplate keyTemplate) throws GeneralSecurityException {
        final KeyManager<?> manager = getUntypedKeyManager(keyTemplate.getTypeUrl());
        if (KeyManagerRegistry.globalInstance().isNewKeyAllowed(keyTemplate.getTypeUrl())) {
            return manager.newKey(keyTemplate.getValue());
        }
        throw new GeneralSecurityException("newKey-operation not permitted for key type " + keyTemplate.getTypeUrl());
    }
    
    @Deprecated
    public static synchronized MessageLite newKey(final String typeUrl, final MessageLite format) throws GeneralSecurityException {
        final KeyManager<?> manager = getUntypedKeyManager(typeUrl);
        if (KeyManagerRegistry.globalInstance().isNewKeyAllowed(typeUrl)) {
            return manager.newKey(format);
        }
        throw new GeneralSecurityException("newKey-operation not permitted for key type " + typeUrl);
    }
    
    @Deprecated
    public static KeyData getPublicKeyData(final String typeUrl, final ByteString serializedPrivateKey) throws GeneralSecurityException {
        final KeyManager<?> manager = getUntypedKeyManager(typeUrl);
        if (!(manager instanceof PrivateKeyManager)) {
            throw new GeneralSecurityException("manager for key type " + typeUrl + " is not a PrivateKeyManager");
        }
        return ((PrivateKeyManager)manager).getPublicKeyData(serializedPrivateKey);
    }
    
    @Deprecated
    public static <P> P getPrimitive(final String typeUrl, final MessageLite key, final Class<P> primitiveClass) throws GeneralSecurityException {
        final KeyManager<P> manager = KeyManagerRegistry.globalInstance().getKeyManager(typeUrl, primitiveClass);
        return manager.getPrimitive(key.toByteString());
    }
    
    @Deprecated
    public static <P> P getPrimitive(final String typeUrl, final ByteString serializedKey, final Class<P> primitiveClass) throws GeneralSecurityException {
        final KeyManager<P> manager = KeyManagerRegistry.globalInstance().getKeyManager(typeUrl, primitiveClass);
        return manager.getPrimitive(serializedKey);
    }
    
    @Deprecated
    public static <P> P getPrimitive(final String typeUrl, final byte[] serializedKey, final Class<P> primitiveClass) throws GeneralSecurityException {
        return getPrimitive(typeUrl, ByteString.copyFrom(serializedKey), primitiveClass);
    }
    
    @Deprecated
    public static <P> P getPrimitive(final KeyData keyData, final Class<P> primitiveClass) throws GeneralSecurityException {
        return getPrimitive(keyData.getTypeUrl(), keyData.getValue(), primitiveClass);
    }
    
    static <KeyT extends Key, P> P getFullPrimitive(final KeyT key, final Class<P> primitiveClass) throws GeneralSecurityException {
        return MutablePrimitiveRegistry.globalInstance().getPrimitive(key, primitiveClass);
    }
    
    public static synchronized List<String> keyTemplates() {
        return MutableParametersRegistry.globalInstance().getNames();
    }
    
    public static synchronized void restrictToFipsIfEmpty() throws GeneralSecurityException {
        KeyManagerRegistry.globalInstance().restrictToFipsIfEmptyAndGlobalInstance();
    }
    
    private Registry() {
    }
    
    static {
        logger = Logger.getLogger(Registry.class.getName());
        catalogueMap = new ConcurrentHashMap<String, Catalogue<?>>();
        ALLOWED_PRIMITIVES = Collections.unmodifiableSet((Set<? extends Class<?>>)createAllowedPrimitives());
    }
}
