Search in sources :

Example 1 with MXKey

use of org.matrix.androidsdk.crypto.data.MXKey in project matrix-android-sdk by matrix-org.

the class CryptoRestClient method claimOneTimeKeysForUsersDevices.

/**
 * Claim one-time keys.
 *
 * @param usersDevicesKeyTypesMap a list of users, devices and key types to retrieve keys for.
 * @param callback                the asynchronous callback
 */
public void claimOneTimeKeysForUsersDevices(final MXUsersDevicesMap<String> usersDevicesKeyTypesMap, final ApiCallback<MXUsersDevicesMap<MXKey>> callback) {
    final String description = "claimOneTimeKeysForUsersDevices";
    HashMap<String, Object> params = new HashMap<>();
    params.put("one_time_keys", usersDevicesKeyTypesMap.getMap());
    try {
        mApi.claimOneTimeKeysForUsersDevices(params, new RestAdapterCallback<KeysClaimResponse>(description, mUnsentEventsManager, callback, new RestAdapterCallback.RequestRetryCallBack() {

            @Override
            public void onRetry() {
                claimOneTimeKeysForUsersDevices(usersDevicesKeyTypesMap, callback);
            }
        }) {

            @Override
            public void success(KeysClaimResponse keysClaimResponse, Response response) {
                onEventSent();
                HashMap<String, Map<String, MXKey>> map = new HashMap();
                if (null != keysClaimResponse.oneTimeKeys) {
                    for (String userId : keysClaimResponse.oneTimeKeys.keySet()) {
                        Map<String, Map<String, Map<String, Object>>> mapByUserId = keysClaimResponse.oneTimeKeys.get(userId);
                        HashMap<String, MXKey> keysMap = new HashMap<>();
                        for (String deviceId : mapByUserId.keySet()) {
                            try {
                                keysMap.put(deviceId, new MXKey(mapByUserId.get(deviceId)));
                            } catch (Exception e) {
                                Log.e(LOG_TAG, "## claimOneTimeKeysForUsersDevices : fail to create a MXKey " + e.getMessage());
                            }
                        }
                        if (keysMap.size() != 0) {
                            map.put(userId, keysMap);
                        }
                    }
                }
                callback.onSuccess(new MXUsersDevicesMap<>(map));
            }
        });
    } catch (Throwable t) {
        callback.onUnexpectedError(new Exception(t));
    }
}
Also used : HashMap(java.util.HashMap) MXUsersDevicesMap(org.matrix.androidsdk.crypto.data.MXUsersDevicesMap) DevicesListResponse(org.matrix.androidsdk.rest.model.sync.DevicesListResponse) KeysClaimResponse(org.matrix.androidsdk.rest.model.crypto.KeysClaimResponse) KeysQueryResponse(org.matrix.androidsdk.rest.model.crypto.KeysQueryResponse) KeysUploadResponse(org.matrix.androidsdk.rest.model.crypto.KeysUploadResponse) KeyChangesResponse(org.matrix.androidsdk.rest.model.crypto.KeyChangesResponse) Response(retrofit.client.Response) MXKey(org.matrix.androidsdk.crypto.data.MXKey) KeysClaimResponse(org.matrix.androidsdk.rest.model.crypto.KeysClaimResponse) HashMap(java.util.HashMap) MXUsersDevicesMap(org.matrix.androidsdk.crypto.data.MXUsersDevicesMap) Map(java.util.Map)

Example 2 with MXKey

use of org.matrix.androidsdk.crypto.data.MXKey in project matrix-android-sdk by matrix-org.

the class CryptoRestTest method test03_testClaimOneTimeKeysForUsersDevices.

@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.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.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);
}
Also used : Context(android.content.Context) KeysUploadResponse(org.matrix.androidsdk.rest.model.crypto.KeysUploadResponse) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) CountDownLatch(java.util.concurrent.CountDownLatch) MXUsersDevicesMap(org.matrix.androidsdk.crypto.data.MXUsersDevicesMap) MXKey(org.matrix.androidsdk.crypto.data.MXKey) MatrixError(org.matrix.androidsdk.rest.model.MatrixError) Test(org.junit.Test)

