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

package org.bouncycastle.crypto.kems;

import org.bouncycastle.math.ec.ECPoint;
import java.math.BigInteger;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.CryptoServiceProperties;
import org.bouncycastle.crypto.CryptoServicesRegistrar;
import org.bouncycastle.crypto.constraints.DefaultServiceProperties;
import org.bouncycastle.crypto.CryptoServicePurpose;
import org.bouncycastle.crypto.constraints.ConstraintUtils;
import org.bouncycastle.crypto.DerivationFunction;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.EncapsulatedSecretExtractor;

public class ECIESKEMExtractor implements EncapsulatedSecretExtractor
{
    private final ECPrivateKeyParameters decKey;
    private int keyLen;
    private DerivationFunction kdf;
    private boolean CofactorMode;
    private boolean OldCofactorMode;
    private boolean SingleHashMode;
    
    public ECIESKEMExtractor(final ECPrivateKeyParameters decKey, final int keyLen, final DerivationFunction kdf) {
        this.decKey = decKey;
        this.keyLen = keyLen;
        this.kdf = kdf;
        this.CofactorMode = false;
        this.OldCofactorMode = false;
        this.SingleHashMode = false;
    }
    
    public ECIESKEMExtractor(final ECPrivateKeyParameters decKey, final int keyLen, final DerivationFunction kdf, final boolean cofactorMode, final boolean oldCofactorMode, final boolean singleHashMode) {
        this.decKey = decKey;
        this.keyLen = keyLen;
        this.kdf = kdf;
        this.CofactorMode = cofactorMode;
        if (cofactorMode) {
            this.OldCofactorMode = false;
        }
        else {
            this.OldCofactorMode = oldCofactorMode;
        }
        this.SingleHashMode = singleHashMode;
        CryptoServicesRegistrar.checkConstraints(new DefaultServiceProperties("ECIESKem", ConstraintUtils.bitsOfSecurityFor(this.decKey.getParameters().getCurve()), decKey, CryptoServicePurpose.DECRYPTION));
    }
    
    @Override
    public byte[] extractSecret(final byte[] array) {
        final ECPrivateKeyParameters decKey = this.decKey;
        final ECDomainParameters parameters = decKey.getParameters();
        final ECCurve curve = parameters.getCurve();
        final BigInteger n = parameters.getN();
        final BigInteger h = parameters.getH();
        ECPoint ecPoint = curve.decodePoint(array);
        if (this.CofactorMode || this.OldCofactorMode) {
            ecPoint = ecPoint.multiply(h);
        }
        BigInteger bigInteger = decKey.getD();
        if (this.CofactorMode) {
            bigInteger = bigInteger.multiply(parameters.getHInv()).mod(n);
        }
        return ECIESKEMGenerator.deriveKey(this.SingleHashMode, this.kdf, this.keyLen, array, ecPoint.multiply(bigInteger).normalize().getAffineXCoord().getEncoded());
    }
    
    @Override
    public int getEncapsulationLength() {
        return this.decKey.getParameters().getCurve().getAffinePointEncodingLength(false);
    }
}
