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));
}
}
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);
}
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);
}
}
});
}
Aggregations