]> nmode's Git Repositories - signal-cli/commitdiff
Update libsignal-service-java
authorAsamK <asamk@gmx.de>
Sat, 21 Mar 2020 13:37:02 +0000 (14:37 +0100)
committerAsamK <asamk@gmx.de>
Sat, 21 Mar 2020 13:37:02 +0000 (14:37 +0100)
- Use new ProfileKey class instead of byte array
- Add capabilities (for future support of uuid and groups v2)

build.gradle
src/main/java/org/asamk/signal/manager/BaseConfig.java
src/main/java/org/asamk/signal/manager/KeyUtils.java
src/main/java/org/asamk/signal/manager/Manager.java
src/main/java/org/asamk/signal/storage/SignalAccount.java

index 9d5b33a94dcee056449086865fea197f83c0fff9..5c8984da94529fe7403aaa601368bd94a840f0ac 100644 (file)
@@ -20,7 +20,7 @@ repositories {
 }
 
 dependencies {
-    compile 'com.github.turasa:signal-service-java:2.15.3_unofficial_2'
+    compile 'com.github.turasa:signal-service-java:2.15.3_unofficial_3'
     compile 'org.bouncycastle:bcprov-jdk15on:1.64'
     compile 'net.sourceforge.argparse4j:argparse4j:0.8.1'
     compile 'org.freedesktop.dbus:dbus-java:2.7.0'
index f204941c7d8d3378b5a473da8ad92426dc2017bb..edb6c201cd3782683bfa502cf158e960c52293f3 100644 (file)
@@ -37,13 +37,16 @@ public class BaseConfig {
 
     private final static List<Interceptor> interceptors = Collections.singletonList(userAgentInterceptor);
 
+    private final static byte[] zkGroupServerPublicParams = new byte[]{};
+
     final static SignalServiceConfiguration serviceConfiguration = new SignalServiceConfiguration(
             new SignalServiceUrl[]{new SignalServiceUrl(URL, TRUST_STORE)},
             new SignalCdnUrl[]{new SignalCdnUrl(CDN_URL, TRUST_STORE)},
             new SignalContactDiscoveryUrl[0],
             new SignalKeyBackupServiceUrl[]{new SignalKeyBackupServiceUrl(SIGNAL_KEY_BACKUP_URL, TRUST_STORE)},
             new SignalStorageUrl[]{new SignalStorageUrl(STORAGE_URL, TRUST_STORE)},
-            interceptors
+            interceptors,
+            zkGroupServerPublicParams
     );
 
     private BaseConfig() {
index 6ffc3f36a5be499c55934f86c076aebf02f9c8ae..421a32f4badeeddad6019c2bd3918d4ba7fe8332 100644 (file)
@@ -1,6 +1,8 @@
 package org.asamk.signal.manager;
 
 import org.asamk.signal.util.RandomUtils;
+import org.signal.zkgroup.InvalidInputException;
+import org.signal.zkgroup.profiles.ProfileKey;
 import org.whispersystems.util.Base64;
 
 class KeyUtils {
@@ -12,8 +14,12 @@ class KeyUtils {
         return getSecret(52);
     }
 
-    static byte[] createProfileKey() {
-        return getSecretBytes(32);
+    static ProfileKey createProfileKey() {
+        try {
+            return new ProfileKey(getSecretBytes(32));
+        } catch (InvalidInputException e) {
+            throw new AssertionError("Profile key is guaranteed to be 32 bytes here");
+        }
     }
 
     static String createPassword() {
index 8d0d46c88bc7054768104fed9bbb971a0ad7a50a..3a587257f5be93b68b07085a12f02477b09f3dd9 100644 (file)
@@ -41,6 +41,8 @@ import org.signal.libsignal.metadata.ProtocolLegacyMessageException;
 import org.signal.libsignal.metadata.ProtocolNoSessionException;
 import org.signal.libsignal.metadata.ProtocolUntrustedIdentityException;
 import org.signal.libsignal.metadata.SelfSendException;
+import org.signal.zkgroup.InvalidInputException;
+import org.signal.zkgroup.profiles.ProfileKey;
 import org.whispersystems.libsignal.IdentityKey;
 import org.whispersystems.libsignal.IdentityKeyPair;
 import org.whispersystems.libsignal.InvalidKeyException;
@@ -84,6 +86,7 @@ import org.whispersystems.signalservice.api.messages.multidevice.RequestMessage;
 import org.whispersystems.signalservice.api.messages.multidevice.SentTranscriptMessage;
 import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage;
 import org.whispersystems.signalservice.api.messages.multidevice.VerifiedMessage;
+import org.whispersystems.signalservice.api.profiles.SignalServiceProfile;
 import org.whispersystems.signalservice.api.push.ContactTokenDetails;
 import org.whispersystems.signalservice.api.push.SignalServiceAddress;
 import org.whispersystems.signalservice.api.push.exceptions.AuthorizationFailedException;
@@ -126,6 +129,8 @@ import java.util.concurrent.TimeoutException;
 
 public class Manager implements Signal {
 
+    private static final SignalServiceProfile.Capabilities capabilities = new SignalServiceProfile.Capabilities(false, false);
+
     private final String settingsPath;
     private final String dataPath;
     private final String attachmentsPath;
@@ -237,7 +242,7 @@ public class Manager implements Signal {
         if (username == null) {
             account = SignalAccount.createTemporaryAccount(identityKey, registrationId);
         } else {
-            byte[] profileKey = KeyUtils.createProfileKey();
+            ProfileKey profileKey = KeyUtils.createProfileKey();
             account = SignalAccount.create(dataPath, username, identityKey, registrationId, profileKey);
             account.save();
         }
@@ -265,7 +270,7 @@ public class Manager implements Signal {
     }
 
     public void updateAccountAttributes() throws IOException {
-        accountManager.setAccountAttributes(account.getSignalingKey(), account.getSignalProtocolStore().getLocalRegistrationId(), true, account.getRegistrationLockPin(), account.getRegistrationLock(), getSelfUnidentifiedAccessKey(), false);
+        accountManager.setAccountAttributes(account.getSignalingKey(), account.getSignalProtocolStore().getLocalRegistrationId(), true, account.getRegistrationLockPin(), account.getRegistrationLock(), getSelfUnidentifiedAccessKey(), false, capabilities);
     }
 
     public void setProfileName(String name) throws IOException {
@@ -314,9 +319,16 @@ public class Manager implements Signal {
         }
 
         // Create new account with the synced identity
-        byte[] profileKey = ret.getProfileKey();
-        if (profileKey == null) {
+        byte[] profileKeyBytes = ret.getProfileKey();
+        ProfileKey profileKey;
+        if (profileKeyBytes == null) {
             profileKey = KeyUtils.createProfileKey();
+        } else {
+            try {
+                profileKey = new ProfileKey(profileKeyBytes);
+            } catch (InvalidInputException e) {
+                throw new IOException("Received invalid profileKey", e);
+            }
         }
         account = SignalAccount.createLinkedAccount(dataPath, username, account.getPassword(), ret.getDeviceId(), ret.getIdentity(), account.getSignalProtocolStore().getLocalRegistrationId(), account.getSignalingKey(), profileKey);
 
@@ -354,7 +366,7 @@ public class Manager implements Signal {
         IdentityKeyPair identityKeyPair = account.getSignalProtocolStore().getIdentityKeyPair();
         String verificationCode = accountManager.getNewDeviceVerificationCode();
 
-        accountManager.addDevice(deviceIdentifier, deviceKey, identityKeyPair, Optional.of(account.getProfileKey()), verificationCode);
+        accountManager.addDevice(deviceIdentifier, deviceKey, identityKeyPair, Optional.of(account.getProfileKey().serialize()), verificationCode);
         account.setMultiDevice(true);
         account.save();
     }
@@ -396,7 +408,7 @@ public class Manager implements Signal {
         verificationCode = verificationCode.replace("-", "");
         account.setSignalingKey(KeyUtils.createSignalingKey());
         // TODO make unrestricted unidentified access configurable
-        accountManager.verifyAccountWithCode(verificationCode, account.getSignalingKey(), account.getSignalProtocolStore().getLocalRegistrationId(), true, pin, null, getSelfUnidentifiedAccessKey(), false);
+        accountManager.verifyAccountWithCode(verificationCode, account.getSignalingKey(), account.getSignalProtocolStore().getLocalRegistrationId(), true, pin, null, getSelfUnidentifiedAccessKey(), false, capabilities);
 
         //accountManager.setGcmId(Optional.of(GoogleCloudMessaging.getInstance(this).register(REGISTRATION_ID)));
         account.setRegistered(true);
@@ -502,7 +514,7 @@ public class Manager implements Signal {
         SignalServiceDataMessage.Reaction reaction = new SignalServiceDataMessage.Reaction(emoji, remove, targetAuthor, targetSentTimestamp);
         final SignalServiceDataMessage.Builder messageBuilder = SignalServiceDataMessage.newBuilder()
                 .withReaction(reaction)
-                .withProfileKey(account.getProfileKey());
+                .withProfileKey(account.getProfileKey().serialize());
         if (groupId != null) {
             SignalServiceGroup group = SignalServiceGroup.newBuilder(SignalServiceGroup.Type.DELIVER)
                     .withId(groupId)
@@ -685,7 +697,7 @@ public class Manager implements Signal {
 
             messageBuilder.withAttachments(attachmentPointers);
         }
-        messageBuilder.withProfileKey(account.getProfileKey());
+        messageBuilder.withProfileKey(account.getProfileKey().serialize());
         sendMessageLegacy(messageBuilder, recipients);
     }
 
@@ -695,7 +707,7 @@ public class Manager implements Signal {
         SignalServiceDataMessage.Reaction reaction = new SignalServiceDataMessage.Reaction(emoji, remove, targetAuthor, targetSentTimestamp);
         final SignalServiceDataMessage.Builder messageBuilder = SignalServiceDataMessage.newBuilder()
                 .withReaction(reaction)
-                .withProfileKey(account.getProfileKey());
+                .withProfileKey(account.getProfileKey().serialize());
         sendMessageLegacy(messageBuilder, recipients);
     }
 
@@ -1117,7 +1129,10 @@ public class Manager implements Signal {
         }
         if (message.getProfileKey().isPresent() && message.getProfileKey().get().length == 32) {
             if (source.equals(username)) {
-                this.account.setProfileKey(message.getProfileKey().get());
+                try {
+                    this.account.setProfileKey(new ProfileKey(message.getProfileKey().get()));
+                } catch (InvalidInputException ignored) {
+                }
             }
             ContactInfo contact = account.getContactStore().getContact(source);
             if (contact == null) {
@@ -1413,7 +1428,7 @@ public class Manager implements Signal {
                                     contact.color = c.getColor().get();
                                 }
                                 if (c.getProfileKey().isPresent()) {
-                                    contact.profileKey = Base64.encodeBytes(c.getProfileKey().get());
+                                    contact.profileKey = Base64.encodeBytes(c.getProfileKey().get().serialize());
                                 }
                                 if (c.getVerified().isPresent()) {
                                     final VerifiedMessage verifiedMessage = c.getVerified().get();
@@ -1603,7 +1618,11 @@ public class Manager implements Signal {
                         }
                     }
 
-                    byte[] profileKey = record.profileKey == null ? null : Base64.decode(record.profileKey);
+                    ProfileKey profileKey = null;
+                    try {
+                        profileKey = record.profileKey == null ? null : new ProfileKey(Base64.decode(record.profileKey));
+                    } catch (InvalidInputException ignored) {
+                    }
                     out.write(new DeviceContact(record.getAddress(), Optional.fromNullable(record.name),
                             createContactAvatarAttachment(record.number), Optional.fromNullable(record.color),
                             Optional.fromNullable(verifiedMessage), Optional.fromNullable(profileKey), record.blocked,
index 151835cb6afb3ab810e41281ee4d7f63018d61e3..fd4da41f39f45f79dff6f90b800de7a35718c78d 100644 (file)
@@ -16,6 +16,8 @@ import org.asamk.signal.storage.protocol.JsonSignalProtocolStore;
 import org.asamk.signal.storage.threads.JsonThreadStore;
 import org.asamk.signal.util.IOUtils;
 import org.asamk.signal.util.Util;
+import org.signal.zkgroup.InvalidInputException;
+import org.signal.zkgroup.profiles.ProfileKey;
 import org.whispersystems.libsignal.IdentityKeyPair;
 import org.whispersystems.libsignal.state.PreKeyRecord;
 import org.whispersystems.libsignal.state.SignedPreKeyRecord;
@@ -42,7 +44,7 @@ public class SignalAccount {
     private String password;
     private String registrationLockPin;
     private String signalingKey;
-    private byte[] profileKey;
+    private ProfileKey profileKey;
     private int preKeyIdOffset;
     private int nextSignedPreKeyId;
 
@@ -70,7 +72,7 @@ public class SignalAccount {
         return account;
     }
 
-    public static SignalAccount create(String dataPath, String username, IdentityKeyPair identityKey, int registrationId, byte[] profileKey) throws IOException {
+    public static SignalAccount create(String dataPath, String username, IdentityKeyPair identityKey, int registrationId, ProfileKey profileKey) throws IOException {
         IOUtils.createPrivateDirectories(dataPath);
 
         SignalAccount account = new SignalAccount();
@@ -87,7 +89,7 @@ public class SignalAccount {
         return account;
     }
 
-    public static SignalAccount createLinkedAccount(String dataPath, String username, String password, int deviceId, IdentityKeyPair identityKey, int registrationId, String signalingKey, byte[] profileKey) throws IOException {
+    public static SignalAccount createLinkedAccount(String dataPath, String username, String password, int deviceId, IdentityKeyPair identityKey, int registrationId, String signalingKey, ProfileKey profileKey) throws IOException {
         IOUtils.createPrivateDirectories(dataPath);
 
         SignalAccount account = new SignalAccount();
@@ -161,7 +163,11 @@ public class SignalAccount {
             nextSignedPreKeyId = 0;
         }
         if (rootNode.has("profileKey")) {
-            profileKey = Base64.decode(Util.getNotNullNode(rootNode, "profileKey").asText());
+            try {
+                profileKey = new ProfileKey(Base64.decode(Util.getNotNullNode(rootNode, "profileKey").asText()));
+            } catch (InvalidInputException e) {
+                throw new IOException("Config file contains an invalid profileKey, needs to be base64 encoded array of 32 bytes", e);
+            }
         }
 
         signalProtocolStore = jsonProcessor.convertValue(Util.getNotNullNode(rootNode, "axolotlStore"), JsonSignalProtocolStore.class);
@@ -203,7 +209,7 @@ public class SignalAccount {
                 .put("signalingKey", signalingKey)
                 .put("preKeyIdOffset", preKeyIdOffset)
                 .put("nextSignedPreKeyId", nextSignedPreKeyId)
-                .put("profileKey", Base64.encodeBytes(profileKey))
+                .put("profileKey", Base64.encodeBytes(profileKey.serialize()))
                 .put("registered", registered)
                 .putPOJO("axolotlStore", signalProtocolStore)
                 .putPOJO("groupStore", groupStore)
@@ -307,11 +313,11 @@ public class SignalAccount {
         this.signalingKey = signalingKey;
     }
 
-    public byte[] getProfileKey() {
+    public ProfileKey getProfileKey() {
         return profileKey;
     }
 
-    public void setProfileKey(final byte[] profileKey) {
+    public void setProfileKey(final ProfileKey profileKey) {
         this.profileKey = profileKey;
     }