Java tutorial
/** * Copyright (c) 2013-2014 Netflix, Inc. All rights reserved. * * 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 com.netflix.msl.keyx; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.nio.charset.Charset; import java.security.NoSuchAlgorithmException; import java.security.Security; import java.util.Arrays; import java.util.Random; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import javax.xml.bind.DatatypeConverter; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.json.JSONException; import org.json.JSONObject; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; import com.netflix.msl.MslCryptoException; import com.netflix.msl.MslEncodingException; import com.netflix.msl.MslEntityAuthException; import com.netflix.msl.MslError; import com.netflix.msl.MslException; import com.netflix.msl.MslInternalException; import com.netflix.msl.MslKeyExchangeException; import com.netflix.msl.MslMasterTokenException; import com.netflix.msl.crypto.ICryptoContext; import com.netflix.msl.crypto.JcaAlgorithm; import com.netflix.msl.crypto.JsonWebEncryptionCryptoContext; import com.netflix.msl.crypto.JsonWebEncryptionCryptoContext.AesKwCryptoContext; import com.netflix.msl.crypto.JsonWebEncryptionCryptoContext.CekCryptoContext; import com.netflix.msl.crypto.JsonWebEncryptionCryptoContext.Encryption; import com.netflix.msl.crypto.JsonWebEncryptionCryptoContext.Format; import com.netflix.msl.crypto.JsonWebKey; import com.netflix.msl.crypto.JsonWebKey.Algorithm; import com.netflix.msl.crypto.JsonWebKey.Usage; import com.netflix.msl.entityauth.EntityAuthenticationData; import com.netflix.msl.entityauth.EntityAuthenticationFactory; import com.netflix.msl.entityauth.EntityAuthenticationScheme; import com.netflix.msl.entityauth.MockPresharedAuthenticationFactory; import com.netflix.msl.keyx.JsonWebEncryptionLadderExchange.Mechanism; import com.netflix.msl.keyx.JsonWebEncryptionLadderExchange.RequestData; import com.netflix.msl.keyx.JsonWebEncryptionLadderExchange.ResponseData; import com.netflix.msl.keyx.KeyExchangeFactory.KeyExchangeData; import com.netflix.msl.test.ExpectedMslException; import com.netflix.msl.tokens.MasterToken; import com.netflix.msl.util.AuthenticationUtils; import com.netflix.msl.util.JsonUtils; import com.netflix.msl.util.MockAuthenticationUtils; import com.netflix.msl.util.MockMslContext; import com.netflix.msl.util.MslTestUtils; /** * JSON Web Encryption ladder exchange unit tests. * * @author Wesley Miaw <wmiaw@netflix.com> */ @RunWith(Suite.class) @SuiteClasses({ JsonWebEncryptionLadderExchangeSuite.KeyExchangeFactoryTest.class, JsonWebEncryptionLadderExchangeSuite.RequestDataTest.class, JsonWebEncryptionLadderExchangeSuite.ResponseDataTest.class }) public class JsonWebEncryptionLadderExchangeSuite { /** Encoding charset. */ private static final Charset UTF_8 = Charset.forName("UTF-8"); /** JSON key key exchange scheme. */ private static final String KEY_SCHEME = "scheme"; /** JSON key key request data. */ private static final String KEY_KEYDATA = "keydata"; private static ICryptoContext PSK_CRYPTO_CONTEXT, WRAP_CRYPTO_CONTEXT; private static byte[] WRAP_JWK; private static byte[] WRAPDATA; private static final String PSK_IDENTITY = MockPresharedAuthenticationFactory.PSK_ESN; private static MasterToken PSK_MASTER_TOKEN; private static byte[] PSK_ENCRYPTION_JWK; private static byte[] PSK_HMAC_JWK; @BeforeClass public static synchronized void setup() throws MslEncodingException, MslCryptoException, NoSuchAlgorithmException, MslEntityAuthException { if (pskCtx == null) { Security.addProvider(new BouncyCastleProvider()); pskCtx = new MockMslContext(EntityAuthenticationScheme.PSK, false); // Create PSK wrapping crypto context. { final EntityAuthenticationData entityAuthData = pskCtx.getEntityAuthenticationData(null); final EntityAuthenticationFactory entityAuthFactory = pskCtx .getEntityAuthenticationFactory(entityAuthData.getScheme()); final ICryptoContext pskCryptoContext = entityAuthFactory.getCryptoContext(pskCtx, entityAuthData); final CekCryptoContext wrapCekCryptoContext = new AesKwCryptoContext(pskCryptoContext); PSK_CRYPTO_CONTEXT = new JsonWebEncryptionCryptoContext(pskCtx, wrapCekCryptoContext, Encryption.A128GCM, Format.JWE_JS); } // The wrap key is the new wrapping key wrapped by the specified // wrapping key (e.g. PSK or RSA) inside a JWK. Technically we // shouldn't know this but that's the only way to verify things. // // Create the new wrapping key and wrap crypto context. final byte[] wrappingKey = new byte[16]; pskCtx.getRandom().nextBytes(wrappingKey); final SecretKey wrapKey = new SecretKeySpec(wrappingKey, JcaAlgorithm.AESKW); final CekCryptoContext cekCryptoContext = new AesKwCryptoContext(wrapKey); WRAP_CRYPTO_CONTEXT = new JsonWebEncryptionCryptoContext(pskCtx, cekCryptoContext, Encryption.A128GCM, Format.JWE_JS); // // Wrap the new wrapping key using a PSK wrap crypto context. final JsonWebKey wrapJwk = new JsonWebKey(Usage.wrap, Algorithm.A128KW, false, null, wrapKey); WRAP_JWK = PSK_CRYPTO_CONTEXT.wrap(wrapJwk.toJSONString().getBytes(UTF_8)); // The wrap data is an AES-128 key wrapped by the primary MSL // context. Technically we shouldn't know this but that's the only // way to verify things. WRAPDATA = pskCtx.getMslCryptoContext().wrap(wrappingKey); final WrapCryptoContextRepository repository = new MockCryptoContextRepository(); final AuthenticationUtils authutils = new MockAuthenticationUtils(); final KeyExchangeFactory keyxFactory = new JsonWebEncryptionLadderExchange(repository, authutils); pskCtx.addKeyExchangeFactory(keyxFactory); PSK_MASTER_TOKEN = MslTestUtils.getMasterToken(pskCtx, 1, 1); final SecretKey pskEncryptionKey = PSK_MASTER_TOKEN.getEncryptionKey(); final JsonWebKey pskEncryptionJwk = new JsonWebKey(Usage.enc, Algorithm.A128CBC, false, null, pskEncryptionKey); PSK_ENCRYPTION_JWK = WRAP_CRYPTO_CONTEXT.wrap(pskEncryptionJwk.toJSONString().getBytes(UTF_8)); final SecretKey pskHmacKey = PSK_MASTER_TOKEN.getHmacKey(); final JsonWebKey pskHmacJwk = new JsonWebKey(Usage.sig, Algorithm.HS256, false, null, pskHmacKey); PSK_HMAC_JWK = WRAP_CRYPTO_CONTEXT.wrap(pskHmacJwk.toJSONString().getBytes(UTF_8)); } } @AfterClass public static synchronized void teardown() { // Teardown causes problems because the data is shared by the inner // classes, so don't do any cleanup. } /** PSK MSL context. */ private static MockMslContext pskCtx; /** Request data unit tests. */ public static class RequestDataTest { /** JSON key wrap key wrapping mechanism. */ private static final String KEY_MECHANISM = "mechanism"; /** JSON key public key. */ private static final String KEY_PUBLIC_KEY = "publickey"; /** JSON key wrap data. */ private static final String KEY_WRAPDATA = "wrapdata"; @Rule public ExpectedMslException thrown = ExpectedMslException.none(); @Test public void ctorsWrap() throws MslCryptoException, MslKeyExchangeException, MslEncodingException, JSONException { final RequestData req = new RequestData(Mechanism.WRAP, WRAPDATA); assertEquals(KeyExchangeScheme.JWE_LADDER, req.getKeyExchangeScheme()); assertEquals(Mechanism.WRAP, req.getMechanism()); assertArrayEquals(WRAPDATA, req.getWrapdata()); final JSONObject keydata = req.getKeydata(); assertNotNull(keydata); final RequestData joReq = new RequestData(keydata); assertEquals(req.getKeyExchangeScheme(), joReq.getKeyExchangeScheme()); assertEquals(req.getMechanism(), joReq.getMechanism()); assertArrayEquals(req.getWrapdata(), joReq.getWrapdata()); final JSONObject joKeydata = req.getKeydata(); assertNotNull(joKeydata); assertTrue(JsonUtils.equals(keydata, joKeydata)); } @Test public void jsonWrap() throws JSONException { final RequestData req = new RequestData(Mechanism.WRAP, WRAPDATA); final JSONObject jo = new JSONObject(req.toJSONString()); assertEquals(KeyExchangeScheme.JWE_LADDER.name(), jo.getString(KEY_SCHEME)); final JSONObject keydata = jo.getJSONObject(KEY_KEYDATA); assertEquals(Mechanism.WRAP.name(), keydata.getString(KEY_MECHANISM)); assertFalse(keydata.has(KEY_PUBLIC_KEY)); assertArrayEquals(WRAPDATA, DatatypeConverter.parseBase64Binary(keydata.getString(KEY_WRAPDATA))); } @Test public void createWrap() throws JSONException, MslEncodingException, MslEntityAuthException, MslKeyExchangeException, MslCryptoException { final RequestData req = new RequestData(Mechanism.WRAP, WRAPDATA); final JSONObject jo = new JSONObject(req.toJSONString()); final KeyRequestData keyRequestData = KeyRequestData.create(pskCtx, jo); assertNotNull(keyRequestData); assertTrue(keyRequestData instanceof RequestData); final RequestData joReq = (RequestData) keyRequestData; assertEquals(req.getKeyExchangeScheme(), joReq.getKeyExchangeScheme()); assertEquals(req.getMechanism(), joReq.getMechanism()); assertArrayEquals(req.getWrapdata(), joReq.getWrapdata()); } @Test(expected = MslInternalException.class) public void ctorWrapNullWrapdata() { new RequestData(Mechanism.WRAP, null); } @Test public void ctorsPsk() throws MslCryptoException, MslKeyExchangeException, MslEncodingException, JSONException { final RequestData req = new RequestData(Mechanism.PSK, null); assertEquals(KeyExchangeScheme.JWE_LADDER, req.getKeyExchangeScheme()); assertEquals(Mechanism.PSK, req.getMechanism()); assertNull(req.getWrapdata()); final JSONObject keydata = req.getKeydata(); assertNotNull(keydata); final RequestData joReq = new RequestData(keydata); assertEquals(req.getKeyExchangeScheme(), joReq.getKeyExchangeScheme()); assertEquals(req.getMechanism(), joReq.getMechanism()); assertNull(joReq.getWrapdata()); final JSONObject joKeydata = req.getKeydata(); assertNotNull(joKeydata); assertTrue(JsonUtils.equals(keydata, joKeydata)); } @Test public void jsonPsk() throws JSONException { final RequestData req = new RequestData(Mechanism.PSK, null); final JSONObject jo = new JSONObject(req.toJSONString()); assertEquals(KeyExchangeScheme.JWE_LADDER.name(), jo.getString(KEY_SCHEME)); final JSONObject keydata = jo.getJSONObject(KEY_KEYDATA); assertEquals(Mechanism.PSK.name(), keydata.getString(KEY_MECHANISM)); assertFalse(keydata.has(KEY_PUBLIC_KEY)); assertFalse(keydata.has(KEY_WRAPDATA)); } @Test public void createPsk() throws MslEncodingException, MslEntityAuthException, MslKeyExchangeException, JSONException, MslCryptoException { final RequestData req = new RequestData(Mechanism.PSK, null); final JSONObject jo = new JSONObject(req.toJSONString()); final KeyRequestData keyRequestData = KeyRequestData.create(pskCtx, jo); assertNotNull(keyRequestData); assertTrue(keyRequestData instanceof RequestData); final RequestData joReq = (RequestData) keyRequestData; assertEquals(req.getKeyExchangeScheme(), joReq.getKeyExchangeScheme()); assertEquals(req.getMechanism(), joReq.getMechanism()); assertNull(joReq.getWrapdata()); } @Test public void missingMechanism() throws JSONException, MslCryptoException, MslKeyExchangeException, MslEncodingException { thrown.expect(MslEncodingException.class); thrown.expectMslError(MslError.JSON_PARSE_ERROR); final RequestData req = new RequestData(Mechanism.PSK, null); final JSONObject keydata = req.getKeydata(); assertNotNull(keydata.remove(KEY_MECHANISM)); new RequestData(keydata); } @Test public void invalidMechanism() throws MslCryptoException, MslKeyExchangeException, MslEncodingException, JSONException { thrown.expect(MslKeyExchangeException.class); thrown.expectMslError(MslError.UNIDENTIFIED_KEYX_MECHANISM); final RequestData req = new RequestData(Mechanism.PSK, null); final JSONObject keydata = req.getKeydata(); keydata.put(KEY_MECHANISM, "x"); new RequestData(keydata); } @Test public void wrapMissingWrapdata() throws MslCryptoException, MslKeyExchangeException, MslEncodingException, JSONException { thrown.expect(MslEncodingException.class); thrown.expectMslError(MslError.JSON_PARSE_ERROR); final RequestData req = new RequestData(Mechanism.WRAP, WRAPDATA); final JSONObject keydata = req.getKeydata(); assertNotNull(keydata.remove(KEY_WRAPDATA)); new RequestData(keydata); } @Test public void wrapInvalidWrapdata() throws MslCryptoException, MslKeyExchangeException, MslEncodingException, JSONException { thrown.expect(MslKeyExchangeException.class); thrown.expectMslError(MslError.KEYX_WRAPPING_KEY_MISSING); final RequestData req = new RequestData(Mechanism.WRAP, WRAPDATA); final JSONObject keydata = req.getKeydata(); keydata.put(KEY_WRAPDATA, "x"); new RequestData(keydata); } @Test public void equalsMechanism() throws MslCryptoException, MslKeyExchangeException, MslEncodingException, JSONException { final RequestData dataA = new RequestData(Mechanism.WRAP, WRAPDATA); final RequestData dataB = new RequestData(Mechanism.PSK, null); final RequestData dataA2 = new RequestData(dataA.getKeydata()); assertTrue(dataA.equals(dataA)); assertEquals(dataA.hashCode(), dataA.hashCode()); assertFalse(dataA.equals(dataB)); assertFalse(dataB.equals(dataA)); assertTrue(dataA.hashCode() != dataB.hashCode()); assertTrue(dataA.equals(dataA2)); assertTrue(dataA2.equals(dataA)); assertEquals(dataA.hashCode(), dataA2.hashCode()); } @Test public void equalsWrapdata() throws MslCryptoException, MslKeyExchangeException, MslEncodingException, JSONException { final byte[] wrapdataB = Arrays.copyOf(WRAPDATA, WRAPDATA.length); ++wrapdataB[0]; final RequestData dataA = new RequestData(Mechanism.WRAP, WRAPDATA); final RequestData dataB = new RequestData(Mechanism.WRAP, wrapdataB); final RequestData dataA2 = new RequestData(dataA.getKeydata()); assertTrue(dataA.equals(dataA)); assertEquals(dataA.hashCode(), dataA.hashCode()); assertFalse(dataA.equals(dataB)); assertFalse(dataB.equals(dataA)); assertTrue(dataA.hashCode() != dataB.hashCode()); assertTrue(dataA.equals(dataA2)); assertTrue(dataA2.equals(dataA)); assertEquals(dataA.hashCode(), dataA2.hashCode()); } } /** Response data unit tests. */ public static class ResponseDataTest { /** JSON key master token. */ private static final String KEY_MASTER_TOKEN = "mastertoken"; /** JSON key wrapping key. */ private static final String KEY_WRAP_KEY = "wrapkey"; /** JSON key wrapping key data. */ private static final String KEY_WRAPDATA = "wrapdata"; /** JSON key encrypted encryption key. */ private static final String KEY_ENCRYPTION_KEY = "encryptionkey"; /** JSON key encrypted HMAC key. */ private static final String KEY_HMAC_KEY = "hmackey"; @Rule public ExpectedMslException thrown = ExpectedMslException.none(); @Test public void ctors() throws JSONException, MslKeyExchangeException, MslEncodingException { final ResponseData resp = new ResponseData(PSK_MASTER_TOKEN, WRAP_JWK, WRAPDATA, PSK_ENCRYPTION_JWK, PSK_HMAC_JWK); assertArrayEquals(PSK_ENCRYPTION_JWK, resp.getEncryptionKey()); assertArrayEquals(PSK_HMAC_JWK, resp.getHmacKey()); assertEquals(KeyExchangeScheme.JWE_LADDER, resp.getKeyExchangeScheme()); assertEquals(PSK_MASTER_TOKEN, resp.getMasterToken()); assertArrayEquals(WRAPDATA, resp.getWrapdata()); assertArrayEquals(WRAP_JWK, resp.getWrapKey()); final JSONObject keydata = resp.getKeydata(); assertNotNull(keydata); final ResponseData joResp = new ResponseData(PSK_MASTER_TOKEN, keydata); assertArrayEquals(resp.getEncryptionKey(), joResp.getEncryptionKey()); assertArrayEquals(resp.getHmacKey(), joResp.getHmacKey()); assertEquals(resp.getKeyExchangeScheme(), joResp.getKeyExchangeScheme()); assertEquals(resp.getMasterToken(), joResp.getMasterToken()); assertArrayEquals(resp.getWrapdata(), joResp.getWrapdata()); assertArrayEquals(resp.getWrapKey(), joResp.getWrapKey()); final JSONObject joKeydata = joResp.getKeydata(); assertNotNull(joKeydata); assertTrue(JsonUtils.equals(keydata, joKeydata)); } @Test public void json() throws MslEncodingException, MslCryptoException, JSONException, MslException { final ResponseData resp = new ResponseData(PSK_MASTER_TOKEN, WRAP_JWK, WRAPDATA, PSK_ENCRYPTION_JWK, PSK_HMAC_JWK); final JSONObject jo = new JSONObject(resp.toJSONString()); assertEquals(KeyExchangeScheme.JWE_LADDER.name(), jo.getString(KEY_SCHEME)); final MasterToken masterToken = new MasterToken(pskCtx, jo.getJSONObject(KEY_MASTER_TOKEN)); assertEquals(PSK_MASTER_TOKEN, masterToken); final JSONObject keydata = jo.getJSONObject(KEY_KEYDATA); assertArrayEquals(PSK_ENCRYPTION_JWK, DatatypeConverter.parseBase64Binary(keydata.getString(KEY_ENCRYPTION_KEY))); assertArrayEquals(PSK_HMAC_JWK, DatatypeConverter.parseBase64Binary(keydata.getString(KEY_HMAC_KEY))); assertArrayEquals(WRAPDATA, DatatypeConverter.parseBase64Binary(keydata.getString(KEY_WRAPDATA))); assertArrayEquals(WRAP_JWK, DatatypeConverter.parseBase64Binary(keydata.getString(KEY_WRAP_KEY))); } @Test public void create() throws JSONException, MslEncodingException, MslCryptoException, MslKeyExchangeException, MslException { final ResponseData resp = new ResponseData(PSK_MASTER_TOKEN, WRAP_JWK, WRAPDATA, PSK_ENCRYPTION_JWK, PSK_HMAC_JWK); final JSONObject jo = new JSONObject(resp.toJSONString()); final KeyResponseData keyResponseData = KeyResponseData.create(pskCtx, jo); assertNotNull(keyResponseData); assertTrue(keyResponseData instanceof ResponseData); final ResponseData joResp = (ResponseData) keyResponseData; assertArrayEquals(resp.getEncryptionKey(), joResp.getEncryptionKey()); assertArrayEquals(resp.getHmacKey(), joResp.getHmacKey()); assertEquals(resp.getKeyExchangeScheme(), joResp.getKeyExchangeScheme()); assertEquals(resp.getMasterToken(), joResp.getMasterToken()); assertArrayEquals(resp.getWrapdata(), joResp.getWrapdata()); assertArrayEquals(resp.getWrapKey(), joResp.getWrapKey()); } @Test public void missingWrapKey() throws JSONException, MslKeyExchangeException, MslEncodingException { thrown.expect(MslEncodingException.class); thrown.expectMslError(MslError.JSON_PARSE_ERROR); final ResponseData resp = new ResponseData(PSK_MASTER_TOKEN, WRAP_JWK, WRAPDATA, PSK_ENCRYPTION_JWK, PSK_HMAC_JWK); final JSONObject keydata = resp.getKeydata(); assertNotNull(keydata.remove(KEY_WRAP_KEY)); new ResponseData(PSK_MASTER_TOKEN, keydata); } @Test public void missingWrapdata() throws JSONException, MslKeyExchangeException, MslEncodingException { thrown.expect(MslEncodingException.class); thrown.expectMslError(MslError.JSON_PARSE_ERROR); final ResponseData resp = new ResponseData(PSK_MASTER_TOKEN, WRAP_JWK, WRAPDATA, PSK_ENCRYPTION_JWK, PSK_HMAC_JWK); final JSONObject keydata = resp.getKeydata(); assertNotNull(keydata.remove(KEY_WRAPDATA)); new ResponseData(PSK_MASTER_TOKEN, keydata); } @Test public void missingEncryptionKey() throws MslKeyExchangeException, MslEncodingException, JSONException { thrown.expect(MslEncodingException.class); thrown.expectMslError(MslError.JSON_PARSE_ERROR); final ResponseData resp = new ResponseData(PSK_MASTER_TOKEN, WRAP_JWK, WRAPDATA, PSK_ENCRYPTION_JWK, PSK_HMAC_JWK); final JSONObject keydata = resp.getKeydata(); assertNotNull(keydata.remove(KEY_ENCRYPTION_KEY)); new ResponseData(PSK_MASTER_TOKEN, keydata); } @Test public void missingHmacKey() throws JSONException, MslKeyExchangeException, MslEncodingException { thrown.expect(MslEncodingException.class); thrown.expectMslError(MslError.JSON_PARSE_ERROR); final ResponseData resp = new ResponseData(PSK_MASTER_TOKEN, WRAP_JWK, WRAPDATA, PSK_ENCRYPTION_JWK, PSK_HMAC_JWK); final JSONObject keydata = resp.getKeydata(); assertNotNull(keydata.remove(KEY_HMAC_KEY)); new ResponseData(PSK_MASTER_TOKEN, keydata); } @Test public void equalsWrapKey() throws MslKeyExchangeException, MslEncodingException, JSONException { final byte[] wrapKeyB = Arrays.copyOf(WRAP_JWK, WRAP_JWK.length); ++wrapKeyB[0]; final ResponseData dataA = new ResponseData(PSK_MASTER_TOKEN, WRAP_JWK, WRAPDATA, PSK_ENCRYPTION_JWK, PSK_HMAC_JWK); final ResponseData dataB = new ResponseData(PSK_MASTER_TOKEN, wrapKeyB, WRAPDATA, PSK_ENCRYPTION_JWK, PSK_HMAC_JWK); final ResponseData dataA2 = new ResponseData(PSK_MASTER_TOKEN, dataA.getKeydata()); assertTrue(dataA.equals(dataA)); assertEquals(dataA.hashCode(), dataA.hashCode()); assertFalse(dataA.equals(dataB)); assertFalse(dataB.equals(dataA)); assertTrue(dataA.hashCode() != dataB.hashCode()); assertTrue(dataA.equals(dataA2)); assertTrue(dataA2.equals(dataA)); assertEquals(dataA.hashCode(), dataA2.hashCode()); } @Test public void equalsWrapdata() throws MslKeyExchangeException, MslEncodingException, JSONException { final byte[] wrapdataB = Arrays.copyOf(WRAPDATA, WRAPDATA.length); ++wrapdataB[0]; final ResponseData dataA = new ResponseData(PSK_MASTER_TOKEN, WRAP_JWK, WRAPDATA, PSK_ENCRYPTION_JWK, PSK_HMAC_JWK); final ResponseData dataB = new ResponseData(PSK_MASTER_TOKEN, WRAP_JWK, wrapdataB, PSK_ENCRYPTION_JWK, PSK_HMAC_JWK); final ResponseData dataA2 = new ResponseData(PSK_MASTER_TOKEN, dataA.getKeydata()); assertTrue(dataA.equals(dataA)); assertEquals(dataA.hashCode(), dataA.hashCode()); assertFalse(dataA.equals(dataB)); assertFalse(dataB.equals(dataA)); assertTrue(dataA.hashCode() != dataB.hashCode()); assertTrue(dataA.equals(dataA2)); assertTrue(dataA2.equals(dataA)); assertEquals(dataA.hashCode(), dataA2.hashCode()); } @Test public void equalsEncryptionKey() throws MslKeyExchangeException, MslEncodingException, JSONException { final byte[] encryptionKeyB = Arrays.copyOf(PSK_ENCRYPTION_JWK, PSK_ENCRYPTION_JWK.length); ++encryptionKeyB[0]; final ResponseData dataA = new ResponseData(PSK_MASTER_TOKEN, WRAP_JWK, WRAPDATA, PSK_ENCRYPTION_JWK, PSK_HMAC_JWK); final ResponseData dataB = new ResponseData(PSK_MASTER_TOKEN, WRAP_JWK, WRAPDATA, encryptionKeyB, PSK_HMAC_JWK); final ResponseData dataA2 = new ResponseData(PSK_MASTER_TOKEN, dataA.getKeydata()); assertTrue(dataA.equals(dataA)); assertEquals(dataA.hashCode(), dataA.hashCode()); assertFalse(dataA.equals(dataB)); assertFalse(dataB.equals(dataA)); assertTrue(dataA.hashCode() != dataB.hashCode()); assertTrue(dataA.equals(dataA2)); assertTrue(dataA2.equals(dataA)); assertEquals(dataA.hashCode(), dataA2.hashCode()); } @Test public void equalsHmacKey() throws MslKeyExchangeException, MslEncodingException, JSONException { final byte[] hmacKeyB = Arrays.copyOf(PSK_HMAC_JWK, PSK_HMAC_JWK.length); ++hmacKeyB[0]; final ResponseData dataA = new ResponseData(PSK_MASTER_TOKEN, WRAP_JWK, WRAPDATA, PSK_ENCRYPTION_JWK, PSK_HMAC_JWK); final ResponseData dataB = new ResponseData(PSK_MASTER_TOKEN, WRAP_JWK, WRAPDATA, PSK_ENCRYPTION_JWK, hmacKeyB); final ResponseData dataA2 = new ResponseData(PSK_MASTER_TOKEN, dataA.getKeydata()); assertTrue(dataA.equals(dataA)); assertEquals(dataA.hashCode(), dataA.hashCode()); assertFalse(dataA.equals(dataB)); assertFalse(dataB.equals(dataA)); assertTrue(dataA.hashCode() != dataB.hashCode()); assertTrue(dataA.equals(dataA2)); assertTrue(dataA2.equals(dataA)); assertEquals(dataA.hashCode(), dataA2.hashCode()); } } /** Key exchange factory unit tests. */ public static class KeyExchangeFactoryTest { /** * Fake key request data for the JSON Web Key key ladder key exchange * scheme. */ private static class FakeKeyRequestData extends KeyRequestData { /** Create a new fake key request data. */ protected FakeKeyRequestData() { super(KeyExchangeScheme.JWE_LADDER); } /* (non-Javadoc) * @see com.netflix.msl.keyx.KeyRequestData#getKeydata() */ @Override protected JSONObject getKeydata() throws JSONException { return null; } } /** * Fake key response data for the JSON Web Key key ladder key exchange * scheme. */ private static class FakeKeyResponseData extends KeyResponseData { /** Create a new fake key response data. */ protected FakeKeyResponseData() { super(PSK_MASTER_TOKEN, KeyExchangeScheme.JWE_LADDER); } /* (non-Javadoc) * @see com.netflix.msl.keyx.KeyResponseData#getKeydata() */ @Override protected JSONObject getKeydata() { return null; } } /** * Unwrap a JSON Web Key and return the secret key it contains. * * @param wrapCryptoContext crypto context for unwrapping the JSON Web Key. * @param wrappedJwk the wrapped JSON Web Key. * @return the secret key. * @throws MslCryptoException if there is an error unwrapping the JSON * Web Key. * @throws JSONException if there is an error reconstructing the JSON * Web Key JSON object. * @throws MslEncodingException if there is an error parsing the JSON * Web Key JSON object. */ private static SecretKey extractJwkSecretKey(final ICryptoContext wrapCryptoContext, final byte[] wrappedJwk) throws MslCryptoException, JSONException, MslEncodingException { final byte[] unwrappedJwk = wrapCryptoContext.unwrap(wrappedJwk); final JSONObject jwkJo = new JSONObject(new String(unwrappedJwk, UTF_8)); final JsonWebKey jwk = new JsonWebKey(jwkJo); return jwk.getSecretKey(); } @Rule public ExpectedMslException thrown = ExpectedMslException.none(); @BeforeClass public static void setup() { random = new Random(); repository = new MockCryptoContextRepository(); authutils = new MockAuthenticationUtils(); factory = new JsonWebEncryptionLadderExchange(repository, authutils); // Not sure why I have to do this again since it's already done by // the parent class. Security.addProvider(new BouncyCastleProvider()); } @AfterClass public static void teardown() { factory = null; authutils = null; repository = null; random = null; } @Before public void reset() { authutils.reset(); pskCtx.getMslStore().clearCryptoContexts(); pskCtx.getMslStore().clearServiceTokens(); repository.clear(); } /** Random. */ private static Random random; /** JWE key ladder crypto context repository. */ private static MockCryptoContextRepository repository; /** Authentication utilities. */ private static MockAuthenticationUtils authutils; /** Key exchange factory. */ private static KeyExchangeFactory factory; @Test public void factory() { assertEquals(KeyExchangeScheme.JWE_LADDER, factory.getScheme()); } @Test public void generateWrapInitialResponse() throws MslKeyExchangeException, MslCryptoException, MslEncodingException, MslEntityAuthException, MslException, JSONException { final KeyRequestData req = new RequestData(Mechanism.WRAP, WRAPDATA); final KeyExchangeData keyxData = factory.generateResponse(pskCtx, req, PSK_IDENTITY); assertNotNull(keyxData); assertNotNull(keyxData.cryptoContext); assertNotNull(keyxData.keyResponseData); final KeyResponseData resp = keyxData.keyResponseData; assertEquals(KeyExchangeScheme.JWE_LADDER, resp.getKeyExchangeScheme()); final MasterToken masterToken = resp.getMasterToken(); assertNotNull(masterToken); assertEquals(PSK_IDENTITY, masterToken.getIdentity()); // Unwrap the new wrapping key and create a crypto context from it. assertTrue(resp instanceof ResponseData); final ResponseData respdata = (ResponseData) resp; final SecretKey wrappingKey = extractJwkSecretKey(WRAP_CRYPTO_CONTEXT, respdata.getWrapKey()); final CekCryptoContext cekCryptoContext = new AesKwCryptoContext(wrappingKey); final ICryptoContext wrapCryptoContext = new JsonWebEncryptionCryptoContext(pskCtx, cekCryptoContext, Encryption.A128GCM, Format.JWE_JS); // Unwrap the session keys. final SecretKey encryptionKey = extractJwkSecretKey(wrapCryptoContext, respdata.getEncryptionKey()); assertArrayEquals(masterToken.getEncryptionKey().getEncoded(), encryptionKey.getEncoded()); final SecretKey hmacKey = extractJwkSecretKey(wrapCryptoContext, respdata.getHmacKey()); assertArrayEquals(masterToken.getHmacKey().getEncoded(), hmacKey.getEncoded()); } @Test public void generatePskInitialResponse() throws MslKeyExchangeException, MslCryptoException, MslEncodingException, MslEntityAuthException, MslException, JSONException { final KeyRequestData req = new RequestData(Mechanism.PSK, null); final KeyExchangeData keyxData = factory.generateResponse(pskCtx, req, PSK_IDENTITY); assertNotNull(keyxData); assertNotNull(keyxData.cryptoContext); assertNotNull(keyxData.keyResponseData); final KeyResponseData resp = keyxData.keyResponseData; assertEquals(KeyExchangeScheme.JWE_LADDER, resp.getKeyExchangeScheme()); final MasterToken masterToken = resp.getMasterToken(); assertNotNull(masterToken); assertEquals(PSK_IDENTITY, masterToken.getIdentity()); // Unwrap the new wrapping key and create a crypto context from it. assertTrue(resp instanceof ResponseData); final ResponseData respdata = (ResponseData) resp; final SecretKey wrappingKey = extractJwkSecretKey(PSK_CRYPTO_CONTEXT, respdata.getWrapKey()); final CekCryptoContext cekCryptoContext = new AesKwCryptoContext(wrappingKey); final ICryptoContext wrapCryptoContext = new JsonWebEncryptionCryptoContext(pskCtx, cekCryptoContext, Encryption.A128GCM, Format.JWE_JS); // Unwrap the session keys. final SecretKey encryptionKey = extractJwkSecretKey(wrapCryptoContext, respdata.getEncryptionKey()); assertArrayEquals(masterToken.getEncryptionKey().getEncoded(), encryptionKey.getEncoded()); final SecretKey hmacKey = extractJwkSecretKey(wrapCryptoContext, respdata.getHmacKey()); assertArrayEquals(masterToken.getHmacKey().getEncoded(), hmacKey.getEncoded()); } @Test(expected = MslInternalException.class) public void wrongRequestInitialResponse() throws MslKeyExchangeException, MslCryptoException, MslEncodingException, MslEntityAuthException, MslException { final KeyRequestData req = new FakeKeyRequestData(); factory.generateResponse(pskCtx, req, PSK_IDENTITY); } @Test public void generateWrapSubsequentResponse() throws MslKeyExchangeException, MslCryptoException, MslEncodingException, MslMasterTokenException, MslEntityAuthException, MslException, JSONException { final KeyRequestData req = new RequestData(Mechanism.WRAP, WRAPDATA); final KeyExchangeData keyxData = factory.generateResponse(pskCtx, req, PSK_MASTER_TOKEN); assertNotNull(keyxData); assertNotNull(keyxData.cryptoContext); assertNotNull(keyxData.keyResponseData); final KeyResponseData resp = keyxData.keyResponseData; assertEquals(KeyExchangeScheme.JWE_LADDER, resp.getKeyExchangeScheme()); final MasterToken masterToken = resp.getMasterToken(); assertNotNull(masterToken); assertEquals(PSK_MASTER_TOKEN.getIdentity(), masterToken.getIdentity()); assertEquals(PSK_MASTER_TOKEN.getSerialNumber(), masterToken.getSerialNumber()); assertEquals(PSK_MASTER_TOKEN.getSequenceNumber() + 1, masterToken.getSequenceNumber()); // Unwrap the new wrapping key and create a crypto context from it. assertTrue(resp instanceof ResponseData); final ResponseData respdata = (ResponseData) resp; final SecretKey wrappingKey = extractJwkSecretKey(WRAP_CRYPTO_CONTEXT, respdata.getWrapKey()); final CekCryptoContext cekCryptoContext = new AesKwCryptoContext(wrappingKey); final ICryptoContext wrapCryptoContext = new JsonWebEncryptionCryptoContext(pskCtx, cekCryptoContext, Encryption.A128GCM, Format.JWE_JS); // Unwrap the session keys. final SecretKey encryptionKey = extractJwkSecretKey(wrapCryptoContext, respdata.getEncryptionKey()); assertArrayEquals(masterToken.getEncryptionKey().getEncoded(), encryptionKey.getEncoded()); final SecretKey hmacKey = extractJwkSecretKey(wrapCryptoContext, respdata.getHmacKey()); assertArrayEquals(masterToken.getHmacKey().getEncoded(), hmacKey.getEncoded()); } @Test public void generatePskSubsequentResponse() throws MslKeyExchangeException, MslCryptoException, MslEncodingException, MslMasterTokenException, MslEntityAuthException, MslException, JSONException { final KeyRequestData req = new RequestData(Mechanism.PSK, null); final KeyExchangeData keyxData = factory.generateResponse(pskCtx, req, PSK_MASTER_TOKEN); assertNotNull(keyxData); assertNotNull(keyxData.cryptoContext); assertNotNull(keyxData.keyResponseData); final KeyResponseData resp = keyxData.keyResponseData; assertEquals(KeyExchangeScheme.JWE_LADDER, resp.getKeyExchangeScheme()); final MasterToken masterToken = resp.getMasterToken(); assertNotNull(masterToken); assertEquals(PSK_MASTER_TOKEN.getIdentity(), masterToken.getIdentity()); assertEquals(PSK_MASTER_TOKEN.getSerialNumber(), masterToken.getSerialNumber()); assertEquals(PSK_MASTER_TOKEN.getSequenceNumber() + 1, masterToken.getSequenceNumber()); // Unwrap the new wrapping key and create a crypto context from it. assertTrue(resp instanceof ResponseData); final ResponseData respdata = (ResponseData) resp; final SecretKey wrappingKey = extractJwkSecretKey(PSK_CRYPTO_CONTEXT, respdata.getWrapKey()); final CekCryptoContext cekCryptoContext = new AesKwCryptoContext(wrappingKey); final ICryptoContext wrapCryptoContext = new JsonWebEncryptionCryptoContext(pskCtx, cekCryptoContext, Encryption.A128GCM, Format.JWE_JS); // Unwrap the session keys. final SecretKey encryptionKey = extractJwkSecretKey(wrapCryptoContext, respdata.getEncryptionKey()); assertArrayEquals(masterToken.getEncryptionKey().getEncoded(), encryptionKey.getEncoded()); final SecretKey hmacKey = extractJwkSecretKey(wrapCryptoContext, respdata.getHmacKey()); assertArrayEquals(masterToken.getHmacKey().getEncoded(), hmacKey.getEncoded()); } @Test(expected = MslInternalException.class) public void wrongRequestSubsequentResponse() throws MslKeyExchangeException, MslCryptoException, MslEncodingException, MslMasterTokenException, MslEntityAuthException, MslException { final KeyRequestData req = new FakeKeyRequestData(); factory.generateResponse(pskCtx, req, PSK_MASTER_TOKEN); } @Test(expected = MslMasterTokenException.class) public void untrustedMasterTokenSubsequentResponse() throws MslEncodingException, MslCryptoException, JSONException, MslException { final KeyRequestData req = new RequestData(Mechanism.PSK, null); final MasterToken masterToken = MslTestUtils.getUntrustedMasterToken(pskCtx); factory.generateResponse(pskCtx, req, masterToken); } @Test public void getWrapCryptoContext() throws MslKeyExchangeException, MslCryptoException, MslEncodingException, MslEntityAuthException, MslException { final KeyRequestData req = new RequestData(Mechanism.WRAP, WRAPDATA); final KeyExchangeData keyxData = factory.generateResponse(pskCtx, req, PSK_IDENTITY); final ICryptoContext reqCryptoContext = keyxData.cryptoContext; final KeyResponseData resp = keyxData.keyResponseData; // We must put the wrapping key into the repository to create the // response crypto context. repository.addCryptoContext(WRAPDATA, WRAP_CRYPTO_CONTEXT); assertNotNull(repository.getCryptoContext(WRAPDATA)); final ICryptoContext respCryptoContext = factory.getCryptoContext(pskCtx, req, resp, null); final byte[] wrapdata = repository.getWrapdata(); assertNotNull(wrapdata); assertArrayEquals(((ResponseData) resp).getWrapdata(), wrapdata); assertNull(repository.getCryptoContext(WRAPDATA)); final byte[] data = new byte[32]; random.nextBytes(data); // Ciphertext won't always be equal depending on how it was // enveloped. So we cannot check for equality or inequality. final byte[] requestCiphertext = reqCryptoContext.encrypt(data); final byte[] responseCiphertext = respCryptoContext.encrypt(data); assertFalse(Arrays.equals(data, requestCiphertext)); assertFalse(Arrays.equals(data, responseCiphertext)); // Signatures should always be equal. final byte[] requestSignature = reqCryptoContext.sign(data); final byte[] responseSignature = respCryptoContext.sign(data); assertFalse(Arrays.equals(data, requestSignature)); assertFalse(Arrays.equals(data, responseSignature)); assertArrayEquals(requestSignature, responseSignature); // Plaintext should always be equal to the original message. final byte[] requestPlaintext = reqCryptoContext.decrypt(responseCiphertext); final byte[] responsePlaintext = respCryptoContext.decrypt(requestCiphertext); assertNotNull(requestPlaintext); assertArrayEquals(data, requestPlaintext); assertArrayEquals(requestPlaintext, responsePlaintext); // Verification should always succeed. assertTrue(reqCryptoContext.verify(data, responseSignature)); assertTrue(respCryptoContext.verify(data, requestSignature)); } @Test public void getPskCryptoContext() throws MslKeyExchangeException, MslCryptoException, MslEncodingException, MslEntityAuthException, MslException { final KeyRequestData req = new RequestData(Mechanism.PSK, null); final KeyExchangeData keyxData = factory.generateResponse(pskCtx, req, PSK_IDENTITY); final ICryptoContext reqCryptoContext = keyxData.cryptoContext; final KeyResponseData resp = keyxData.keyResponseData; assertNull(repository.getWrapdata()); final ICryptoContext respCryptoContext = factory.getCryptoContext(pskCtx, req, resp, null); final byte[] wrapdata = repository.getWrapdata(); assertNotNull(wrapdata); assertArrayEquals(((ResponseData) resp).getWrapdata(), wrapdata); final byte[] data = new byte[32]; random.nextBytes(data); // Ciphertext won't always be equal depending on how it was // enveloped. So we cannot check for equality or inequality. final byte[] requestCiphertext = reqCryptoContext.encrypt(data); final byte[] responseCiphertext = respCryptoContext.encrypt(data); assertFalse(Arrays.equals(data, requestCiphertext)); assertFalse(Arrays.equals(data, responseCiphertext)); // Signatures should always be equal. final byte[] requestSignature = reqCryptoContext.sign(data); final byte[] responseSignature = respCryptoContext.sign(data); assertFalse(Arrays.equals(data, requestSignature)); assertFalse(Arrays.equals(data, responseSignature)); assertArrayEquals(requestSignature, responseSignature); // Plaintext should always be equal to the original message. final byte[] requestPlaintext = reqCryptoContext.decrypt(responseCiphertext); final byte[] responsePlaintext = respCryptoContext.decrypt(requestCiphertext); assertNotNull(requestPlaintext); assertArrayEquals(data, requestPlaintext); assertArrayEquals(requestPlaintext, responsePlaintext); // Verification should always succeed. assertTrue(reqCryptoContext.verify(data, responseSignature)); assertTrue(respCryptoContext.verify(data, requestSignature)); } @Test(expected = MslInternalException.class) public void wrongRequestCryptoContext() throws MslKeyExchangeException, MslCryptoException, MslEncodingException, MslEntityAuthException, MslException { final KeyRequestData req = new RequestData(Mechanism.PSK, null); final KeyExchangeData keyxData = factory.generateResponse(pskCtx, req, PSK_IDENTITY); final KeyResponseData resp = keyxData.keyResponseData; final KeyRequestData fakeReq = new FakeKeyRequestData(); factory.getCryptoContext(pskCtx, fakeReq, resp, null); } @Test(expected = MslInternalException.class) public void wrongResponseCryptoContext() throws MslKeyExchangeException, MslCryptoException, MslEncodingException, MslMasterTokenException, MslEntityAuthException { final KeyRequestData req = new RequestData(Mechanism.PSK, null); final KeyResponseData fakeResp = new FakeKeyResponseData(); factory.getCryptoContext(pskCtx, req, fakeResp, null); } @Test public void pskUnsupportedCryptoContext() throws MslKeyExchangeException, MslEntityAuthException, MslException { thrown.expect(MslKeyExchangeException.class); thrown.expectMslError(MslError.UNSUPPORTED_KEYX_MECHANISM); final MockMslContext ctx = new MockMslContext(EntityAuthenticationScheme.PSK, false); final KeyRequestData req = new RequestData(Mechanism.PSK, null); final KeyExchangeData keyxData = factory.generateResponse(ctx, req, PSK_IDENTITY); final KeyResponseData resp = keyxData.keyResponseData; ctx.removeEntityAuthenticationFactory(EntityAuthenticationScheme.PSK); factory.getCryptoContext(ctx, req, resp, null); } @Test public void wrapKeyMissingCryptoContext() throws MslKeyExchangeException, MslCryptoException, MslEncodingException, MslEntityAuthException, MslException { thrown.expect(MslKeyExchangeException.class); thrown.expectMslError(MslError.KEYX_WRAPPING_KEY_MISSING); final KeyRequestData req = new RequestData(Mechanism.WRAP, WRAPDATA); final KeyExchangeData keyxData = factory.generateResponse(pskCtx, req, PSK_IDENTITY); final KeyResponseData resp = keyxData.keyResponseData; factory.getCryptoContext(pskCtx, req, resp, null); } @Test public void invalidWrapJwkCryptoContext() throws MslKeyExchangeException, MslCryptoException, MslEncodingException, MslEntityAuthException, MslException { thrown.expect(MslKeyExchangeException.class); thrown.expectMslError(MslError.INVALID_JWK); final byte[] data = new byte[16]; random.nextBytes(data); final byte[] wrapJwk = WRAP_CRYPTO_CONTEXT.wrap(data); final KeyRequestData req = new RequestData(Mechanism.WRAP, WRAPDATA); final KeyResponseData invalidResp = new ResponseData(PSK_MASTER_TOKEN, wrapJwk, WRAPDATA, PSK_ENCRYPTION_JWK, PSK_HMAC_JWK); repository.addCryptoContext(WRAPDATA, WRAP_CRYPTO_CONTEXT); factory.getCryptoContext(pskCtx, req, invalidResp, null); } @Test public void invalidEncryptionJwkCryptoContext() throws MslException { thrown.expect(MslKeyExchangeException.class); thrown.expectMslError(MslError.INVALID_JWK); final KeyRequestData req = new RequestData(Mechanism.WRAP, WRAPDATA); final KeyExchangeData keyxData = factory.generateResponse(pskCtx, req, PSK_IDENTITY); final ResponseData resp = (ResponseData) keyxData.keyResponseData; // First get the new crypto context. This installs the returned // wrapping key in the repository. repository.addCryptoContext(WRAPDATA, WRAP_CRYPTO_CONTEXT); assertArrayEquals(WRAPDATA, repository.getWrapdata()); factory.getCryptoContext(pskCtx, req, resp, null); assertFalse(Arrays.equals(WRAPDATA, repository.getWrapdata())); // Now make the invalid response. final byte[] data = new byte[16]; random.nextBytes(data); final ICryptoContext wrapCryptoContext = repository.getCryptoContext(repository.getWrapdata()); final byte[] encryptionJwk = wrapCryptoContext.wrap(data); // Extract values from the response. final MasterToken masterToken = resp.getMasterToken(); final byte[] wrapJwk = resp.getWrapKey(); final byte[] wrapdata = resp.getWrapdata(); final byte[] hmacJwk = resp.getHmacKey(); final KeyResponseData invalidResp = new ResponseData(masterToken, wrapJwk, wrapdata, encryptionJwk, hmacJwk); // Reinstall the previous wrap crypto context. repository.addCryptoContext(WRAPDATA, WRAP_CRYPTO_CONTEXT); assertArrayEquals(WRAPDATA, repository.getWrapdata()); factory.getCryptoContext(pskCtx, req, invalidResp, null); } @Test public void invalidHmacJwkCryptoContext() throws MslException { thrown.expect(MslKeyExchangeException.class); thrown.expectMslError(MslError.INVALID_JWK); final KeyRequestData req = new RequestData(Mechanism.WRAP, WRAPDATA); final KeyExchangeData keyxData = factory.generateResponse(pskCtx, req, PSK_IDENTITY); final ResponseData resp = (ResponseData) keyxData.keyResponseData; // First get the new crypto context. This installs the returned // wrapping key in the repository. repository.addCryptoContext(WRAPDATA, WRAP_CRYPTO_CONTEXT); assertArrayEquals(WRAPDATA, repository.getWrapdata()); factory.getCryptoContext(pskCtx, req, resp, null); assertFalse(Arrays.equals(WRAPDATA, repository.getWrapdata())); // Now make the invalid response. final byte[] data = new byte[16]; random.nextBytes(data); final ICryptoContext wrapCryptoContext = repository.getCryptoContext(repository.getWrapdata()); final byte[] hmacJwk = wrapCryptoContext.wrap(data); // Extract values from the response. final MasterToken masterToken = resp.getMasterToken(); final byte[] wrapJwk = resp.getWrapKey(); final byte[] wrapdata = resp.getWrapdata(); final byte[] encryptionJwk = resp.getEncryptionKey(); final KeyResponseData invalidResp = new ResponseData(masterToken, wrapJwk, wrapdata, encryptionJwk, hmacJwk); // Reinstall the previous wrap crypto context. repository.addCryptoContext(WRAPDATA, WRAP_CRYPTO_CONTEXT); assertArrayEquals(WRAPDATA, repository.getWrapdata()); factory.getCryptoContext(pskCtx, req, invalidResp, null); } } }