Search in sources :

Example 1 with ApiEncryptionKeySignature

use of im.actor.core.api.ApiEncryptionKeySignature in project actor-platform by actorapp.

the class KeyManagerActor method onMainKeysReady.

private void onMainKeysReady() {
    Log.d(TAG, "Main Keys are ready");
    //
    // Generation required pre keys
    //
    int missingKeysCount = Math.max(0, Configuration.EPHEMERAL_KEYS_COUNT - ownKeys.getPreKeys().length);
    if (missingKeysCount > 0) {
        ownKeys = ownKeys.appendPreKeys(ManagedList.of(PrivateKey.GENERATOR, missingKeysCount).toArray(new PrivateKey[0]));
        encryptionKeysStorage.addOrUpdateItem(0, ownKeys.toByteArray());
    }
    //
    // Uploading own pre keys
    //
    final ManagedList<PrivateKey> pendingEphermalKeys = ManagedList.of(ownKeys.getPreKeys()).filter(PrivateKey.NOT_UPLOADED);
    if (pendingEphermalKeys.size() > 0) {
        ArrayList<ApiEncryptionKey> uploadingKeys = pendingEphermalKeys.map(PrivateKey.TO_API);
        ArrayList<ApiEncryptionKeySignature> uploadingSignatures = pendingEphermalKeys.map(PrivateKey.SIGN(ownKeys.getIdentityKey()));
        api(new RequestUploadPreKey(ownKeys.getKeyGroupId(), uploadingKeys, uploadingSignatures)).then(new Consumer<ResponseVoid>() {

            @Override
            public void apply(ResponseVoid responseVoid) {
                ownKeys = ownKeys.markAsUploaded(pendingEphermalKeys.toArray(new PrivateKey[pendingEphermalKeys.size()]));
                encryptionKeysStorage.addOrUpdateItem(0, ownKeys.toByteArray());
                onAllKeysReady();
            }
        }).failure(new Consumer<Exception>() {

            @Override
            public void apply(Exception e) {
                Log.w(TAG, "Ephemeral keys upload error");
                Log.e(TAG, e);
            // Ignore. This will freeze all encryption operations.
            }
        });
    } else {
        onAllKeysReady();
    }
}
Also used : ResponseVoid(im.actor.core.api.rpc.ResponseVoid) PrivateKey(im.actor.core.modules.encryption.entity.PrivateKey) RequestUploadPreKey(im.actor.core.api.rpc.RequestUploadPreKey) IOException(java.io.IOException) Consumer(im.actor.runtime.function.Consumer) ApiEncryptionKeySignature(im.actor.core.api.ApiEncryptionKeySignature) ApiEncryptionKey(im.actor.core.api.ApiEncryptionKey)

Example 2 with ApiEncryptionKeySignature

use of im.actor.core.api.ApiEncryptionKeySignature 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());
                }
            });
        }
    });
}
Also used : RequestLoadPrePublicKeys(im.actor.core.api.rpc.RequestLoadPrePublicKeys) ApiUserOutPeer(im.actor.core.api.ApiUserOutPeer) RequestLoadPublicKey(im.actor.core.api.rpc.RequestLoadPublicKey) PublicKey(im.actor.core.modules.encryption.entity.PublicKey) UserKeys(im.actor.core.modules.encryption.entity.UserKeys) ResponsePublicKeys(im.actor.core.api.rpc.ResponsePublicKeys) UserKeysGroup(im.actor.core.modules.encryption.entity.UserKeysGroup) Promise(im.actor.runtime.promise.Promise) Function(im.actor.runtime.function.Function) ApiEncryptionKeySignature(im.actor.core.api.ApiEncryptionKeySignature) Tuple2(im.actor.runtime.function.Tuple2) ApiEncryptionKey(im.actor.core.api.ApiEncryptionKey)

Example 3 with ApiEncryptionKeySignature

use of im.actor.core.api.ApiEncryptionKeySignature in project actor-platform by actorapp.

the class KeyManagerActor method validateUserKeysGroup.

