/* * Copyright 2016 OpenMarket Ltd * * 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.matrix.androidsdk; import android.content.Context; import android.support.test.InstrumentationRegistry; import android.support.test.runner.AndroidJUnit4; import android.text.TextUtils; import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; import org.matrix.androidsdk.crypto.MXCryptoAlgorithms; import org.matrix.androidsdk.crypto.data.MXDeviceInfo; import org.matrix.androidsdk.crypto.data.MXKey; import org.matrix.androidsdk.crypto.data.MXUsersDevicesMap; import org.matrix.androidsdk.rest.callback.ApiCallback; import org.matrix.androidsdk.rest.model.MatrixError; import org.matrix.androidsdk.rest.model.crypto.KeysQueryResponse; import org.matrix.androidsdk.rest.model.crypto.KeysUploadResponse; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.UUID; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import static org.junit.Assert.assertTrue; @RunWith(AndroidJUnit4.class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class CryptoRestTest { private static final String MXTESTS_BOB = "mxBob"; private static final String MXTESTS_BOB_PWD = "bobbob"; private static final String MXTESTS_ALICE = "mxAlice"; private static final String MXTESTS_ALICE_PWD = "alicealice"; private MXSession mBobSession; private MXSession mAliceSession; private void createBobAccount() throws Exception { Context context = InstrumentationRegistry.getContext(); mBobSession = null; mBobSession = CryptoTestHelper.createAccountAndSync(context, MXTESTS_BOB + System.currentTimeMillis() + UUID.randomUUID().toString(), MXTESTS_BOB_PWD, true); assertTrue (null != mBobSession); } public void createAliceAccount() throws Exception { Context context = InstrumentationRegistry.getContext(); mAliceSession = null; mAliceSession = CryptoTestHelper.createAccountAndSync(context, MXTESTS_ALICE + System.currentTimeMillis() + UUID.randomUUID().toString(), MXTESTS_ALICE_PWD, true); assertTrue (null != mAliceSession); } public void test01_testDeviceKeys() throws Exception { Context context = InstrumentationRegistry.getContext(); createBobAccount(); final HashMap<String, Object> results = new HashMap<>(); String ed25519key = "wV5E3EUSHpHuoZLljNzojlabjGdXT3Mz7rugG9zgbkI"; MXDeviceInfo bobDevice = new MXDeviceInfo("dev1"); bobDevice.userId = mBobSession.getMyUserId(); bobDevice.algorithms = Arrays.asList(MXCryptoAlgorithms.MXCRYPTO_ALGORITHM_OLM); HashMap<String, String> keysMap = new HashMap(); keysMap.put("ed25519:" + bobDevice.deviceId, ed25519key); bobDevice.keys = keysMap; final CountDownLatch lock0 = new CountDownLatch(1); mBobSession.getCryptoRestClient().uploadKeys(bobDevice.JSONDictionary(), null, "dev1", new ApiCallback<KeysUploadResponse>() { @Override public void onSuccess(KeysUploadResponse keysUploadResponse) { results.put("keysUploadResponse", keysUploadResponse); lock0.countDown(); } @Override public void onNetworkError(Exception e) { lock0.countDown(); } @Override public void onMatrixError(MatrixError e) { lock0.countDown(); } @Override public void onUnexpectedError(Exception e) { lock0.countDown(); } }); lock0.await(1000, TimeUnit.DAYS.MILLISECONDS); KeysUploadResponse keysUploadResponse = (KeysUploadResponse)results.get("keysUploadResponse"); assertTrue (null != keysUploadResponse); assertTrue(null != keysUploadResponse.oneTimeKeyCounts); assertTrue(0 == keysUploadResponse.oneTimeKeyCounts.size()); assertTrue(0 == keysUploadResponse.oneTimeKeyCountsForAlgorithm("deded")); final CountDownLatch lock1 = new CountDownLatch(1); mBobSession.getCryptoRestClient().downloadKeysForUsers(Arrays.asList(mBobSession.getMyUserId()), null, new ApiCallback<KeysQueryResponse>() { @Override public void onSuccess(KeysQueryResponse keysQueryResponse) { results.put("keysQueryResponse", keysQueryResponse); lock1.countDown(); } @Override public void onNetworkError(Exception e) { lock1.countDown(); } @Override public void onMatrixError(MatrixError e) { lock1.countDown(); } @Override public void onUnexpectedError(Exception e) { lock1.countDown(); } }); lock1.await(1000, TimeUnit.DAYS.MILLISECONDS); KeysQueryResponse keysQueryResponse = (KeysQueryResponse)results.get("keysQueryResponse"); assertTrue (null != keysQueryResponse); assertTrue (null != keysQueryResponse.deviceKeys); MXUsersDevicesMap<MXDeviceInfo> deviceInfos = new MXUsersDevicesMap<>(keysQueryResponse.deviceKeys); assertTrue (null != deviceInfos.getUserIds()); assertTrue (1 == deviceInfos.getUserIds().size()); List<String> deviceIds = deviceInfos.getUserDeviceIds(mBobSession.getMyUserId()); assertTrue (null != deviceIds); assertTrue (1 == deviceIds.size()); MXDeviceInfo bobDevice2 = deviceInfos.getObject("dev1", mBobSession.getMyUserId()); assertTrue (null != bobDevice2); assertTrue(TextUtils.equals(bobDevice2.deviceId, "dev1")); assertTrue(TextUtils.equals(bobDevice2.userId, mBobSession.getMyUserId())); mBobSession.clear(context); } @Test public void test02_testOneTimeKeys() throws Exception { Context context = InstrumentationRegistry.getContext(); createBobAccount(); final HashMap<String, Object> results = new HashMap<>(); final HashMap<String, Object> otks = new HashMap<>(); otks.put("curve25519:AAAABQ", "ueuHES/Q0P1MZ4J3IUpC8iQTkgQNX66ZpxVLUaTDuB8"); otks.put("curve25519:AAAABA", "PmyaaB68Any+za9CuZXzFsQZW31s/TW6XbAB9akEpQs"); final CountDownLatch lock1 = new CountDownLatch(1); mBobSession.getCryptoRestClient().uploadKeys(null, otks, "dev1", new ApiCallback<KeysUploadResponse>() { @Override public void onSuccess(KeysUploadResponse keysUploadResponse) { results.put("keysUploadResponse", keysUploadResponse); lock1.countDown(); } @Override public void onNetworkError(Exception e) { lock1.countDown(); } @Override public void onMatrixError(MatrixError e) { lock1.countDown(); } @Override public void onUnexpectedError(Exception e) { lock1.countDown(); } }); lock1.await(1000, TimeUnit.DAYS.MILLISECONDS); KeysUploadResponse keysUploadResponse = (KeysUploadResponse)results.get("keysUploadResponse"); assertTrue (null != keysUploadResponse); assertTrue (null != keysUploadResponse.oneTimeKeyCounts); assertTrue (1 == keysUploadResponse.oneTimeKeyCounts.size()); assertTrue (2 == keysUploadResponse.oneTimeKeyCountsForAlgorithm("curve25519")); assertTrue (0 == keysUploadResponse.oneTimeKeyCountsForAlgorithm("deded")); mBobSession.clear(context); } @Test public void test03_testClaimOneTimeKeysForUsersDevices() throws Exception { Context context = InstrumentationRegistry.getContext(); createBobAccount(); createAliceAccount(); final HashMap<String, Object> results = new HashMap<>(); final HashMap<String, Object> otks = new HashMap<>(); { HashMap<String, Object> map = new HashMap<>(); map.put("key", "ueuHES/Q0P1MZ4J3IUpC8iQTkgQNX66ZpxVLUaTDuB8"); HashMap<String, String> signaturesubMap = new HashMap<>(); signaturesubMap.put("ed25519:deviceId1", "signature1"); HashMap<String, Object> signatureMap = new HashMap<>(); signatureMap.put("@user1", signaturesubMap); map.put("signatures", signatureMap); otks.put("curve25519:AAAABQ", map); } { HashMap<String, Object> map = new HashMap<>(); map.put("key", "PmyaaB68Any+za9CuZXzFsQZW31s/TW6XbAB9akEpQs"); HashMap<String, String> signaturesubMap = new HashMap<>(); signaturesubMap.put("ed25519:deviceId2", "signature2"); HashMap<String, Object> signatureMap = new HashMap<>(); signatureMap.put("@user2", signaturesubMap); map.put("signatures", signatureMap); otks.put("curve25519:AAAABA", map); } final CountDownLatch lock1 = new CountDownLatch(1); mBobSession.getCryptoRestClient().uploadKeys(null, otks, "dev1", new ApiCallback<KeysUploadResponse>() { @Override public void onSuccess(KeysUploadResponse keysUploadResponse) { results.put("keysUploadResponse", keysUploadResponse); lock1.countDown(); } @Override public void onNetworkError(Exception e) { lock1.countDown(); } @Override public void onMatrixError(MatrixError e) { lock1.countDown(); } @Override public void onUnexpectedError(Exception e) { lock1.countDown(); } }); lock1.await(1000, TimeUnit.DAYS.MILLISECONDS); KeysUploadResponse bobKeysUploadResponse = (KeysUploadResponse)results.get("keysUploadResponse"); assertTrue (null != bobKeysUploadResponse); MXUsersDevicesMap<String> usersDevicesKeyTypesMap = new MXUsersDevicesMap<>(); usersDevicesKeyTypesMap.setObject("curve25519", mBobSession.getMyUserId(), "dev1"); final CountDownLatch lock2 = new CountDownLatch(1); mAliceSession.getCryptoRestClient().claimOneTimeKeysForUsersDevices(usersDevicesKeyTypesMap, new ApiCallback<MXUsersDevicesMap<MXKey>>() { @Override public void onSuccess(MXUsersDevicesMap<MXKey> usersDevicesMap) { results.put("usersDevicesMap", usersDevicesMap); lock2.countDown(); } @Override public void onNetworkError(Exception e) { lock2.countDown(); } @Override public void onMatrixError(MatrixError e) { lock2.countDown(); } @Override public void onUnexpectedError(Exception e) { lock2.countDown(); } }); lock2.await(1000, TimeUnit.DAYS.MILLISECONDS); MXUsersDevicesMap<MXKey> oneTimeKeys = (MXUsersDevicesMap<MXKey>)results.get("usersDevicesMap"); assertTrue (null != oneTimeKeys); assertTrue (null != oneTimeKeys.getMap()); assertTrue (1 == oneTimeKeys.getMap().size()); MXKey bobOtk = oneTimeKeys.getObject("dev1", mBobSession.getMyUserId()); assertTrue (null != bobOtk); assertTrue(TextUtils.equals(bobOtk.type, MXKey.KEY_CURVE_25519_TYPE)); assertTrue(TextUtils.equals(bobOtk.keyId, "AAAABA")); assertTrue(TextUtils.equals(bobOtk.getKeyFullId(), "curve25519:AAAABA")); assertTrue(TextUtils.equals(bobOtk.value, "PmyaaB68Any+za9CuZXzFsQZW31s/TW6XbAB9akEpQs")); assertTrue(null != bobOtk.signatures); ArrayList<String> keys = new ArrayList<>(bobOtk.signatures.keySet()); assertTrue(keys.size() == 1); mBobSession.clear(context); mAliceSession.clear(context); } }