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

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

import java.security.Signature;
import com.google.crypto.tink.internal.ConscryptUtil;
import com.google.crypto.tink.AccessesPartialKey;
import java.nio.charset.StandardCharsets;
import java.security.spec.KeySpec;
import com.google.crypto.tink.InsecureSecretKeyAccess;
import java.security.KeyFactory;
import com.google.crypto.tink.signature.SlhDsaParameters;
import java.security.GeneralSecurityException;
import com.google.crypto.tink.signature.SlhDsaPrivateKey;
import java.security.Provider;
import java.security.PrivateKey;
import com.google.crypto.tink.config.internal.TinkFipsUtil;
import com.google.errorprone.annotations.Immutable;
import com.google.crypto.tink.PublicKeySign;

@Immutable
public class SlhDsaSignConscrypt implements PublicKeySign
{
    public static final TinkFipsUtil.AlgorithmFipsCompatibility FIPS;
    private static final String TEST_WORKLOAD = "test workload";
    private final byte[] outputPrefix;
    private final PrivateKey privateKey;
    private final String algorithm;
    private final int signatureLength;
    private final Provider provider;
    
    public SlhDsaSignConscrypt(final byte[] outputPrefix, final PrivateKey privateKey, final String algorithm, final int signatureLength, final Provider provider) {
        this.outputPrefix = outputPrefix;
        this.privateKey = privateKey;
        this.algorithm = algorithm;
        this.signatureLength = signatureLength;
        this.provider = provider;
    }
    
    @AccessesPartialKey
    public static PublicKeySign createWithProvider(final SlhDsaPrivateKey slhDsaPrivateKey, final Provider provider) throws GeneralSecurityException {
        if (provider == null) {
            throw new NullPointerException("provider must not be null");
        }
        if (!SlhDsaSignConscrypt.FIPS.isCompatible()) {
            throw new GeneralSecurityException("Can not use SLH-DSA in FIPS-mode, as it is not yet certified in Conscrypt.");
        }
        final SlhDsaParameters parameters = slhDsaPrivateKey.getParameters();
        if (parameters.getPrivateKeySize() != 64 || parameters.getHashType() != SlhDsaParameters.HashType.SHA2 || parameters.getSignatureType() != SlhDsaParameters.SignatureType.SMALL_SIGNATURE) {
            throw new GeneralSecurityException("Unsupported SLH-DSA parameters");
        }
        final PrivateKey privateKey = KeyFactory.getInstance("SLH-DSA-SHA2-128S", provider).generatePrivate(new SlhDsaVerifyConscrypt.RawKeySpec(slhDsaPrivateKey.getPrivateKeyBytes().toByteArray(InsecureSecretKeyAccess.get())));
        final byte[] testSignature = signInternal("test workload".getBytes(StandardCharsets.UTF_8), slhDsaPrivateKey.getOutputPrefix().toByteArray(), privateKey, "SLH-DSA-SHA2-128S", 7856, provider);
        final SlhDsaVerifyConscrypt verifier = (SlhDsaVerifyConscrypt)SlhDsaVerifyConscrypt.createWithProvider(slhDsaPrivateKey.getPublicKey(), provider);
        verifier.verify(testSignature, "test workload".getBytes(StandardCharsets.UTF_8));
        return new SlhDsaSignConscrypt(slhDsaPrivateKey.getOutputPrefix().toByteArray(), privateKey, "SLH-DSA-SHA2-128S", 7856, provider);
    }
    
    @AccessesPartialKey
    public static PublicKeySign create(final SlhDsaPrivateKey slhDsaPrivateKey) throws GeneralSecurityException {
        if (!SlhDsaSignConscrypt.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(slhDsaPrivateKey, provider);
    }
    
    public static boolean isSupported() {
        return SlhDsaVerifyConscrypt.isSupported();
    }
    
    @Override
    public byte[] sign(final byte[] data) throws GeneralSecurityException {
        return signInternal(data, this.outputPrefix, this.privateKey, this.algorithm, this.signatureLength, this.provider);
    }
    
    private static byte[] signInternal(final byte[] data, final byte[] outputPrefix, final PrivateKey privateKey, final String algorithm, final int signatureLength, final Provider provider) throws GeneralSecurityException {
        final Signature signer = Signature.getInstance(algorithm, provider);
        signer.initSign(privateKey);
        signer.update(data);
        final byte[] signature = new byte[outputPrefix.length + signatureLength];
        if (outputPrefix.length > 0) {
            System.arraycopy(outputPrefix, 0, signature, 0, outputPrefix.length);
        }
        signer.sign(signature, outputPrefix.length, signatureLength);
        return signature;
    }
    
    static {
        FIPS = TinkFipsUtil.AlgorithmFipsCompatibility.ALGORITHM_NOT_FIPS;
    }
}
