]> nmode's Git Repositories - signal-cli/blob - src/main/java/org/asamk/signal/manager/ProvisioningManager.java
Refactor Manager to always have a valid SignalAccount instance
[signal-cli] / src / main / java / org / asamk / signal / manager / ProvisioningManager.java
1 /*
2 Copyright (C) 2015-2020 AsamK and contributors
3
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17 package org.asamk.signal.manager;
18
19 import org.asamk.signal.UserAlreadyExists;
20 import org.asamk.signal.storage.SignalAccount;
21 import org.signal.zkgroup.InvalidInputException;
22 import org.signal.zkgroup.profiles.ProfileKey;
23 import org.whispersystems.libsignal.IdentityKeyPair;
24 import org.whispersystems.libsignal.InvalidKeyException;
25 import org.whispersystems.libsignal.util.KeyHelper;
26 import org.whispersystems.signalservice.api.SignalServiceAccountManager;
27 import org.whispersystems.signalservice.api.push.SignalServiceAddress;
28 import org.whispersystems.signalservice.api.util.SleepTimer;
29 import org.whispersystems.signalservice.api.util.UptimeSleepTimer;
30 import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration;
31
32 import java.io.IOException;
33 import java.util.concurrent.TimeoutException;
34
35 public class ProvisioningManager {
36
37 private final PathConfig pathConfig;
38 private final SignalServiceConfiguration serviceConfiguration;
39 private final String userAgent;
40
41 private final SignalServiceAccountManager accountManager;
42 private final IdentityKeyPair identityKey;
43 private final int registrationId;
44 private final String password;
45
46 public ProvisioningManager(String settingsPath, SignalServiceConfiguration serviceConfiguration, String userAgent) {
47 this.pathConfig = PathConfig.createDefault(settingsPath);
48 this.serviceConfiguration = serviceConfiguration;
49 this.userAgent = userAgent;
50
51 identityKey = KeyHelper.generateIdentityKeyPair();
52 registrationId = KeyHelper.generateRegistrationId(false);
53 password = KeyUtils.createPassword();
54 final SleepTimer timer = new UptimeSleepTimer();
55 accountManager = new SignalServiceAccountManager(serviceConfiguration, null, null, password, SignalServiceAddress.DEFAULT_DEVICE_ID, userAgent, timer);
56 }
57
58 public String getDeviceLinkUri() throws TimeoutException, IOException {
59 String deviceUuid = accountManager.getNewDeviceUuid();
60
61 return Utils.createDeviceLinkUri(new Utils.DeviceLinkInfo(deviceUuid, identityKey.getPublicKey().getPublicKey()));
62 }
63
64 public String finishDeviceLink(String deviceName) throws IOException, InvalidKeyException, TimeoutException, UserAlreadyExists {
65 String signalingKey = KeyUtils.createSignalingKey();
66 SignalServiceAccountManager.NewDeviceRegistrationReturn ret = accountManager.finishNewDeviceRegistration(identityKey, signalingKey, false, true, registrationId, deviceName);
67
68 String username = ret.getNumber();
69 // TODO do this check before actually registering
70 if (SignalAccount.userExists(pathConfig.getDataPath(), username)) {
71 throw new UserAlreadyExists(username, SignalAccount.getFileName(pathConfig.getDataPath(), username));
72 }
73
74 // Create new account with the synced identity
75 byte[] profileKeyBytes = ret.getProfileKey();
76 ProfileKey profileKey;
77 if (profileKeyBytes == null) {
78 profileKey = KeyUtils.createProfileKey();
79 } else {
80 try {
81 profileKey = new ProfileKey(profileKeyBytes);
82 } catch (InvalidInputException e) {
83 throw new IOException("Received invalid profileKey", e);
84 }
85 }
86 SignalAccount account = SignalAccount.createLinkedAccount(pathConfig.getDataPath(), username, ret.getUuid(), password, ret.getDeviceId(), ret.getIdentity(), registrationId, signalingKey, profileKey);
87 account.save();
88
89 Manager m = new Manager(account, pathConfig, serviceConfiguration, userAgent);
90
91 m.refreshPreKeys();
92
93 m.requestSyncGroups();
94 m.requestSyncContacts();
95 m.requestSyncBlocked();
96 m.requestSyncConfiguration();
97
98 m.saveAccount();
99
100 return username;
101 }
102 }