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

package com.nimbusds.jose.crypto;

import java.util.Collections;
import java.util.LinkedHashSet;
import java.security.GeneralSecurityException;
import java.security.Provider;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.AlgorithmParameterSpec;
import java.security.KeyPairGenerator;
import java.security.spec.ECParameterSpec;
import java.security.KeyPair;
import java.util.Arrays;
import java.security.PrivateKey;
import com.nimbusds.jose.crypto.impl.ECDH;
import com.nimbusds.jose.jwk.JWK;
import java.security.interfaces.ECPrivateKey;
import com.nimbusds.jose.crypto.impl.AAD;
import com.nimbusds.jose.JWECryptoParts;
import com.nimbusds.jose.JWEHeader;
import com.nimbusds.jose.jwk.ECKey;
import com.nimbusds.jose.JOSEException;
import javax.crypto.SecretKey;
import java.security.interfaces.ECPublicKey;
import com.nimbusds.jose.jwk.Curve;
import java.util.Set;
import com.nimbusds.jose.shaded.jcip.ThreadSafe;
import com.nimbusds.jose.JWEEncrypter;
import com.nimbusds.jose.crypto.impl.ECDHCryptoProvider;

@ThreadSafe
public class ECDHEncrypter extends ECDHCryptoProvider implements JWEEncrypter
{
    public static final Set<Curve> SUPPORTED_ELLIPTIC_CURVES;
    private final ECPublicKey publicKey;
    
    public ECDHEncrypter(final ECPublicKey publicKey) throws JOSEException {
        this(publicKey, null);
    }
    
    public ECDHEncrypter(final ECKey ecJWK) throws JOSEException {
        this(ecJWK.toECPublicKey(), null);
    }
    
    public ECDHEncrypter(final ECPublicKey publicKey, final SecretKey contentEncryptionKey) throws JOSEException {
        super(Curve.forECParameterSpec(publicKey.getParams()), contentEncryptionKey);
        this.publicKey = publicKey;
    }
    
    public ECPublicKey getPublicKey() {
        return this.publicKey;
    }
    
    @Override
    public Set<Curve> supportedEllipticCurves() {
        return ECDHEncrypter.SUPPORTED_ELLIPTIC_CURVES;
    }
    
    @Deprecated
    public JWECryptoParts encrypt(final JWEHeader header, final byte[] clearText) throws JOSEException {
        return this.encrypt(header, clearText, AAD.compute(header));
    }
    
    @Override
    public JWECryptoParts encrypt(final JWEHeader header, final byte[] clearText, final byte[] aad) throws JOSEException {
        final KeyPair ephemeralKeyPair = this.generateEphemeralKeyPair(this.publicKey.getParams());
        final ECPublicKey ephemeralPublicKey = (ECPublicKey)ephemeralKeyPair.getPublic();
        final ECPrivateKey ephemeralPrivateKey = (ECPrivateKey)ephemeralKeyPair.getPrivate();
        final JWEHeader updatedHeader = new JWEHeader.Builder(header).ephemeralPublicKey(new ECKey.Builder(this.getCurve(), ephemeralPublicKey).build()).build();
        final SecretKey Z = ECDH.deriveSharedSecret(this.publicKey, ephemeralPrivateKey, this.getJCAContext().getKeyEncryptionProvider());
        final byte[] updatedAAD = Arrays.equals(AAD.compute(header), aad) ? AAD.compute(updatedHeader) : aad;
        return this.encryptWithZ(updatedHeader, Z, clearText, updatedAAD);
    }
    
    private KeyPair generateEphemeralKeyPair(final ECParameterSpec ecParameterSpec) throws JOSEException {
        final Provider keProvider = this.getJCAContext().getKeyEncryptionProvider();
        try {
            KeyPairGenerator generator;
            if (keProvider != null) {
                generator = KeyPairGenerator.getInstance("EC", keProvider);
            }
            else {
                generator = KeyPairGenerator.getInstance("EC");
            }
            generator.initialize(ecParameterSpec);
            return generator.generateKeyPair();
        }
        catch (final NoSuchAlgorithmException | InvalidAlgorithmParameterException e) {
            throw new JOSEException("Couldn't generate ephemeral EC key pair: " + e.getMessage(), e);
        }
    }
    
    static {
        final Set<Curve> curves = new LinkedHashSet<Curve>();
        curves.add(Curve.P_256);
        curves.add(Curve.P_384);
        curves.add(Curve.P_521);
        SUPPORTED_ELLIPTIC_CURVES = Collections.unmodifiableSet((Set<? extends Curve>)curves);
    }
}
