import java.io.File;
import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
import java.security.Security;
import java.util.ArrayList;
import java.util.List;
System.exit(3);
}
break;
+ case "addDevice":
+ if (dBusConn != null) {
+ System.err.println("link is not yet implemented via dbus");
+ System.exit(1);
+ }
+ if (!m.isRegistered()) {
+ System.err.println("User is not registered.");
+ System.exit(1);
+ }
+ try {
+ m.addDeviceLink(new URI(ns.getString("uri")));
+ } catch (IOException e) {
+ e.printStackTrace();
+ System.exit(3);
+ } catch (InvalidKeyException e) {
+ e.printStackTrace();
+ System.exit(2);
+ } catch (URISyntaxException e) {
+ e.printStackTrace();
+ System.exit(2);
+ }
+ break;
case "send":
if (dBusConn == null && !m.isRegistered()) {
System.err.println("User is not registered.");
parserLink.addArgument("-n", "--name")
.help("Specify a name to describe this new device.");
+ Subparser parserAddDevice = subparsers.addParser("addDevice");
+ parserAddDevice.addArgument("--uri")
+ .required(true)
+ .help("Specify the uri contained in the QR code shown by the new device.");
+
Subparser parserRegister = subparsers.addParser("register");
parserRegister.addArgument("-v", "--voice")
.help("The verification should be done over voice, not sms.")
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.apache.http.util.TextUtils;
import org.asamk.Signal;
import org.whispersystems.libsignal.*;
import org.whispersystems.libsignal.ecc.Curve;
import org.whispersystems.libsignal.ecc.ECKeyPair;
+import org.whispersystems.libsignal.ecc.ECPublicKey;
import org.whispersystems.libsignal.state.PreKeyRecord;
import org.whispersystems.libsignal.state.SignalProtocolStore;
import org.whispersystems.libsignal.state.SignedPreKeyRecord;
import org.whispersystems.signalservice.api.crypto.*;
import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
import org.whispersystems.signalservice.api.messages.*;
+import org.whispersystems.signalservice.api.messages.multidevice.RequestMessage;
import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.whispersystems.signalservice.api.push.TrustStore;
import org.whispersystems.signalservice.api.push.exceptions.EncapsulatedExceptions;
import org.whispersystems.signalservice.api.util.InvalidNumberException;
import org.whispersystems.signalservice.api.util.PhoneNumberFormatter;
+import org.whispersystems.signalservice.internal.push.SignalServiceProtos;
import java.io.*;
import java.net.URI;
import java.net.URISyntaxException;
+import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Paths;
registered = true;
refreshPreKeys();
+ save();
+ }
+
+
+ public static Map<String, String> getQueryMap(String query) {
+ String[] params = query.split("&");
+ Map<String, String> map = new HashMap<>();
+ for (String param : params) {
+ String name = null;
+ try {
+ name = URLDecoder.decode(param.split("=")[0], "utf-8");
+ } catch (UnsupportedEncodingException e) {
+ // Impossible
+ }
+ String value = null;
+ try {
+ value = URLDecoder.decode(param.split("=")[1], "utf-8");
+ } catch (UnsupportedEncodingException e) {
+ // Impossible
+ }
+ map.put(name, value);
+ }
+ return map;
+ }
+
+ public void addDeviceLink(URI linkUri) throws IOException, InvalidKeyException {
+ Map<String, String> query = getQueryMap(linkUri.getQuery());
+ String deviceIdentifier = query.get("uuid");
+ String publicKeyEncoded = query.get("pub_key");
+
+ if (TextUtils.isEmpty(deviceIdentifier) || TextUtils.isEmpty(publicKeyEncoded)) {
+ throw new RuntimeException("Invalid device link uri");
+ }
+
+ ECPublicKey deviceKey = Curve.decodePoint(Base64.decode(publicKeyEncoded), 0);
+
+ addDeviceLink(deviceIdentifier, deviceKey);
+ }
+
+ private void addDeviceLink(String deviceIdentifier, ECPublicKey deviceKey) throws IOException, InvalidKeyException {
+ IdentityKeyPair identityKeyPair = signalProtocolStore.getIdentityKeyPair();
+ String verificationCode = accountManager.getNewDeviceVerificationCode();
+
+ accountManager.addDevice(deviceIdentifier, deviceKey, identityKeyPair, verificationCode);
}
private List<PreKeyRecord> generatePreKeys() {