//
// Helper methods
//
private UserKeysGroup validateUserKeysGroup(int uid, ApiEncryptionKeyGroup keyGroup) {
    if (!"curve25519".equals(keyGroup.getIdentityKey().getKeyAlg())) {
        // Anything other than curve25519 is not supported
        Log.w(TAG, "(uid:" + uid + ") Unsupported identity key alg " + keyGroup.getIdentityKey().getKeyAlg());
        return null;
    }
    PublicKey identity = new PublicKey(keyGroup.getIdentityKey().getKeyId(), keyGroup.getIdentityKey().getKeyAlg(), keyGroup.getIdentityKey().getKeyMaterial());
    ArrayList<PublicKey> keys = new ArrayList<PublicKey>();
    key_loop: for (ApiEncryptionKey key : keyGroup.getKeys()) {
        //
        for (ApiEncryptionKeySignature sig : keyGroup.getSignatures()) {
            if (!sig.getSignatureAlg().equals("Ed25519")) {
                // Anything other than Ed25519 is not supported
                Log.w(TAG, "(uid:" + uid + ") Unsupported signature algorithm " + sig.getSignatureAlg());
                continue;
            }
            if (sig.getKeyId() != key.getKeyId()) {
                continue;
            }
            byte[] keyForSign = RatchetKeySignature.hashForSignature(key.getKeyId(), key.getKeyAlg(), key.getKeyMaterial());
            if (!Curve25519.verifySignature(identity.getPublicKey(), keyForSign, sig.getSignature())) {
                Log.w(TAG, "(uid:" + uid + ") Unable to verify signature for " + Crypto.keyHash(key.getKeyMaterial()) + " key");
                continue key_loop;
            }
        }
        //
        // Adding key to collection
        //
        keys.add(new PublicKey(key.getKeyId(), key.getKeyAlg(), key.getKeyMaterial()));
    }
    if (keys.size() == 0) {
        Log.w(TAG, "(uid:" + uid + ") No valid keys in key group #" + keyGroup.getKeyGroupId());
    }
    return new UserKeysGroup(keyGroup.getKeyGroupId(), identity, keys.toArray(new PublicKey[keys.size()]), new PublicKey[0]);
}
Also used : ApiEncryptionKeySignature(im.actor.core.api.ApiEncryptionKeySignature) RequestLoadPublicKey(im.actor.core.api.rpc.RequestLoadPublicKey) PublicKey(im.actor.core.modules.encryption.entity.PublicKey) ApiEncryptionKey(im.actor.core.api.ApiEncryptionKey) ArrayList(java.util.ArrayList) UserKeysGroup(im.actor.core.modules.encryption.entity.UserKeysGroup)

Example 4 with ApiEncryptionKeySignature

use of im.actor.core.api.ApiEncryptionKeySignature 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;
                }
            });
        }
    });
}
Also used : User(im.actor.core.entity.User) ApiUserOutPeer(im.actor.core.api.ApiUserOutPeer) RequestLoadPublicKey(im.actor.core.api.rpc.RequestLoadPublicKey) PublicKey(im.actor.core.modules.encryption.entity.PublicKey) RequestLoadPublicKey(im.actor.core.api.rpc.RequestLoadPublicKey) ArrayList(java.util.ArrayList) UserKeys(im.actor.core.modules.encryption.entity.UserKeys) ResponsePublicKeys(im.actor.core.api.rpc.ResponsePublicKeys) UserKeysGroup(im.actor.core.modules.encryption.entity.UserKeysGroup) Promise(im.actor.runtime.promise.Promise) Function(im.actor.runtime.function.Function) ApiEncryptionKeySignature(im.actor.core.api.ApiEncryptionKeySignature) Tuple2(im.actor.runtime.function.Tuple2) ApiEncryptionKey(im.actor.core.api.ApiEncryptionKey)

Example 5 with ApiEncryptionKeySignature

use of im.actor.core.api.ApiEncryptionKeySignature in project actor-platform by actorapp.

the class KeyManagerActor method preStart.

