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

package com.nimbusds.jose.crypto;

import java.security.GeneralSecurityException;
import java.security.InvalidKeyException;
import com.nimbusds.jose.ActionRequiredForJWSCompletionException;
import java.security.SignatureException;
import java.security.Signature;
import com.nimbusds.jose.CompletableJWSObjectSigning;
import com.nimbusds.jose.crypto.opts.UserAuthenticationRequired;
import com.nimbusds.jose.JWSAlgorithm;
import java.util.Collection;
import com.nimbusds.jose.crypto.impl.AlgorithmSupportMessage;
import com.nimbusds.jose.util.Base64URL;
import com.nimbusds.jose.JWSHeader;
import com.nimbusds.jose.jwk.Curve;
import java.security.interfaces.ECKey;
import com.nimbusds.jose.crypto.impl.ECDSA;
import com.nimbusds.jose.JOSEException;
import java.util.Collections;
import java.security.interfaces.ECPrivateKey;
import com.nimbusds.jose.JWSSignerOption;
import java.util.Set;
import java.security.PrivateKey;
import com.nimbusds.jose.shaded.jcip.ThreadSafe;
import com.nimbusds.jose.JWSSigner;
import com.nimbusds.jose.crypto.impl.ECDSAProvider;

@ThreadSafe
public class ECDSASigner extends ECDSAProvider implements JWSSigner
{
    private final PrivateKey privateKey;
    private final Set<JWSSignerOption> opts;
    
    public ECDSASigner(final ECPrivateKey privateKey) throws JOSEException {
        this(privateKey, Collections.emptySet());
    }
    
    public ECDSASigner(final ECPrivateKey privateKey, final Set<JWSSignerOption> opts) throws JOSEException {
        super(ECDSA.resolveAlgorithm(privateKey));
        this.privateKey = privateKey;
        this.opts = ((opts != null) ? opts : Collections.emptySet());
    }
    
    public ECDSASigner(final PrivateKey privateKey, final Curve curve) throws JOSEException {
        this(privateKey, curve, Collections.emptySet());
    }
    
    public ECDSASigner(final PrivateKey privateKey, final Curve curve, final Set<JWSSignerOption> opts) throws JOSEException {
        super(ECDSA.resolveAlgorithm(curve));
        if (!"EC".equalsIgnoreCase(privateKey.getAlgorithm())) {
            throw new IllegalArgumentException("The private key algorithm must be EC");
        }
        this.privateKey = privateKey;
        this.opts = ((opts != null) ? opts : Collections.emptySet());
    }
    
    public ECDSASigner(final com.nimbusds.jose.jwk.ECKey ecJWK) throws JOSEException {
        this(ecJWK, null);
    }
    
    public ECDSASigner(final com.nimbusds.jose.jwk.ECKey ecJWK, final Set<JWSSignerOption> opts) throws JOSEException {
        super(ECDSA.resolveAlgorithm(ecJWK.getCurve()));
        if (!ecJWK.isPrivate()) {
            throw new JOSEException("The EC JWK doesn't contain a private part");
        }
        this.privateKey = ecJWK.toPrivateKey();
        this.opts = ((opts != null) ? opts : Collections.emptySet());
    }
    
    public PrivateKey getPrivateKey() {
        return this.privateKey;
    }
    
    @Override
    public Base64URL sign(final JWSHeader header, final byte[] signingInput) throws JOSEException {
        final JWSAlgorithm alg = header.getAlgorithm();
        if (!this.supportedJWSAlgorithms().contains(alg)) {
            throw new JOSEException(AlgorithmSupportMessage.unsupportedJWSAlgorithm(alg, this.supportedJWSAlgorithms()));
        }
        byte[] jcaSignature;
        try {
            final Signature dsa = ECDSA.getSignerAndVerifier(alg, this.getJCAContext().getProvider());
            dsa.initSign(this.privateKey, this.getJCAContext().getSecureRandom());
            if (this.opts.contains(UserAuthenticationRequired.getInstance())) {
                throw new ActionRequiredForJWSCompletionException("Authenticate user to complete signing", UserAuthenticationRequired.getInstance(), new CompletableJWSObjectSigning() {
                    @Override
                    public Signature getInitializedSignature() {
                        return dsa;
                    }
                    
                    @Override
                    public Base64URL complete() throws JOSEException {
                        try {
                            dsa.update(signingInput);
                            final byte[] jcaSignature = dsa.sign();
                            final int rsByteArrayLength = ECDSA.getSignatureByteArrayLength(header.getAlgorithm());
                            final byte[] jwsSignature = ECDSA.transcodeSignatureToConcat(jcaSignature, rsByteArrayLength);
                            return Base64URL.encode(jwsSignature);
                        }
                        catch (final SignatureException e) {
                            throw new JOSEException(e.getMessage(), e);
                        }
                    }
                });
            }
            dsa.update(signingInput);
            jcaSignature = dsa.sign();
        }
        catch (final InvalidKeyException | SignatureException e) {
            throw new JOSEException(e.getMessage(), e);
        }
        final int rsByteArrayLength = ECDSA.getSignatureByteArrayLength(header.getAlgorithm());
        final byte[] jwsSignature = ECDSA.transcodeSignatureToConcat(jcaSignature, rsByteArrayLength);
        return Base64URL.encode(jwsSignature);
    }
}
