/*
 * Copyright 2012-2017 Brian Campbell
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.jose4j.jca;

import org.hamcrest.CoreMatchers;
import org.jose4j.jwa.AlgorithmConstraints;
import org.jose4j.jwa.AlgorithmConstraints.ConstraintType;
import org.jose4j.jwa.JceProviderTestSupport;
import org.jose4j.jwe.ContentEncryptionAlgorithmIdentifiers;
import org.jose4j.jwe.JsonWebEncryption;
import org.jose4j.jwe.KeyManagementAlgorithmIdentifiers;
import org.jose4j.jws.AlgorithmIdentifiers;
import org.jose4j.jws.JsonWebSignature;
import org.jose4j.jwx.JsonWebStructure;
import org.jose4j.keys.AesKey;
import org.jose4j.keys.ExampleEcKeysFromJws;
import org.jose4j.keys.ExampleRsaJwksFromJwe;
import org.jose4j.keys.HmacKey;
import org.jose4j.lang.JoseException;
import org.junit.Assert;
import org.junit.Test;

import java.math.BigInteger;
import java.security.interfaces.RSAPrivateKey;

/**
 *
 */
public class ProviderContextTest
{
    public static final String NO_SUCH_PROVIDER = "-_NO__SUCH__PROVIDER_-";

    public static final ProviderContext EMPTY_CONTEXT = new ProviderContext();

    @Test
    public void testGeneralDefaulting()
    {
        ProviderContext pc = new ProviderContext();
        Assert.assertNull(pc.getSecureRandom());

        String generalProvider = "some-provider";
        String specificProvider = "some-other-provider";

        for (ProviderContext.Context pcc : new ProviderContext.Context[] {pc.getGeneralProviderContext(), pc.getSuppliedKeyProviderContext()})
        {
            Assert.assertNull(pcc.getGeneralProvider());

            Assert.assertNull(pcc.getCipherProvider());
            Assert.assertNull(pcc.getKeyAgreementProvider());
            Assert.assertNull(pcc.getKeyFactoryProvider());
            Assert.assertNull(pcc.getKeyPairGeneratorProvider());
            Assert.assertNull(pcc.getMacProvider());
            Assert.assertNull(pcc.getMessageDigestProvider());
            Assert.assertNull(pcc.getSignatureProvider());

            pcc.setGeneralProvider(generalProvider);
            Assert.assertThat(pcc.getCipherProvider(), CoreMatchers.equalTo(generalProvider));
            pcc.setCipherProvider(specificProvider);
            Assert.assertThat(pcc.getCipherProvider(), CoreMatchers.equalTo(specificProvider));

            pcc.setGeneralProvider(generalProvider);
            Assert.assertThat(pcc.getKeyAgreementProvider(), CoreMatchers.equalTo(generalProvider));
            pcc.setKeyAgreementProvider(specificProvider);
            Assert.assertThat(pcc.getKeyAgreementProvider(), CoreMatchers.equalTo(specificProvider));

            pcc.setGeneralProvider(generalProvider);
            Assert.assertThat(pcc.getKeyFactoryProvider(), CoreMatchers.equalTo(generalProvider));
            pcc.setKeyFactoryProvider(specificProvider);
            Assert.assertThat(pcc.getKeyFactoryProvider(), CoreMatchers.equalTo(specificProvider));

            pcc.setGeneralProvider(generalProvider);
            Assert.assertThat(pcc.getKeyPairGeneratorProvider(), CoreMatchers.equalTo(generalProvider));
            pcc.setKeyPairGeneratorProvider(specificProvider);
            Assert.assertThat(pcc.getKeyPairGeneratorProvider(), CoreMatchers.equalTo(specificProvider));

            pcc.setGeneralProvider(generalProvider);
            Assert.assertThat(pcc.getMacProvider(), CoreMatchers.equalTo(generalProvider));
            pcc.setMacProvider(specificProvider);
            Assert.assertThat(pcc.getMacProvider(), CoreMatchers.equalTo(specificProvider));

            pcc.setGeneralProvider(generalProvider);
            Assert.assertThat(pcc.getMessageDigestProvider(), CoreMatchers.equalTo(generalProvider));
            pcc.setMessageDigestProvider(specificProvider);
            Assert.assertThat(pcc.getMessageDigestProvider(), CoreMatchers.equalTo(specificProvider));

            pcc.setGeneralProvider(generalProvider);
            Assert.assertThat(pcc.getSignatureProvider(), CoreMatchers.equalTo(generalProvider));
            pcc.setSignatureProvider(specificProvider);
            Assert.assertThat(pcc.getSignatureProvider(), CoreMatchers.equalTo(specificProvider));
        }
    }

