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

package com.google.crypto.tink.signature.internal;

import java.util.Arrays;
import com.google.crypto.tink.subtle.Bytes;
import com.google.crypto.tink.internal.Util;
import com.google.crypto.tink.proto.OutputPrefixType;
import com.google.crypto.tink.internal.OutputPrefixUtil;
import java.security.GeneralSecurityException;
import com.google.crypto.tink.KeyManager;
import com.google.crypto.tink.internal.ProtoKeySerialization;
import com.google.crypto.tink.internal.KeyManagerRegistry;
import com.google.crypto.tink.InsecureSecretKeyAccess;
import com.google.crypto.tink.internal.LegacyProtoKey;
import com.google.errorprone.annotations.Immutable;
import com.google.crypto.tink.PublicKeyVerify;

@Immutable
public final class LegacyFullVerify implements PublicKeyVerify
{
    private final PublicKeyVerify rawVerifier;
    private final byte[] outputPrefix;
    private final byte[] messageSuffix;
    
    public static PublicKeyVerify create(final LegacyProtoKey key) throws GeneralSecurityException {
        final ProtoKeySerialization protoKeySerialization = key.getSerialization(InsecureSecretKeyAccess.get());
        final KeyManager<PublicKeyVerify> manager = KeyManagerRegistry.globalInstance().getKeyManager(protoKeySerialization.getTypeUrl(), PublicKeyVerify.class);
        final PublicKeyVerify rawVerifier = manager.getPrimitive(protoKeySerialization.getValue());
        return new LegacyFullVerify(rawVerifier, getOutputPrefix(protoKeySerialization), getMessageSuffix(protoKeySerialization));
    }
    
    static byte[] getOutputPrefix(final ProtoKeySerialization key) throws GeneralSecurityException {
        switch (key.getOutputPrefixType()) {
            case LEGACY:
            case CRUNCHY: {
                return OutputPrefixUtil.getLegacyOutputPrefix(key.getIdRequirementOrNull()).toByteArray();
            }
            case TINK: {
                return OutputPrefixUtil.getTinkOutputPrefix(key.getIdRequirementOrNull()).toByteArray();
            }
            case RAW: {
                return OutputPrefixUtil.EMPTY_PREFIX.toByteArray();
            }
            default: {
                throw new GeneralSecurityException("unknown output prefix type");
            }
        }
    }
    
    static byte[] getMessageSuffix(final ProtoKeySerialization key) {
        if (key.getOutputPrefixType().equals(OutputPrefixType.LEGACY)) {
            return new byte[] { 0 };
        }
        return new byte[0];
    }
    
    private LegacyFullVerify(final PublicKeyVerify rawVerifier, final byte[] outputPrefix, final byte[] messageSuffix) {
        this.rawVerifier = rawVerifier;
        this.outputPrefix = outputPrefix;
        this.messageSuffix = messageSuffix;
    }
    
    @Override
    public void verify(final byte[] signature, final byte[] data) throws GeneralSecurityException {
        if (this.outputPrefix.length == 0 && this.messageSuffix.length == 0) {
            this.rawVerifier.verify(signature, data);
            return;
        }
        if (!Util.isPrefix(this.outputPrefix, signature)) {
            throw new GeneralSecurityException("Invalid signature (output prefix mismatch)");
        }
        byte[] dataCopy = data;
        if (this.messageSuffix.length != 0) {
            dataCopy = Bytes.concat(new byte[][] { data, this.messageSuffix });
        }
        final byte[] signatureNoPrefix = Arrays.copyOfRange(signature, this.outputPrefix.length, signature.length);
        this.rawVerifier.verify(signatureNoPrefix, dataCopy);
    }
}