Example 3 with MXKey

use of org.matrix.androidsdk.crypto.data.MXKey in project matrix-android-sdk by matrix-org.

the class MXCrypto method ensureOlmSessionsForDevices.

/**
 * Try to make sure we have established olm sessions for the given devices.
 * It must be called in getCryptoHandler() thread.
 * The callback is called in the UI thread.
 *
 * @param devicesByUser a map from userid to list of devices.
 * @param callback      teh asynchronous callback
 */
public void ensureOlmSessionsForDevices(final HashMap<String, ArrayList<MXDeviceInfo>> devicesByUser, final ApiCallback<MXUsersDevicesMap<MXOlmSessionResult>> callback) {
    ArrayList<MXDeviceInfo> devicesWithoutSession = new ArrayList<>();
    final MXUsersDevicesMap<MXOlmSessionResult> results = new MXUsersDevicesMap<>();
    Set<String> userIds = devicesByUser.keySet();
    for (String userId : userIds) {
        ArrayList<MXDeviceInfo> deviceInfos = devicesByUser.get(userId);
        for (MXDeviceInfo deviceInfo : deviceInfos) {
            String deviceId = deviceInfo.deviceId;
            String key = deviceInfo.identityKey();
            String sessionId = mOlmDevice.getSessionId(key);
            if (TextUtils.isEmpty(sessionId)) {
                devicesWithoutSession.add(deviceInfo);
            }
            MXOlmSessionResult olmSessionResult = new MXOlmSessionResult(deviceInfo, sessionId);
            results.setObject(olmSessionResult, userId, deviceId);
        }
    }
    if (devicesWithoutSession.size() == 0) {
        if (null != callback) {
            getUIHandler().post(new Runnable() {

                @Override
                public void run() {
                    callback.onSuccess(results);
                }
            });
        }
        return;
    }
    // Prepare the request for claiming one-time keys
    MXUsersDevicesMap<String> usersDevicesToClaim = new MXUsersDevicesMap<>();
    final String oneTimeKeyAlgorithm = MXKey.KEY_SIGNED_CURVE_25519_TYPE;
    for (MXDeviceInfo device : devicesWithoutSession) {
        usersDevicesToClaim.setObject(oneTimeKeyAlgorithm, device.userId, device.deviceId);
    }
    // TODO: this has a race condition - if we try to send another message
    // while we are claiming a key, we will end up claiming two and setting up
    // two sessions.
    // 
    // That should eventually resolve itself, but it's poor form.
    Log.d(LOG_TAG, "## claimOneTimeKeysForUsersDevices() : " + usersDevicesToClaim);
    mSession.getCryptoRestClient().claimOneTimeKeysForUsersDevices(usersDevicesToClaim, new ApiCallback<MXUsersDevicesMap<MXKey>>() {

        @Override
        public void onSuccess(final MXUsersDevicesMap<MXKey> oneTimeKeys) {
            getEncryptingThreadHandler().post(new Runnable() {

                @Override
                public void run() {
                    try {
                        Log.d(LOG_TAG, "## claimOneTimeKeysForUsersDevices() : keysClaimResponse.oneTimeKeys: " + oneTimeKeys);
                        Set<String> userIds = devicesByUser.keySet();
                        for (String userId : userIds) {
                            ArrayList<MXDeviceInfo> deviceInfos = devicesByUser.get(userId);
                            for (MXDeviceInfo deviceInfo : deviceInfos) {
                                MXKey oneTimeKey = null;
                                List<String> deviceIds = oneTimeKeys.getUserDeviceIds(userId);
                                if (null != deviceIds) {
                                    for (String deviceId : deviceIds) {
                                        MXOlmSessionResult olmSessionResult = results.getObject(deviceId, userId);
                                        if (null != olmSessionResult.mSessionId) {
                                            // We already have a result for this device
                                            continue;
                                        }
                                        MXKey key = oneTimeKeys.getObject(deviceId, userId);
                                        if (TextUtils.equals(key.type, oneTimeKeyAlgorithm)) {
                                            oneTimeKey = key;
                                        }
                                        if (null == oneTimeKey) {
                                            Log.d(LOG_TAG, "## ensureOlmSessionsForDevices() : No one-time keys " + oneTimeKeyAlgorithm + " for device " + userId + " : " + deviceId);
                                            continue;
                                        }
                                        // Update the result for this device in results
                                        olmSessionResult.mSessionId = verifyKeyAndStartSession(oneTimeKey, userId, deviceInfo);
                                    }
                                }
                            }
                        }
                    } catch (Exception e) {
                        Log.e(LOG_TAG, "## ensureOlmSessionsForDevices() " + e.getMessage());
                    }
                    if (!hasBeenReleased()) {
                        if (null != callback) {
                            getUIHandler().post(new Runnable() {

                                @Override
                                public void run() {
                                    callback.onSuccess(results);
                                }
                            });
                        }
                    }
                }
            });
        }

        @Override
        public void onNetworkError(Exception e) {
            Log.e(LOG_TAG, "## ensureOlmSessionsForUsers(): claimOneTimeKeysForUsersDevices request failed" + e.getMessage());
            if (null != callback) {
                callback.onNetworkError(e);
            }
        }

        @Override
        public void onMatrixError(MatrixError e) {
            Log.e(LOG_TAG, "## ensureOlmSessionsForUsers(): claimOneTimeKeysForUsersDevices request failed" + e.getMessage());
            if (null != callback) {
                callback.onMatrixError(e);
            }
        }

        @Override
        public void onUnexpectedError(Exception e) {
            Log.e(LOG_TAG, "## ensureOlmSessionsForUsers(): claimOneTimeKeysForUsersDevices request failed" + e.getMessage());
            if (null != callback) {
                callback.onUnexpectedError(e);
            }
        }
    });
}
Also used : MXOlmSessionResult(org.matrix.androidsdk.crypto.data.MXOlmSessionResult) MXDeviceInfo(org.matrix.androidsdk.crypto.data.MXDeviceInfo) ArrayList(java.util.ArrayList) MXUsersDevicesMap(org.matrix.androidsdk.crypto.data.MXUsersDevicesMap) MXKey(org.matrix.androidsdk.crypto.data.MXKey) MatrixError(org.matrix.androidsdk.rest.model.MatrixError)