    @Test
    public void kindaLameTestForNonexistentProviderJwsRsa() throws JoseException
    {
        JsonWebSignature jws = new JsonWebSignature();
        jws.setPayload("meh");
        jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256);
        jws.setKey(ExampleRsaJwksFromJwe.APPENDIX_A_1.getPrivateKey());
        ProviderContext providerCtx = new ProviderContext();
        providerCtx.getSuppliedKeyProviderContext().setSignatureProvider(NO_SUCH_PROVIDER);
        jws.setProviderContext(providerCtx);
        expectNoProviderProduce(jws);

        jws.setProviderContext(EMPTY_CONTEXT);
        String jwsCompactSerialization = jws.getCompactSerialization();

        jws = new JsonWebSignature();
        jws.setCompactSerialization(jwsCompactSerialization);
        jws.setKey(ExampleRsaJwksFromJwe.APPENDIX_A_1.getPublicKey());
        jws.setProviderContext(providerCtx);
        expectNoProviderConsume(jws);

        jws.setProviderContext(EMPTY_CONTEXT);
        Assert.assertTrue(jws.verifySignature());
    }


    @Test
    public void kindaLameTestForNonexistentProviderJwsEc() throws JoseException
    {
        JsonWebSignature jws = new JsonWebSignature();
        jws.setPayload("whatever");
        jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.ECDSA_USING_P256_CURVE_AND_SHA256);
        jws.setKey(ExampleEcKeysFromJws.PRIVATE_256);
        ProviderContext providerCtx = new ProviderContext();
        providerCtx.getSuppliedKeyProviderContext().setSignatureProvider(NO_SUCH_PROVIDER);
        jws.setProviderContext(providerCtx);
        expectNoProviderProduce(jws);

        jws.setProviderContext(EMPTY_CONTEXT);
        String jwsCompactSerialization = jws.getCompactSerialization();

        jws = new JsonWebSignature();
        jws.setAlgorithmConstraints(new AlgorithmConstraints(ConstraintType.PERMIT, AlgorithmIdentifiers.ECDSA_USING_P256_CURVE_AND_SHA256));
        jws.setCompactSerialization(jwsCompactSerialization);
        jws.setKey(ExampleEcKeysFromJws.PUBLIC_256);
        jws.setProviderContext(providerCtx);
        expectNoProviderConsume(jws);

        jws.setProviderContext(EMPTY_CONTEXT);
        Assert.assertTrue(jws.verifySignature());
    }

    @Test
    public void kindaLameTestForNonexistentProviderJwsHmac() throws JoseException
    {
        JsonWebSignature jws = new JsonWebSignature();
        jws.setPayload("okay");
        jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.HMAC_SHA256);
        HmacKey key = new HmacKey(new byte[32]);
        jws.setKey(key);
        ProviderContext providerCtx = new ProviderContext();
        providerCtx.getSuppliedKeyProviderContext().setMacProvider(NO_SUCH_PROVIDER);
        jws.setProviderContext(providerCtx);
        expectNoProviderProduce(jws);

        jws.setProviderContext(EMPTY_CONTEXT);
        String jwsCompactSerialization = jws.getCompactSerialization();

        jws = new JsonWebSignature();
        jws.setAlgorithmConstraints(new AlgorithmConstraints(ConstraintType.PERMIT, AlgorithmIdentifiers.HMAC_SHA256));
        jws.setCompactSerialization(jwsCompactSerialization);
        jws.setKey(key);
        jws.setProviderContext(providerCtx);
        expectNoProviderConsume(jws);

        jws.setProviderContext(EMPTY_CONTEXT);
        Assert.assertTrue(jws.verifySignature());
    }

    void expectNoProviderProduce(JsonWebStructure jwx)
    {
        try
        {
            String compactSerialization = jwx.getCompactSerialization();
            Assert.fail("Shouldn't have gotten compact serialization " + compactSerialization);
        }
        catch (JoseException e)
        {
            Assert.assertThat(e.getMessage(), CoreMatchers.containsString(NO_SUCH_PROVIDER));
        }
    }

    void expectNoProviderConsume(JsonWebStructure jwx)
    {
        try
        {
            String inside = jwx.getPayload();
            Assert.fail("Shouldn't have gotten payload " + inside);
        }
        catch (JoseException e)
        {
            Assert.assertThat(e.getMessage(), CoreMatchers.containsString(NO_SUCH_PROVIDER));
        }
    }

    @Test
    public void kindaLameTestForNonexistentProviderJweRsaOaepAnd15() throws JoseException
    {
        for (String alg : new String[] {KeyManagementAlgorithmIdentifiers.RSA_OAEP, KeyManagementAlgorithmIdentifiers.RSA1_5})
        {
            JsonWebEncryption jwe = new JsonWebEncryption();
            String payload = "meh";
            jwe.setPayload(payload);
            jwe.setAlgorithmHeaderValue(alg);
            jwe.setAlgorithmConstraints(AlgorithmConstraints.NO_CONSTRAINTS);
            jwe.setKey(ExampleRsaJwksFromJwe.APPENDIX_A_1.getPublicKey());
            jwe.setEncryptionMethodHeaderParameter(ContentEncryptionAlgorithmIdentifiers.AES_128_CBC_HMAC_SHA_256);
            ProviderContext providerCtx = new ProviderContext();
            providerCtx.getSuppliedKeyProviderContext().setCipherProvider(NO_SUCH_PROVIDER);
            jwe.setProviderContext(providerCtx);
            expectNoProviderProduce(jwe);

            jwe.setProviderContext(EMPTY_CONTEXT);
            String jwsCompactSerialization = jwe.getCompactSerialization();

            jwe = new JsonWebEncryption();
            jwe.setAlgorithmConstraints(AlgorithmConstraints.NO_CONSTRAINTS);
            jwe.setCompactSerialization(jwsCompactSerialization);
            jwe.setKey(ExampleRsaJwksFromJwe.APPENDIX_A_1.getPrivateKey());
            jwe.setProviderContext(providerCtx);
            expectNoProviderConsume(jwe);

            jwe.setProviderContext(EMPTY_CONTEXT);
            Assert.assertThat(jwe.getPayload(), CoreMatchers.equalTo(payload));
        }
    }

    @Test
    public void kindaLameTestForNonexistentProviderJweDirAesMac() throws JoseException
    {
        final String mac = "MAC";
        final String cipher = "Cipher";
        for (String which : new String[] {mac, cipher})
        {
            JsonWebEncryption jwe = new JsonWebEncryption();
            String payload = "meh";
            jwe.setPayload(payload);
            jwe.setAlgorithmHeaderValue(KeyManagementAlgorithmIdentifiers.DIRECT);
            AesKey key = new AesKey(new byte[32]);
            jwe.setKey(key);
            jwe.setEncryptionMethodHeaderParameter(ContentEncryptionAlgorithmIdentifiers.AES_128_CBC_HMAC_SHA_256);
            ProviderContext providerCtx = new ProviderContext();
            switch (which)
            {
                case cipher:
                    providerCtx.getSuppliedKeyProviderContext().setCipherProvider(NO_SUCH_PROVIDER);
                    break;
                case mac:
                    providerCtx.getSuppliedKeyProviderContext().setMacProvider(NO_SUCH_PROVIDER);
                    break;
                default:
                    Assert.fail("shouldn't get here");
            }
            jwe.setProviderContext(providerCtx);
            expectNoProviderProduce(jwe);

            jwe = new JsonWebEncryption();
            jwe.setPayload(payload);
            jwe.setAlgorithmHeaderValue(KeyManagementAlgorithmIdentifiers.DIRECT);
            jwe.setKey(key);
            jwe.setEncryptionMethodHeaderParameter(ContentEncryptionAlgorithmIdentifiers.AES_128_CBC_HMAC_SHA_256);
            jwe.setProviderContext(EMPTY_CONTEXT);
            String jwsCompactSerialization = jwe.getCompactSerialization();

            jwe = new JsonWebEncryption();
            jwe.setCompactSerialization(jwsCompactSerialization);
            jwe.setKey(key);
            jwe.setProviderContext(providerCtx);
            expectNoProviderConsume(jwe);

            jwe.setProviderContext(EMPTY_CONTEXT);
            Assert.assertThat(jwe.getPayload(), CoreMatchers.equalTo(payload));
        }
    }

    @Test
    public void kindaLameTestForNonexistentProviderJweAesCbcHmac() throws JoseException
    {
        JsonWebEncryption jwe = new JsonWebEncryption();
        String payload = "meh";
        jwe.setPayload(payload);
        jwe.setAlgorithmHeaderValue(KeyManagementAlgorithmIdentifiers.DIRECT);
        AesKey key = new AesKey(new byte[32]);
        jwe.setKey(key);
        jwe.setEncryptionMethodHeaderParameter(ContentEncryptionAlgorithmIdentifiers.AES_128_CBC_HMAC_SHA_256);
        ProviderContext providerCtx = new ProviderContext();
        providerCtx.getSuppliedKeyProviderContext().setCipherProvider(NO_SUCH_PROVIDER);
        jwe.setProviderContext(providerCtx);
        expectNoProviderProduce(jwe);

        jwe = new JsonWebEncryption();
        jwe.setPayload(payload);
        jwe.setAlgorithmHeaderValue(KeyManagementAlgorithmIdentifiers.DIRECT);
        jwe.setKey(key);
        jwe.setEncryptionMethodHeaderParameter(ContentEncryptionAlgorithmIdentifiers.AES_128_CBC_HMAC_SHA_256);
        jwe.setProviderContext(EMPTY_CONTEXT);
        String jwsCompactSerialization = jwe.getCompactSerialization();

        jwe = new JsonWebEncryption();
        jwe.setCompactSerialization(jwsCompactSerialization);
        jwe.setKey(key);
        jwe.setProviderContext(providerCtx);
        expectNoProviderConsume(jwe);

        jwe.setProviderContext(EMPTY_CONTEXT);
        Assert.assertThat(jwe.getPayload(), CoreMatchers.equalTo(payload));
    }

    @Test
    public void kindaLameTestForNonexistentProviderJweAeskws() throws Exception
    {
        JceProviderTestSupport support = new JceProviderTestSupport();
        support.setKeyManagementAlgsNeeded(KeyManagementAlgorithmIdentifiers.A128GCMKW);
        support.runWithBouncyCastleProviderIfNeeded(new JceProviderTestSupport.RunnableTest()
        {
            @Override
            public void runTest() throws Exception
            {
                for (String alg : new String[] {KeyManagementAlgorithmIdentifiers.A128KW, KeyManagementAlgorithmIdentifiers.A128GCMKW})
                {
                    JsonWebEncryption jwe = new JsonWebEncryption();
                    String payload = "meh";
                    jwe.setPayload(payload);
                    jwe.setAlgorithmHeaderValue(alg);
                    AesKey key = new AesKey(new byte[16]);
                    jwe.setKey(key);
                    jwe.setEncryptionMethodHeaderParameter(ContentEncryptionAlgorithmIdentifiers.AES_128_GCM);
                    ProviderContext providerCtx = new ProviderContext();
                    providerCtx.getSuppliedKeyProviderContext().setCipherProvider(NO_SUCH_PROVIDER);
                    jwe.setProviderContext(providerCtx);
                    expectNoProviderProduce(jwe);

                    jwe.setProviderContext(EMPTY_CONTEXT);
                    String jwsCompactSerialization = jwe.getCompactSerialization();

                    jwe = new JsonWebEncryption();
                    jwe.setCompactSerialization(jwsCompactSerialization);
                    jwe.setKey(key);
                    jwe.setProviderContext(providerCtx);
                    expectNoProviderConsume(jwe);

                    jwe.setProviderContext(EMPTY_CONTEXT);
                    Assert.assertThat(jwe.getPayload(), CoreMatchers.equalTo(payload));
                }
            }
        });
    }

    @Test
    public void kindaLameTestForNonexistentProviderJweEc() throws JoseException
    {
        String[] algs = {KeyManagementAlgorithmIdentifiers.ECDH_ES,
                KeyManagementAlgorithmIdentifiers.ECDH_ES_A128KW,
                KeyManagementAlgorithmIdentifiers.ECDH_ES_A256KW,
                KeyManagementAlgorithmIdentifiers.ECDH_ES_A192KW};
        final String keyFactory = "KF";
        final String keyAgreement = "KA";
        final String keyPairGenerator = "KPG";
        for (String whichKind : new String []{keyFactory, keyAgreement, keyPairGenerator})
        {
            for (String alg : algs)
            {
                JsonWebEncryption jwe = new JsonWebEncryption();
                String payload = "meh";
                jwe.setPayload(payload);
                jwe.setAlgorithmHeaderValue(alg);
                jwe.setKey(ExampleEcKeysFromJws.PUBLIC_256);
                jwe.setEncryptionMethodHeaderParameter(ContentEncryptionAlgorithmIdentifiers.AES_128_CBC_HMAC_SHA_256);
                ProviderContext providerCtx = new ProviderContext();
                switch (whichKind)
                {
                    case keyAgreement:
                        providerCtx.getSuppliedKeyProviderContext().setKeyAgreementProvider(NO_SUCH_PROVIDER);
                        break;
                    case keyFactory:
                        providerCtx.getGeneralProviderContext().setKeyFactoryProvider(NO_SUCH_PROVIDER);
                        break;
                    case keyPairGenerator:
                        providerCtx.getGeneralProviderContext().setKeyPairGeneratorProvider(NO_SUCH_PROVIDER);
                        break;
                     default:
                         Assert.fail("shouldn't get here");
                }

                jwe.setProviderContext(providerCtx);
                if (!whichKind.equals(keyFactory)) // keyfactory is only used on consuming
                {
                    expectNoProviderProduce(jwe);
                }

                jwe.setProviderContext(EMPTY_CONTEXT);
                String jwsCompactSerialization = jwe.getCompactSerialization();

                jwe = new JsonWebEncryption();
                jwe.setCompactSerialization(jwsCompactSerialization);
                jwe.setKey(ExampleEcKeysFromJws.PRIVATE_256);
                jwe.setProviderContext(providerCtx);
                if (!whichKind.equals(keyPairGenerator))
                {
                    expectNoProviderConsume(jwe);
                }

                jwe.setProviderContext(EMPTY_CONTEXT);
                Assert.assertThat(jwe.getPayload(), CoreMatchers.equalTo(payload));
            }
        }
    }

    @Test
    public void kindaLameTestForSelectingProviderJwsRsaWithBC() throws Exception
    {
        JceProviderTestSupport support = new JceProviderTestSupport();
        support.setUseBouncyCastleRegardlessOfAlgs(true);
        support.setPutBouncyCastleFirst(false);
        support.runWithBouncyCastleProviderIfNeeded(new JceProviderTestSupport.RunnableTest()
        {
            @Override
            public void runTest() throws Exception
            {
                JsonWebSignature jws = new JsonWebSignature();
                jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256);
                jws.setPayload("sign this");

                RSAPrivateKey pk = new RSAPrivateKey()
                {
                    RSAPrivateKey delegateKey = (RSAPrivateKey) ExampleRsaJwksFromJwe.APPENDIX_A_1.getPrivateKey();

                    @Override
                    public String getAlgorithm()
                    {
                        return delegateKey.getAlgorithm();
                    }

                    @Override
                    public String getFormat()
                    {
                        return delegateKey.getFormat();
                    }

                    @Override
                    public byte[] getEncoded()
                    {
                        return delegateKey.getEncoded();
                    }

                    @Override
                    public BigInteger getPrivateExponent()
                    {
                        lookAtStackTraceForBC();
                        return delegateKey.getPrivateExponent();
                    }

                    @Override
                    public BigInteger getModulus()
                    {
                        return delegateKey.getModulus();
                    }

                    private void lookAtStackTraceForBC()
                    {
                        boolean bc = false;
                        for (StackTraceElement ste : new Exception().getStackTrace())
                        {
                            if (ste.getClassName().contains(".bouncycastle."))
                            {
                                bc = true;
                            }
                        }

                        if (!bc)
                        {
                            throw new IllegalStateException("Bouncy Castle not used!");
                        }
                    }
                };

                jws.setKey(pk);
                ProviderContext pc = new ProviderContext();
                pc.getSuppliedKeyProviderContext().setSignatureProvider("BC");
                jws.setProviderContext(pc);
                jws.getCompactSerialization();
            }
        });
    }

    @Test
    public void kindaLameTestForSelectingProviderForContentEncGcm() throws Exception
    {
        JceProviderTestSupport support = new JceProviderTestSupport();
        support.setUseBouncyCastleRegardlessOfAlgs(true);
        support.setPutBouncyCastleFirst(false);
        support.runWithBouncyCastleProviderIfNeeded(new JceProviderTestSupport.RunnableTest()
        {
            @Override
            public void runTest() throws Exception
            {

                for (String enc : new String[] {ContentEncryptionAlgorithmIdentifiers.AES_128_GCM, ContentEncryptionAlgorithmIdentifiers.AES_128_GCM, ContentEncryptionAlgorithmIdentifiers.AES_256_GCM})
                {
                    JsonWebEncryption jwe = new JsonWebEncryption();
                    jwe.setAlgorithmHeaderValue(KeyManagementAlgorithmIdentifiers.A128KW);
                    jwe.setEncryptionMethodHeaderParameter(enc);
                    final String payloadIn = "encrypt me";
                    jwe.setPayload(payloadIn);

                    final AesKey key = new AesKey(new byte[]{1, 2, 1, 1, 0, 0, 1, 2, 9, 1, 0, 5, 1, 7, 1, 4});
                    jwe.setKey(key);
                    ProviderContext pc = new ProviderContext();
                    pc.getGeneralProviderContext().setCipherProvider(NO_SUCH_PROVIDER);
                    jwe.setProviderContext(pc);
                    expectNoProviderProduce(jwe);

                    jwe = new JsonWebEncryption();
                    jwe.setAlgorithmHeaderValue(KeyManagementAlgorithmIdentifiers.A128KW);
                    jwe.setEncryptionMethodHeaderParameter(enc);
                    jwe.setPayload(payloadIn);
                    jwe.setKey(key);
                    final String compactSerialization = jwe.getCompactSerialization();

                    jwe = new JsonWebEncryption();
                    jwe.setCompactSerialization(compactSerialization);
                    jwe.setKey(key);
                    Assert.assertThat(jwe.getPayload(), CoreMatchers.equalTo(payloadIn));

                    jwe = new JsonWebEncryption();
                    jwe.setCompactSerialization(compactSerialization);
                    jwe.setKey(key);
                    jwe.setProviderContext(pc);
                    expectNoProviderConsume(jwe);
                }
            }
        });
    }

    @Test
    public void kindaLameTestForSelectingProviderForContentEncCbcHmac() throws Exception
    {
        for (boolean doMac : new boolean[] {true, false})
        {
            for (String enc : new String[] {ContentEncryptionAlgorithmIdentifiers.AES_128_CBC_HMAC_SHA_256, ContentEncryptionAlgorithmIdentifiers.AES_192_CBC_HMAC_SHA_384, ContentEncryptionAlgorithmIdentifiers.AES_256_CBC_HMAC_SHA_512})
            {
                JsonWebEncryption jwe = new JsonWebEncryption();
                jwe.setAlgorithmHeaderValue(KeyManagementAlgorithmIdentifiers.A128KW);
                jwe.setEncryptionMethodHeaderParameter(enc);
                final String payloadIn = "encrypt me";
                jwe.setPayload(payloadIn);

                final AesKey key = new AesKey(new byte[]{1, 2, 1, 1, 0, 0, 1, 2, 9, 1, 0, 5, 1, 7, 1, 4});
                jwe.setKey(key);
                ProviderContext pc = new ProviderContext();
                final ProviderContext.Context providerContext = pc.getGeneralProviderContext();
                if (doMac)
                {
                    providerContext.setMacProvider(NO_SUCH_PROVIDER);
                }
                else
                {
                    providerContext.setCipherProvider(NO_SUCH_PROVIDER);
                }

                jwe.setProviderContext(pc);
                expectNoProviderProduce(jwe);

                jwe = new JsonWebEncryption();
                jwe.setAlgorithmHeaderValue(KeyManagementAlgorithmIdentifiers.A128KW);
                jwe.setEncryptionMethodHeaderParameter(enc);
                jwe.setPayload(payloadIn);
                jwe.setKey(key);
                final String compactSerialization = jwe.getCompactSerialization();

                jwe = new JsonWebEncryption();
                jwe.setCompactSerialization(compactSerialization);
                jwe.setKey(key);
                Assert.assertThat(jwe.getPayload(), CoreMatchers.equalTo(payloadIn));

                jwe = new JsonWebEncryption();
                jwe.setCompactSerialization(compactSerialization);
                jwe.setKey(key);
                jwe.setProviderContext(pc);
                expectNoProviderConsume(jwe);
            }
        }
    }

}
