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

package org.bouncycastle.crypto.agreement;

import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.math.ec.ECConstants;
import org.bouncycastle.math.ec.ECAlgorithms;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import java.math.BigInteger;
import org.bouncycastle.crypto.CryptoServicesRegistrar;
import org.bouncycastle.crypto.params.ECKeyParameters;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.BasicAgreement;

public class ECDHBasicAgreement implements BasicAgreement
{
    private ECPrivateKeyParameters key;
    
    @Override
    public void init(final CipherParameters cipherParameters) {
        this.key = (ECPrivateKeyParameters)cipherParameters;
        CryptoServicesRegistrar.checkConstraints(Utils.getDefaultProperties("ECDH", this.key));
    }
    
    @Override
    public int getFieldSize() {
        return this.key.getParameters().getCurve().getFieldElementEncodingLength();
    }
    
    @Override
    public BigInteger calculateAgreement(final CipherParameters cipherParameters) {
        final ECPublicKeyParameters ecPublicKeyParameters = (ECPublicKeyParameters)cipherParameters;
        final ECDomainParameters parameters = this.key.getParameters();
        if (!parameters.equals(ecPublicKeyParameters.getParameters())) {
            throw new IllegalStateException("ECDH public key has wrong domain parameters");
        }
        BigInteger val = this.key.getD();
        ECPoint ecPoint = ECAlgorithms.cleanPoint(parameters.getCurve(), ecPublicKeyParameters.getQ());
        if (ecPoint.isInfinity()) {
            throw new IllegalStateException("Infinity is not a valid public key for ECDH");
        }
        final BigInteger h = parameters.getH();
        if (!h.equals(ECConstants.ONE)) {
            val = parameters.getHInv().multiply(val).mod(parameters.getN());
            ecPoint = ECAlgorithms.referenceMultiply(ecPoint, h);
        }
        final ECPoint normalize = ecPoint.multiply(val).normalize();
        if (normalize.isInfinity()) {
            throw new IllegalStateException("Infinity is not a valid agreement value for ECDH");
        }
        return normalize.getAffineXCoord().toBigInteger();
    }
}
