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

package com.nimbusds.jose.crypto.impl;

import java.util.Collections;
import java.util.LinkedHashSet;
import com.nimbusds.jose.util.Base64URL;
import com.nimbusds.jose.JWECryptoParts;
import com.nimbusds.jose.JWEHeader;
import com.nimbusds.jose.JOSEException;
import java.util.Collection;
import javax.crypto.SecretKey;
import com.nimbusds.jose.jwk.Curve;
import com.nimbusds.jose.EncryptionMethod;
import com.nimbusds.jose.JWEAlgorithm;
import java.util.Set;

public abstract class ECDHCryptoProvider extends BaseJWEProvider
{
    public static final Set<JWEAlgorithm> SUPPORTED_ALGORITHMS;
    public static final Set<EncryptionMethod> SUPPORTED_ENCRYPTION_METHODS;
    private final Curve curve;
    private final ConcatKDF concatKDF;
    
    protected ECDHCryptoProvider(final Curve curve, final SecretKey cek) throws JOSEException {
        super(ECDHCryptoProvider.SUPPORTED_ALGORITHMS, ContentCryptoProvider.SUPPORTED_ENCRYPTION_METHODS, cek);
        final Curve definedCurve = (curve != null) ? curve : new Curve("unknown");
        if (!this.supportedEllipticCurves().contains(curve)) {
            throw new JOSEException(AlgorithmSupportMessage.unsupportedEllipticCurve(definedCurve, this.supportedEllipticCurves()));
        }
        this.curve = curve;
        this.concatKDF = new ConcatKDF("SHA-256");
    }
    
    protected ConcatKDF getConcatKDF() {
        return this.concatKDF;
    }
    
    public abstract Set<Curve> supportedEllipticCurves();
    
    public Curve getCurve() {
        return this.curve;
    }
    
    protected JWECryptoParts encryptWithZ(final JWEHeader header, final SecretKey Z, final byte[] clearText, final byte[] aad) throws JOSEException {
        final JWEAlgorithm alg = JWEHeaderValidation.getAlgorithmAndEnsureNotNull(header);
        final ECDH.AlgorithmMode algMode = ECDH.resolveAlgorithmMode(alg);
        final EncryptionMethod enc = header.getEncryptionMethod();
        this.getConcatKDF().getJCAContext().setProvider(this.getJCAContext().getMACProvider());
        final SecretKey sharedKey = ECDH.deriveSharedKey(header, Z, this.getConcatKDF());
        SecretKey cek;
        Base64URL encryptedKey;
        if (algMode.equals(ECDH.AlgorithmMode.DIRECT)) {
            if (this.isCEKProvided()) {
                throw new JOSEException("The provided CEK is not supported");
            }
            cek = sharedKey;
            encryptedKey = null;
        }
        else {
            if (!algMode.equals(ECDH.AlgorithmMode.KW)) {
                throw new JOSEException("Unexpected JWE ECDH algorithm mode: " + algMode);
            }
            cek = this.getCEK(enc);
            encryptedKey = Base64URL.encode(AESKW.wrapCEK(cek, sharedKey, this.getJCAContext().getKeyEncryptionProvider()));
        }
        return ContentCryptoProvider.encrypt(header, clearText, aad, cek, encryptedKey, this.getJCAContext());
    }
    
    protected byte[] decryptWithZ(final JWEHeader header, final byte[] aad, final SecretKey Z, final Base64URL encryptedKey, final Base64URL iv, final Base64URL cipherText, final Base64URL authTag) throws JOSEException {
        final JWEAlgorithm alg = JWEHeaderValidation.getAlgorithmAndEnsureNotNull(header);
        final ECDH.AlgorithmMode algMode = ECDH.resolveAlgorithmMode(alg);
        this.getConcatKDF().getJCAContext().setProvider(this.getJCAContext().getMACProvider());
        final SecretKey sharedKey = ECDH.deriveSharedKey(header, Z, this.getConcatKDF());
        SecretKey cek;
        if (algMode.equals(ECDH.AlgorithmMode.DIRECT)) {
            cek = sharedKey;
        }
        else {
            if (!algMode.equals(ECDH.AlgorithmMode.KW)) {
                throw new JOSEException("Unexpected JWE ECDH algorithm mode: " + algMode);
            }
            if (encryptedKey == null) {
                throw new JOSEException("Missing JWE encrypted key");
            }
            cek = AESKW.unwrapCEK(sharedKey, encryptedKey.decode(), this.getJCAContext().getKeyEncryptionProvider());
        }
        return ContentCryptoProvider.decrypt(header, aad, encryptedKey, iv, cipherText, authTag, cek, this.getJCAContext());
    }
    
    static {
        SUPPORTED_ENCRYPTION_METHODS = ContentCryptoProvider.SUPPORTED_ENCRYPTION_METHODS;
        final Set<JWEAlgorithm> algs = new LinkedHashSet<JWEAlgorithm>();
        algs.add(JWEAlgorithm.ECDH_ES);
        algs.add(JWEAlgorithm.ECDH_ES_A128KW);
        algs.add(JWEAlgorithm.ECDH_ES_A192KW);
        algs.add(JWEAlgorithm.ECDH_ES_A256KW);
        SUPPORTED_ALGORITHMS = Collections.unmodifiableSet((Set<? extends JWEAlgorithm>)algs);
    }
}
