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

package org.bouncycastle.pqc.crypto.mldsa;

import org.bouncycastle.crypto.digests.SHA512Digest;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.CryptoException;
import org.bouncycastle.crypto.digests.SHAKEDigest;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import java.io.IOException;
import org.bouncycastle.pqc.crypto.DigestUtils;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.crypto.params.ParametersWithContext;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.Digest;
import java.security.SecureRandom;
import org.bouncycastle.crypto.Signer;

public class HashMLDSASigner implements Signer
{
    private static final byte[] EMPTY_CONTEXT;
    private MLDSAPublicKeyParameters pubKey;
    private MLDSAPrivateKeyParameters privKey;
    private SecureRandom random;
    private MLDSAEngine engine;
    private Digest digest;
    private byte[] digestOIDEncoding;
    
    @Override
    public void init(final boolean b, CipherParameters parameters) {
        byte[] array = HashMLDSASigner.EMPTY_CONTEXT;
        if (parameters instanceof ParametersWithContext) {
            final ParametersWithContext parametersWithContext = (ParametersWithContext)parameters;
            array = parametersWithContext.getContext();
            parameters = parametersWithContext.getParameters();
            if (array.length > 255) {
                throw new IllegalArgumentException("context too long");
            }
        }
        MLDSAParameters mldsaParameters;
        if (b) {
            this.pubKey = null;
            if (parameters instanceof ParametersWithRandom) {
                final ParametersWithRandom parametersWithRandom = (ParametersWithRandom)parameters;
                this.privKey = (MLDSAPrivateKeyParameters)parametersWithRandom.getParameters();
                this.random = parametersWithRandom.getRandom();
            }
            else {
                this.privKey = (MLDSAPrivateKeyParameters)parameters;
                this.random = null;
            }
            mldsaParameters = this.privKey.getParameters();
            (this.engine = mldsaParameters.getEngine(this.random)).initSign(this.privKey.tr, true, array);
        }
        else {
            this.pubKey = (MLDSAPublicKeyParameters)parameters;
            this.privKey = null;
            this.random = null;
            mldsaParameters = this.pubKey.getParameters();
            (this.engine = mldsaParameters.getEngine(null)).initVerify(this.pubKey.rho, this.pubKey.t1, true, array);
        }
        this.initDigest(mldsaParameters);
    }
    
    private void initDigest(final MLDSAParameters mldsaParameters) {
        this.digest = createDigest(mldsaParameters);
        final ASN1ObjectIdentifier digestOid = DigestUtils.getDigestOid(this.digest.getAlgorithmName());
        try {
            this.digestOIDEncoding = digestOid.getEncoded("DER");
        }
        catch (final IOException ex) {
            throw new IllegalStateException("oid encoding failed: " + ex.getMessage());
        }
    }
    
    @Override
    public void update(final byte b) {
        this.digest.update(b);
    }
    
    @Override
    public void update(final byte[] array, final int n, final int n2) {
        this.digest.update(array, n, n2);
    }
    
    @Override
    public byte[] generateSignature() throws CryptoException, DataLengthException {
        final SHAKEDigest finishPreHash = this.finishPreHash();
        final byte[] bytes = new byte[32];
        if (this.random != null) {
            this.random.nextBytes(bytes);
        }
        return this.engine.generateSignature(this.engine.generateMu(finishPreHash), finishPreHash, this.privKey.rho, this.privKey.k, this.privKey.t0, this.privKey.s1, this.privKey.s2, bytes);
    }
    
    @Override
    public boolean verifySignature(final byte[] array) {
        return this.engine.verifyInternal(array, array.length, this.finishPreHash(), this.pubKey.rho, this.pubKey.t1);
    }
    
    @Override
    public void reset() {
        this.digest.reset();
    }
    
    private SHAKEDigest finishPreHash() {
        final byte[] array = new byte[this.digest.getDigestSize()];
        this.digest.doFinal(array, 0);
        final SHAKEDigest shake256Digest = this.engine.getShake256Digest();
        shake256Digest.update(this.digestOIDEncoding, 0, this.digestOIDEncoding.length);
        shake256Digest.update(array, 0, array.length);
        return shake256Digest;
    }
    
    private static Digest createDigest(final MLDSAParameters mldsaParameters) {
        switch (mldsaParameters.getType()) {
            case 0:
            case 1: {
                return new SHA512Digest();
            }
            default: {
                throw new IllegalArgumentException("unknown parameters type");
            }
        }
    }
    
    static {
        EMPTY_CONTEXT = new byte[0];
    }
}