@Override
public void preStart() {
    Log.d(TAG, "Starting KeyManager...");
    //
    // Initialization key storage
    //
    encryptionKeysStorage = Storage.createKeyValue("encryption_keys");
    //
    // Initialization own private keys
    //
    ownKeys = null;
    byte[] ownKeysStorage = encryptionKeysStorage.loadItem(0);
    if (ownKeysStorage != null) {
        try {
            ownKeys = new PrivateKeyStorage(ownKeysStorage);
            // If we need re-save key storage
            if (ownKeys.isWasRegenerated()) {
                encryptionKeysStorage.addOrUpdateItem(0, ownKeys.toByteArray());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    if (ownKeys == null) {
        Curve25519KeyPair identityPrivate = Curve25519.keyGen(Crypto.randomBytes(64));
        Curve25519KeyPair key0 = Curve25519.keyGen(Crypto.randomBytes(64));
        ownKeys = new PrivateKeyStorage(0, new PrivateKey(RandomUtils.nextRid(), "curve25519", identityPrivate.getPrivateKey(), identityPrivate.getPublicKey()), new PrivateKey[] { new PrivateKey(RandomUtils.nextRid(), "curve25519", key0.getPrivateKey(), key0.getPublicKey()) }, new PrivateKey[0]);
        encryptionKeysStorage.addOrUpdateItem(0, ownKeys.toByteArray());
    }
    if (ownKeys.getKeyGroupId() == 0) {
        ApiEncryptionKey identityKey = ownKeys.getIdentityKey().toApiKey();
        ArrayList<ApiEncryptionKey> keys = ManagedList.of(ownKeys.getKeys()).map(PrivateKey.TO_API);
        ArrayList<ApiEncryptionKeySignature> signatures = ManagedList.of(ownKeys.getKeys()).map(PrivateKey.SIGN(ownKeys.getIdentityKey()));
        Log.d(TAG, "Creation of new key group");
        api(new RequestCreateNewKeyGroup(identityKey, Configuration.SUPPORTED, keys, signatures)).then(new Consumer<ResponseCreateNewKeyGroup>() {

            @Override
            public void apply(ResponseCreateNewKeyGroup response) {
                ownKeys = ownKeys.setGroupId(response.getKeyGroupId());
                encryptionKeysStorage.addOrUpdateItem(0, ownKeys.toByteArray());
                onMainKeysReady();
            }
        }).failure(new Consumer<Exception>() {

            @Override
            public void apply(Exception e) {
                Log.w(TAG, "Keys upload error");
                Log.e(TAG, e);
            // Just ignore
            }
        });
    } else {
        onMainKeysReady();
    }
}
Also used : RequestCreateNewKeyGroup(im.actor.core.api.rpc.RequestCreateNewKeyGroup) PrivateKeyStorage(im.actor.core.modules.encryption.entity.PrivateKeyStorage) PrivateKey(im.actor.core.modules.encryption.entity.PrivateKey) ResponseCreateNewKeyGroup(im.actor.core.api.rpc.ResponseCreateNewKeyGroup) IOException(java.io.IOException) IOException(java.io.IOException) Consumer(im.actor.runtime.function.Consumer) ApiEncryptionKeySignature(im.actor.core.api.ApiEncryptionKeySignature) Curve25519KeyPair(im.actor.runtime.crypto.Curve25519KeyPair) ApiEncryptionKey(im.actor.core.api.ApiEncryptionKey)

Aggregations

ApiEncryptionKey (im.actor.core.api.ApiEncryptionKey)5 ApiEncryptionKeySignature (im.actor.core.api.ApiEncryptionKeySignature)5 RequestLoadPublicKey (im.actor.core.api.rpc.RequestLoadPublicKey)3 PublicKey (im.actor.core.modules.encryption.entity.PublicKey)3 UserKeysGroup (im.actor.core.modules.encryption.entity.UserKeysGroup)3 ApiUserOutPeer (im.actor.core.api.ApiUserOutPeer)2 ResponsePublicKeys (im.actor.core.api.rpc.ResponsePublicKeys)2 PrivateKey (im.actor.core.modules.encryption.entity.PrivateKey)2 UserKeys (im.actor.core.modules.encryption.entity.UserKeys)2 Consumer (im.actor.runtime.function.Consumer)2 Function (im.actor.runtime.function.Function)2 Tuple2 (im.actor.runtime.function.Tuple2)2 Promise (im.actor.runtime.promise.Promise)2 IOException (java.io.IOException)2 ArrayList (java.util.ArrayList)2 RequestCreateNewKeyGroup (im.actor.core.api.rpc.RequestCreateNewKeyGroup)1 RequestLoadPrePublicKeys (im.actor.core.api.rpc.RequestLoadPrePublicKeys)1 RequestUploadPreKey (im.actor.core.api.rpc.RequestUploadPreKey)1 ResponseCreateNewKeyGroup (im.actor.core.api.rpc.ResponseCreateNewKeyGroup)1 ResponseVoid (im.actor.core.api.rpc.ResponseVoid)1