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

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

import java.security.spec.EncodedKeySpec;
import java.security.Signature;
import com.google.crypto.tink.internal.Util;
import com.google.crypto.tink.internal.ConscryptUtil;
import com.google.crypto.tink.AccessesPartialKey;
import java.security.spec.KeySpec;
import java.security.KeyFactory;
import com.google.crypto.tink.signature.SlhDsaParameters;
import java.security.GeneralSecurityException;
import com.google.crypto.tink.signature.SlhDsaPublicKey;
import java.security.Provider;
import java.security.PublicKey;
import com.google.crypto.tink.config.internal.TinkFipsUtil;
import com.google.errorprone.annotations.Immutable;
import com.google.crypto.tink.PublicKeyVerify;

@Immutable
public class SlhDsaVerifyConscrypt implements PublicKeyVerify
{
    public static final TinkFipsUtil.AlgorithmFipsCompatibility FIPS;
    static final int SLH_DSA_SHA2_128S_SIG_LENGTH = 7856;
    static final String SLH_DSA_SHA2_128S_ALGORITHM = "SLH-DSA-SHA2-128S";
    private final byte[] outputPrefix;
    private final PublicKey publicKey;
    private final String algorithm;
    private final int signatureLength;
    private final Provider provider;
    
    public SlhDsaVerifyConscrypt(final byte[] outputPrefix, final PublicKey publicKey, final String algorithm, final int signatureLength, final Provider provider) {
        this.outputPrefix = outputPrefix;
        this.publicKey = publicKey;
        this.algorithm = algorithm;
        this.signatureLength = signatureLength;
        this.provider = provider;
    }
    
    @AccessesPartialKey
    public static PublicKeyVerify createWithProvider(final SlhDsaPublicKey slhDsaPublicKey, final Provider provider) throws GeneralSecurityException {
        if (provider == null) {
            throw new NullPointerException("provider must not be null");
        }
        if (!SlhDsaVerifyConscrypt.FIPS.isCompatible()) {
            throw new GeneralSecurityException("Can not use SLH-DSA in FIPS-mode, as it is not yet certified in Conscrypt.");
        }
        final SlhDsaParameters parameters = slhDsaPublicKey.getParameters();
        if (parameters.getPrivateKeySize() != 64 || parameters.getHashType() != SlhDsaParameters.HashType.SHA2 || parameters.getSignatureType() != SlhDsaParameters.SignatureType.SMALL_SIGNATURE) {
            throw new GeneralSecurityException("Unsupported SLH-DSA parameters");
        }
        final PublicKey publicKey = KeyFactory.getInstance("SLH-DSA-SHA2-128S", provider).generatePublic(new RawKeySpec(slhDsaPublicKey.getSerializedPublicKey().toByteArray()));
        return new SlhDsaVerifyConscrypt(slhDsaPublicKey.getOutputPrefix().toByteArray(), publicKey, "SLH-DSA-SHA2-128S", 7856, provider);
    }
    
    @AccessesPartialKey
    public static PublicKeyVerify create(final SlhDsaPublicKey slhDsaPublicKey) throws GeneralSecurityException {
        if (!SlhDsaVerifyConscrypt.FIPS.isCompatible()) {
            throw new GeneralSecurityException("Can not use SLH-DSA in FIPS-mode, as it is not yet certified in Conscrypt.");
        }
        final Provider provider = ConscryptUtil.providerOrNull();
        if (provider == null) {
            throw new GeneralSecurityException("Obtaining Conscrypt provider failed");
        }
        return createWithProvider(slhDsaPublicKey, provider);
    }
    
    @Override
    public void verify(final byte[] signature, final byte[] data) throws GeneralSecurityException {
        if (!Util.isPrefix(this.outputPrefix, signature)) {
            throw new GeneralSecurityException("Invalid signature (output prefix mismatch)");
        }
        if (signature.length != this.outputPrefix.length + this.signatureLength) {
            throw new GeneralSecurityException("Invalid signature length");
        }
        final Signature verifier = Signature.getInstance(this.algorithm, this.provider);
        verifier.initVerify(this.publicKey);
        verifier.update(data);
        if (!verifier.verify(signature, this.outputPrefix.length, this.signatureLength)) {
            throw new GeneralSecurityException("Invalid signature");
        }
    }
    
    public static boolean isSupported() {
        if (!SlhDsaVerifyConscrypt.FIPS.isCompatible()) {
            return false;
        }
        final Provider provider = ConscryptUtil.providerOrNull();
        if (provider == null) {
            return false;
        }
        try {
            final KeyFactory unusedKeyFactory = KeyFactory.getInstance("SLH-DSA-SHA2-128S", provider);
            final Signature unusedSignature = Signature.getInstance("SLH-DSA-SHA2-128S", provider);
            return true;
        }
        catch (final GeneralSecurityException e) {
            return false;
        }
    }
    
    static {
        FIPS = TinkFipsUtil.AlgorithmFipsCompatibility.ALGORITHM_NOT_FIPS;
    }
    
    public static final class RawKeySpec extends EncodedKeySpec
    {
        public RawKeySpec(final byte[] encoded) {
            super(encoded);
        }
        
        @Override
        public String getFormat() {
            return "raw";
        }
    }
}
