use of im.actor.core.modules.encryption.entity.UserKeysGroup in project actor-platform by actorapp.
the class EncryptedPeerActor method doEncrypt.
private Promise<EncryptBoxResponse> doEncrypt(final byte[] data) {
if (!isReady) {
stash();
return null;
}
//
// Stage 1: Loading User Key Groups
// Stage 2: Pick sessions for encryption
// Stage 3: Encrypt box_key int session
// Stage 4: Encrypt box
//
final byte[] encKey = Crypto.randomBytes(32);
final byte[] encKeyExtended = keyPrf.calculate(encKey, "ActorPackage", 128);
Log.d(TAG, "doEncrypt");
final long start = Runtime.getActorTime();
return PromisesArray.of(theirKeys.getUserKeysGroups()).filter(new Predicate<UserKeysGroup>() {
@Override
public boolean apply(UserKeysGroup keysGroup) {
return !ignoredKeyGroups.contains(keysGroup.getKeyGroupId());
}
}).mapOptional(new Function<UserKeysGroup, Promise<SessionActor>>() {
@Override
public Promise<SessionActor> apply(final UserKeysGroup keysGroup) {
if (activeSessions.containsKey(keysGroup.getKeyGroupId())) {
return success(activeSessions.get(keysGroup.getKeyGroupId()).getSessions().get(0));
}
return context().getEncryption().getSessionManagerInt().pickSession(uid, keysGroup.getKeyGroupId()).failure(new Consumer<Exception>() {
@Override
public void apply(Exception e) {
ignoredKeyGroups.add(keysGroup.getKeyGroupId());
}
}).map(new Function<PeerSession, SessionActor>() {
@Override
public SessionActor apply(PeerSession src) {
return spawnSession(src);
}
});
}
}).mapOptional(encrypt(encKeyExtended)).zip().map(new Function<List<EncryptedSessionActor.EncryptedPackageRes>, EncryptBoxResponse>() {
@Override
public EncryptBoxResponse apply(List<EncryptedSessionActor.EncryptedPackageRes> src) {
if (src.size() == 0) {
throw new RuntimeException("No sessions available");
}
Log.d(TAG, "Keys Encrypted in " + (Runtime.getActorTime() - start) + " ms");
ArrayList<EncryptedBoxKey> encryptedKeys = new ArrayList<>();
for (EncryptedSessionActor.EncryptedPackageRes r : src) {
Log.d(TAG, "Keys: " + r.getKeyGroupId());
encryptedKeys.add(new EncryptedBoxKey(uid, r.getKeyGroupId(), "curve25519", r.getData()));
}
byte[] encData;
try {
encData = ActorBox.closeBox(ByteStrings.intToBytes(ownKeyGroupId), data, Crypto.randomBytes(32), new ActorBoxKey(encKeyExtended));
} catch (IntegrityException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
Log.d(TAG, "All Encrypted in " + (Runtime.getActorTime() - start) + " ms");
return new EncryptBoxResponse(new EncryptedBox(encryptedKeys.toArray(new EncryptedBoxKey[encryptedKeys.size()]), ByteStrings.merge(ByteStrings.intToBytes(ownKeyGroupId), encData)));
}
});
}
use of im.actor.core.modules.encryption.entity.UserKeysGroup in project actor-platform by actorapp.
the class KeyManagerActor method fetchUserGroups.
//
// User keys fetching
//
/**
* Fetching all user's key groups
*
* @param uid User's id
*/
private Promise<UserKeys> fetchUserGroups(final int uid) {
User user = users().getValue(uid);
if (user == null) {
throw new RuntimeException("Unable to find user #" + uid);
}
final UserKeys userKeys = getCachedUserKeys(uid);
if (userKeys != null) {
return Promise.success(userKeys);
}
return api(new RequestLoadPublicKeyGroups(new ApiUserOutPeer(uid, user.getAccessHash()))).map(new Function<ResponsePublicKeyGroups, ArrayList<UserKeysGroup>>() {
@Override
public ArrayList<UserKeysGroup> apply(ResponsePublicKeyGroups response) {
ArrayList<UserKeysGroup> keysGroups = new ArrayList<>();
for (ApiEncryptionKeyGroup keyGroup : response.getPublicKeyGroups()) {
UserKeysGroup validatedKeysGroup = validateUserKeysGroup(uid, keyGroup);
if (validatedKeysGroup != null) {
keysGroups.add(validatedKeysGroup);
}
}
return keysGroups;
}
}).map(new Function<ArrayList<UserKeysGroup>, UserKeys>() {
@Override
public UserKeys apply(ArrayList<UserKeysGroup> userKeysGroups) {
UserKeys userKeys = new UserKeys(uid, userKeysGroups.toArray(new UserKeysGroup[userKeysGroups.size()]));
cacheUserKeys(userKeys);
return userKeys;
}
});
}
use of im.actor.core.modules.encryption.entity.UserKeysGroup in project actor-platform by actorapp.
the class KeyManagerActor method onPublicKeysGroupAdded.
//
// Keys updates handling
//
/**
* Handler for adding new key group
*
* @param uid User's id
* @param keyGroup Added key group
*/
private void onPublicKeysGroupAdded(int uid, ApiEncryptionKeyGroup keyGroup) {
UserKeys userKeys = getCachedUserKeys(uid);
if (userKeys == null) {
return;
}
UserKeysGroup validatedKeysGroup = validateUserKeysGroup(uid, keyGroup);
if (validatedKeysGroup != null) {
UserKeys updatedUserKeys = userKeys.addUserKeyGroup(validatedKeysGroup);
cacheUserKeys(updatedUserKeys);
context().getEncryption().getEncryptedChatManager(uid).send(new EncryptedPeerActor.KeyGroupUpdated(userKeys));
}
}
use of im.actor.core.modules.encryption.entity.UserKeysGroup in project actor-platform by actorapp.
the class KeyManagerActor method fetchUserPreKey.
/**
* Fetching user's pre key by key id
*
* @param uid User's id
* @param keyGroupId User's key group id
* @param keyId Key id
*/
private Promise<PublicKey> fetchUserPreKey(final int uid, final int keyGroupId, final long keyId) {
User user = users().getValue(uid);
if (user == null) {
throw new RuntimeException("Unable to find user #" + uid);
}
return pickUserGroup(uid, keyGroupId).flatMap(new Function<Tuple2<UserKeysGroup, UserKeys>, Promise<PublicKey>>() {
@Override
public Promise<PublicKey> apply(final Tuple2<UserKeysGroup, UserKeys> keysGroup) {
for (PublicKey p : keysGroup.getT1().getEphemeralKeys()) {
if (p.getKeyId() == keyId) {
return Promise.success(p);
}
}
//
// Downloading pre key
//
ArrayList<Long> ids = new ArrayList<Long>();
ids.add(keyId);
final UserKeysGroup finalKeysGroup = keysGroup.getT1();
return api(new RequestLoadPublicKey(new ApiUserOutPeer(uid, getUser(uid).getAccessHash()), keyGroupId, ids)).map(new Function<ResponsePublicKeys, PublicKey>() {
@Override
public PublicKey apply(ResponsePublicKeys responsePublicKeys) {
if (responsePublicKeys.getPublicKey().size() == 0) {
throw new RuntimeException("Unable to find public key on server");
}
ApiEncryptionKeySignature sig = null;
for (ApiEncryptionKeySignature s : responsePublicKeys.getSignatures()) {
if (s.getKeyId() == keyId && "Ed25519".equals(s.getSignatureAlg())) {
sig = s;
break;
}
}
if (sig == null) {
throw new RuntimeException("Unable to find public key on server");
}
ApiEncryptionKey key = responsePublicKeys.getPublicKey().get(0);
byte[] keyHash = RatchetKeySignature.hashForSignature(key.getKeyId(), key.getKeyAlg(), key.getKeyMaterial());
if (!Curve25519.verifySignature(keysGroup.getT1().getIdentityKey().getPublicKey(), keyHash, sig.getSignature())) {
throw new RuntimeException("Key signature does not isMatch");
}
PublicKey pkey = new PublicKey(keyId, key.getKeyAlg(), key.getKeyMaterial());
UserKeysGroup userKeysGroup = finalKeysGroup.addPublicKey(pkey);
cacheUserKeys(keysGroup.getT2().removeUserKeyGroup(userKeysGroup.getKeyGroupId()).addUserKeyGroup(userKeysGroup));
return pkey;
}
});
}
});
}
use of im.actor.core.modules.encryption.entity.UserKeysGroup in project actor-platform by actorapp.
the class KeyManagerActor method fetchUserPreKey.
/**
* Fetching user's random pre key
*
* @param uid User's id
* @param keyGroupId User's key group id
*/
private Promise<PublicKey> fetchUserPreKey(final int uid, final int keyGroupId) {
return pickUserGroup(uid, keyGroupId).flatMap(new Function<Tuple2<UserKeysGroup, UserKeys>, Promise<PublicKey>>() {
@Override
public Promise<PublicKey> apply(final Tuple2<UserKeysGroup, UserKeys> keyGroups) {
return api(new RequestLoadPrePublicKeys(new ApiUserOutPeer(uid, getUser(uid).getAccessHash()), keyGroupId)).map(new Function<ResponsePublicKeys, PublicKey>() {
@Override
public PublicKey apply(ResponsePublicKeys response) {
if (response.getPublicKey().size() == 0) {
throw new RuntimeException("User doesn't have pre keys");
}
ApiEncryptionKey key = response.getPublicKey().get(0);
ApiEncryptionKeySignature sig = null;
for (ApiEncryptionKeySignature s : response.getSignatures()) {
if (s.getKeyId() == key.getKeyId() && "Ed25519".equals(s.getSignatureAlg())) {
sig = s;
break;
}
}
if (sig == null) {
throw new RuntimeException("Unable to find public key on server");
}
byte[] keyHash = RatchetKeySignature.hashForSignature(key.getKeyId(), key.getKeyAlg(), key.getKeyMaterial());
if (!Curve25519.verifySignature(keyGroups.getT1().getIdentityKey().getPublicKey(), keyHash, sig.getSignature())) {
throw new RuntimeException("Key signature does not isMatch");
}
return new PublicKey(key.getKeyId(), key.getKeyAlg(), key.getKeyMaterial());
}
});
}
});
}
Aggregations