class Crypto {

    public static PublicKey extractPublicKey(PrivateKey privateKey) throws CryptoException {

        // we only support RSA and ECDSA private keys

        PublicKey publicKey;
        switch (privateKey.getAlgorithm()) {
            case RSA:
                try {
                    KeyFactory kf = KeyFactory.getInstance(getRSAAlgo(), getProvider());
                    RSAPrivateCrtKey rsaCrtKey = (RSAPrivateCrtKey) privateKey;
                    RSAPublicKeySpec keySpec = new RSAPublicKeySpec(rsaCrtKey.getModulus(),
                            rsaCrtKey.getPublicExponent());
                    publicKey = kf.generatePublic(keySpec);
                } catch (NoSuchProviderException ex) {
                    LOG.error("extractPublicKey: RSA - Caught NoSuchProviderException exception: " + ex.getMessage());
                    throw new CryptoException(ex);
                } catch (NoSuchAlgorithmException ex) {
                    LOG.error("extractPublicKey: RSA - Caught NoSuchAlgorithmException exception: " + ex.getMessage());
                    throw new CryptoException(ex);
                    ///CLOVER:OFF
                } catch (InvalidKeySpecException ex) {
                    LOG.error("extractPublicKey: RSA - Caught InvalidKeySpecException exception: " + ex.getMessage());
                    throw new CryptoException(ex);
                }
                ///CLOVER:ON
                break;

            case ECDSA:
                try {
                    KeyFactory kf = KeyFactory.getInstance(getECDSAAlgo(), getProvider());
                    BCECPrivateKey ecPrivKey = (BCECPrivateKey) privateKey;
                    ECMultiplier ecMultiplier = new FixedPointCombMultiplier();
                    ECParameterSpec ecParamSpec = ecPrivKey.getParameters();
                    ECPoint ecPointQ = ecMultiplier.multiply(ecParamSpec.getG(), ecPrivKey.getD());
                    ECPublicKeySpec keySpec = new ECPublicKeySpec(ecPointQ, ecParamSpec);
                    publicKey = kf.generatePublic(keySpec);
                } catch (NoSuchProviderException ex) {
                    LOG.error("extractPublicKey: ECDSA - Caught NoSuchProviderException exception: " + ex.getMessage());
                    throw new CryptoException(ex);
                } catch (NoSuchAlgorithmException ex) {
                    LOG.error("extractPublicKey: ECDSA - Caught NoSuchAlgorithmException exception: " + ex.getMessage());
                    throw new CryptoException(ex);
                    ///CLOVER:OFF
                } catch (InvalidKeySpecException ex) {
                    LOG.error("extractPublicKey: ECDSA - Caught InvalidKeySpecException exception: " + ex.getMessage());
                    throw new CryptoException(ex);
                }
                ///CLOVER:ON
                break;

            default:
                String msg = "Unsupported Key Algorithm: " + privateKey.getAlgorithm();
                LOG.error("extractPublicKey: " + msg);
                throw new CryptoException(msg);
        }
        return publicKey;
    }

}