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

package org.bouncycastle.crypto.signers;

import org.bouncycastle.math.ec.FixedPointCombMultiplier;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.math.ec.ECAlgorithms;
import org.bouncycastle.math.ec.ECMultiplier;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.math.ec.ECConstants;
import org.bouncycastle.util.BigIntegers;
import org.bouncycastle.util.Arrays;
import java.math.BigInteger;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.CryptoServicesRegistrar;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.crypto.CipherParameters;
import java.security.SecureRandom;
import org.bouncycastle.crypto.params.ECKeyParameters;
import org.bouncycastle.crypto.DSAExt;

public class ECGOST3410Signer implements DSAExt
{
    ECKeyParameters key;
    SecureRandom random;
    
    @Override
    public void init(final boolean b, CipherParameters parameters) {
        if (b) {
            SecureRandom random = null;
            if (parameters instanceof ParametersWithRandom) {
                final ParametersWithRandom parametersWithRandom = (ParametersWithRandom)parameters;
                random = parametersWithRandom.getRandom();
                parameters = parametersWithRandom.getParameters();
            }
            this.key = (ECPrivateKeyParameters)parameters;
            this.random = CryptoServicesRegistrar.getSecureRandom(random);
        }
        else {
            this.key = (ECPublicKeyParameters)parameters;
            this.random = null;
        }
        CryptoServicesRegistrar.checkConstraints(Utils.getDefaultProperties("ECGOST3410", this.key, b));
    }
    
    @Override
    public BigInteger getOrder() {
        return this.key.getParameters().getN();
    }
    
    @Override
    public BigInteger[] generateSignature(final byte[] array) {
        final BigInteger val = new BigInteger(1, Arrays.reverse(array));
        final ECDomainParameters parameters = this.key.getParameters();
        final BigInteger n = parameters.getN();
        final BigInteger d = ((ECPrivateKeyParameters)this.key).getD();
        final ECMultiplier basePointMultiplier = this.createBasePointMultiplier();
        BigInteger mod;
        BigInteger mod2;
        while (true) {
            final BigInteger randomBigInteger = BigIntegers.createRandomBigInteger(n.bitLength(), this.random);
            if (!randomBigInteger.equals(ECConstants.ZERO)) {
                mod = basePointMultiplier.multiply(parameters.getG(), randomBigInteger).normalize().getAffineXCoord().toBigInteger().mod(n);
                if (mod.equals(ECConstants.ZERO)) {
                    continue;
                }
                mod2 = randomBigInteger.multiply(val).add(d.multiply(mod)).mod(n);
                if (!mod2.equals(ECConstants.ZERO)) {
                    break;
                }
                continue;
            }
        }
        return new BigInteger[] { mod, mod2 };
    }
    
    @Override
    public boolean verifySignature(final byte[] array, final BigInteger bigInteger, final BigInteger bigInteger2) {
        final BigInteger bigInteger3 = new BigInteger(1, Arrays.reverse(array));
        final BigInteger n = this.key.getParameters().getN();
        if (bigInteger.compareTo(ECConstants.ONE) < 0 || bigInteger.compareTo(n) >= 0) {
            return false;
        }
        if (bigInteger2.compareTo(ECConstants.ONE) < 0 || bigInteger2.compareTo(n) >= 0) {
            return false;
        }
        final BigInteger modOddInverseVar = BigIntegers.modOddInverseVar(n, bigInteger3);
        final ECPoint normalize = ECAlgorithms.sumOfTwoMultiplies(this.key.getParameters().getG(), bigInteger2.multiply(modOddInverseVar).mod(n), ((ECPublicKeyParameters)this.key).getQ(), n.subtract(bigInteger).multiply(modOddInverseVar).mod(n)).normalize();
        return !normalize.isInfinity() && normalize.getAffineXCoord().toBigInteger().mod(n).equals(bigInteger);
    }
    
    protected ECMultiplier createBasePointMultiplier() {
        return new FixedPointCombMultiplier();
    }
}