Aggregations

MXKey (org.matrix.androidsdk.crypto.data.MXKey)3 MXUsersDevicesMap (org.matrix.androidsdk.crypto.data.MXUsersDevicesMap)3 ArrayList (java.util.ArrayList)2 HashMap (java.util.HashMap)2 MatrixError (org.matrix.androidsdk.rest.model.MatrixError)2 KeysUploadResponse (org.matrix.androidsdk.rest.model.crypto.KeysUploadResponse)2 Context (android.content.Context)1 Map (java.util.Map)1 CountDownLatch (java.util.concurrent.CountDownLatch)1 Test (org.junit.Test)1 MXDeviceInfo (org.matrix.androidsdk.crypto.data.MXDeviceInfo)1 MXOlmSessionResult (org.matrix.androidsdk.crypto.data.MXOlmSessionResult)1 KeyChangesResponse (org.matrix.androidsdk.rest.model.crypto.KeyChangesResponse)1 KeysClaimResponse (org.matrix.androidsdk.rest.model.crypto.KeysClaimResponse)1 KeysQueryResponse (org.matrix.androidsdk.rest.model.crypto.KeysQueryResponse)1 DevicesListResponse (org.matrix.androidsdk.rest.model.sync.DevicesListResponse)1 Response (retrofit.client.Response)1