]> nmode's Git Repositories - signal-cli/blob - src/main/java/org/asamk/signal/manager/ProvisioningManager.java
Move storage package to manager
[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.manager.storage.SignalAccount;
20 import org.signal.zkgroup.InvalidInputException;
21 import org.signal.zkgroup.profiles.ProfileKey;
22 import org.whispersystems.libsignal.IdentityKeyPair;
23 import org.whispersystems.libsignal.InvalidKeyException;
24 import org.whispersystems.libsignal.util.KeyHelper;
25 import org.whispersystems.signalservice.api.SignalServiceAccountManager;
26 import org.whispersystems.signalservice.api.groupsv2.ClientZkOperations;
27 import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations;
28 import org.whispersystems.signalservice.api.push.SignalServiceAddress;
29 import org.whispersystems.signalservice.api.util.SleepTimer;
30 import org.whispersystems.signalservice.api.util.UptimeSleepTimer;
31 import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration;
32 import org.whispersystems.signalservice.internal.util.DynamicCredentialsProvider;
33
34 import java.io.File;
35 import java.io.IOException;
36 import java.util.concurrent.TimeoutException;
37
38 public class ProvisioningManager {
39
40 private final PathConfig pathConfig;
41 private final SignalServiceConfiguration serviceConfiguration;
42 private final String userAgent;
43
44 private final SignalServiceAccountManager accountManager;
45 private final IdentityKeyPair identityKey;
46 private final int registrationId;
47 private final String password;
48
49 public ProvisioningManager(File settingsPath, SignalServiceConfiguration serviceConfiguration, String userAgent) {
50 this.pathConfig = PathConfig.createDefault(settingsPath);
51 this.serviceConfiguration = serviceConfiguration;
52 this.userAgent = userAgent;
53
54 identityKey = KeyHelper.generateIdentityKeyPair();
55 registrationId = KeyHelper.generateRegistrationId(false);
56 password = KeyUtils.createPassword();
57 final SleepTimer timer = new UptimeSleepTimer();
58 GroupsV2Operations groupsV2Operations;
59 try {
60 groupsV2Operations = new GroupsV2Operations(ClientZkOperations.create(serviceConfiguration));
61 } catch (Throwable ignored) {
62 groupsV2Operations = null;
63 }
64 accountManager = new SignalServiceAccountManager(serviceConfiguration,
65 new DynamicCredentialsProvider(null, null, password, null, SignalServiceAddress.DEFAULT_DEVICE_ID),
66 userAgent,
67 groupsV2Operations,
68 timer);
69 }
70
71 public String getDeviceLinkUri() throws TimeoutException, IOException {
72 String deviceUuid = accountManager.getNewDeviceUuid();
73
74 return Utils.createDeviceLinkUri(new Utils.DeviceLinkInfo(deviceUuid,
75 identityKey.getPublicKey().getPublicKey()));
76 }
77
78 public String finishDeviceLink(String deviceName) throws IOException, InvalidKeyException, TimeoutException, UserAlreadyExists {
79 String signalingKey = KeyUtils.createSignalingKey();
80 SignalServiceAccountManager.NewDeviceRegistrationReturn ret = accountManager.finishNewDeviceRegistration(
81 identityKey,
82 signalingKey,
83 false,
84 true,
85 registrationId,
86 deviceName);
87
88 String username = ret.getNumber();
89 // TODO do this check before actually registering
90 if (SignalAccount.userExists(pathConfig.getDataPath(), username)) {
91 throw new UserAlreadyExists(username, SignalAccount.getFileName(pathConfig.getDataPath(), username));
92 }
93
94 // Create new account with the synced identity
95 byte[] profileKeyBytes = ret.getProfileKey();
96 ProfileKey profileKey;
97 if (profileKeyBytes == null) {
98 profileKey = KeyUtils.createProfileKey();
99 } else {
100 try {
101 profileKey = new ProfileKey(profileKeyBytes);
102 } catch (InvalidInputException e) {
103 throw new IOException("Received invalid profileKey", e);
104 }
105 }
106
107 try (SignalAccount account = SignalAccount.createLinkedAccount(pathConfig.getDataPath(),
108 username,
109 ret.getUuid(),
110 password,
111 ret.getDeviceId(),
112 ret.getIdentity(),
113 registrationId,
114 signalingKey,
115 profileKey)) {
116 account.save();
117
118 try (Manager m = new Manager(account, pathConfig, serviceConfiguration, userAgent)) {
119
120 m.refreshPreKeys();
121
122 m.requestSyncGroups();
123 m.requestSyncContacts();
124 m.requestSyncBlocked();
125 m.requestSyncConfiguration();
126
127 m.saveAccount();
128 }
129 }
130
131 return username;
132 }
133 }