mirror of
https://github.com/AsamK/signal-cli
synced 2025-08-29 02:20:39 +00:00
Encrypt/decrypt device names
This commit is contained in:
parent
56ac648922
commit
6cb867cbeb
6 changed files with 70 additions and 21 deletions
|
@ -14,7 +14,7 @@ repositories {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
api("com.github.turasa:signal-service-java:2.15.3_unofficial_20")
|
||||
api("com.github.turasa:signal-service-java:2.15.3_unofficial_21")
|
||||
implementation("com.google.protobuf:protobuf-javalite:3.10.0")
|
||||
implementation("org.bouncycastle:bcprov-jdk15on:1.68")
|
||||
implementation("org.slf4j:slf4j-api:1.7.30")
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
*/
|
||||
package org.asamk.signal.manager;
|
||||
|
||||
import org.asamk.signal.manager.api.Device;
|
||||
import org.asamk.signal.manager.config.ServiceConfig;
|
||||
import org.asamk.signal.manager.config.ServiceEnvironment;
|
||||
import org.asamk.signal.manager.config.ServiceEnvironmentConfig;
|
||||
|
@ -108,7 +109,6 @@ import org.whispersystems.signalservice.api.messages.multidevice.DeviceContactsO
|
|||
import org.whispersystems.signalservice.api.messages.multidevice.DeviceGroup;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.DeviceGroupsInputStream;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.DeviceGroupsOutputStream;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.DeviceInfo;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.RequestMessage;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.SentTranscriptMessage;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage;
|
||||
|
@ -119,6 +119,7 @@ import org.whispersystems.signalservice.api.profiles.SignalServiceProfile;
|
|||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.MissingConfigurationException;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException;
|
||||
import org.whispersystems.signalservice.api.util.DeviceNameUtil;
|
||||
import org.whispersystems.signalservice.api.util.InvalidNumberException;
|
||||
import org.whispersystems.signalservice.api.util.PhoneNumberFormatter;
|
||||
import org.whispersystems.signalservice.api.util.SleepTimer;
|
||||
|
@ -341,7 +342,7 @@ public class Manager implements Closeable {
|
|||
}
|
||||
|
||||
public void updateAccountAttributes() throws IOException {
|
||||
accountManager.setAccountAttributes(account.getDeviceName(),
|
||||
accountManager.setAccountAttributes(account.getEncryptedDeviceName(),
|
||||
null,
|
||||
account.getLocalRegistrationId(),
|
||||
true,
|
||||
|
@ -422,10 +423,21 @@ public class Manager implements Closeable {
|
|||
account.setRegistered(false);
|
||||
}
|
||||
|
||||
public List<DeviceInfo> getLinkedDevices() throws IOException {
|
||||
public List<Device> getLinkedDevices() throws IOException {
|
||||
var devices = accountManager.getDevices();
|
||||
account.setMultiDevice(devices.size() > 1);
|
||||
return devices;
|
||||
var identityKey = account.getIdentityKeyPair().getPrivateKey();
|
||||
return devices.stream().map(d -> {
|
||||
String deviceName = d.getName();
|
||||
if (deviceName != null) {
|
||||
try {
|
||||
deviceName = DeviceNameUtil.decryptDeviceName(deviceName, identityKey);
|
||||
} catch (IOException e) {
|
||||
logger.debug("Failed to decrypt device name, maybe plain text?", e);
|
||||
}
|
||||
}
|
||||
return new Device(d.getId(), deviceName, d.getCreated(), d.getLastSeen());
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public void removeLinkedDevices(int deviceId) throws IOException {
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
|||
import org.whispersystems.signalservice.api.groupsv2.ClientZkOperations;
|
||||
import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
import org.whispersystems.signalservice.api.util.DeviceNameUtil;
|
||||
import org.whispersystems.signalservice.api.util.SleepTimer;
|
||||
import org.whispersystems.signalservice.api.util.UptimeSleepTimer;
|
||||
import org.whispersystems.signalservice.internal.util.DynamicCredentialsProvider;
|
||||
|
@ -47,7 +48,7 @@ public class ProvisioningManager {
|
|||
private final String userAgent;
|
||||
|
||||
private final SignalServiceAccountManager accountManager;
|
||||
private final IdentityKeyPair identityKey;
|
||||
private final IdentityKeyPair tempIdentityKey;
|
||||
private final int registrationId;
|
||||
private final String password;
|
||||
|
||||
|
@ -56,7 +57,7 @@ public class ProvisioningManager {
|
|||
this.serviceEnvironmentConfig = serviceEnvironmentConfig;
|
||||
this.userAgent = userAgent;
|
||||
|
||||
identityKey = KeyUtils.generateIdentityKeyPair();
|
||||
tempIdentityKey = KeyUtils.generateIdentityKeyPair();
|
||||
registrationId = KeyHelper.generateRegistrationId(false);
|
||||
password = KeyUtils.createPassword();
|
||||
final SleepTimer timer = new UptimeSleepTimer();
|
||||
|
@ -87,22 +88,26 @@ public class ProvisioningManager {
|
|||
public URI getDeviceLinkUri() throws TimeoutException, IOException {
|
||||
var deviceUuid = accountManager.getNewDeviceUuid();
|
||||
|
||||
return new DeviceLinkInfo(deviceUuid, identityKey.getPublicKey().getPublicKey()).createDeviceLinkUri();
|
||||
return new DeviceLinkInfo(deviceUuid, tempIdentityKey.getPublicKey().getPublicKey()).createDeviceLinkUri();
|
||||
}
|
||||
|
||||
public Manager finishDeviceLink(String deviceName) throws IOException, TimeoutException, UserAlreadyExists {
|
||||
var ret = accountManager.getNewDeviceRegistration(identityKey);
|
||||
var ret = accountManager.getNewDeviceRegistration(tempIdentityKey);
|
||||
var number = ret.getNumber();
|
||||
|
||||
if (SignalAccount.userExists(pathConfig.getDataPath(), number)) {
|
||||
throw new UserAlreadyExists(number, SignalAccount.getFileName(pathConfig.getDataPath(), number));
|
||||
}
|
||||
|
||||
var encryptedDeviceName = deviceName == null
|
||||
? null
|
||||
: DeviceNameUtil.encryptDeviceName(deviceName, ret.getIdentity().getPrivateKey());
|
||||
|
||||
var deviceId = accountManager.finishNewDeviceRegistration(ret.getProvisioningCode(),
|
||||
false,
|
||||
true,
|
||||
registrationId,
|
||||
deviceName);
|
||||
encryptedDeviceName);
|
||||
|
||||
// Create new account with the synced identity
|
||||
var profileKey = ret.getProfileKey() == null ? KeyUtils.createProfileKey() : ret.getProfileKey();
|
||||
|
@ -113,7 +118,7 @@ public class ProvisioningManager {
|
|||
number,
|
||||
ret.getUuid(),
|
||||
password,
|
||||
deviceName,
|
||||
encryptedDeviceName,
|
||||
deviceId,
|
||||
ret.getIdentity(),
|
||||
registrationId,
|
||||
|
|
32
lib/src/main/java/org/asamk/signal/manager/api/Device.java
Normal file
32
lib/src/main/java/org/asamk/signal/manager/api/Device.java
Normal file
|
@ -0,0 +1,32 @@
|
|||
package org.asamk.signal.manager.api;
|
||||
|
||||
public class Device {
|
||||
|
||||
private final long id;
|
||||
private final String name;
|
||||
private final long created;
|
||||
private final long lastSeen;
|
||||
|
||||
public Device(long id, String name, long created, long lastSeen) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.created = created;
|
||||
this.lastSeen = lastSeen;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public long getCreated() {
|
||||
return created;
|
||||
}
|
||||
|
||||
public long getLastSeen() {
|
||||
return lastSeen;
|
||||
}
|
||||
}
|
|
@ -74,7 +74,7 @@ public class SignalAccount implements Closeable {
|
|||
|
||||
private String username;
|
||||
private UUID uuid;
|
||||
private String deviceName;
|
||||
private String encryptedDeviceName;
|
||||
private int deviceId = SignalServiceAddress.DEFAULT_DEVICE_ID;
|
||||
private boolean isMultiDevice = false;
|
||||
private String password;
|
||||
|
@ -172,7 +172,7 @@ public class SignalAccount implements Closeable {
|
|||
String username,
|
||||
UUID uuid,
|
||||
String password,
|
||||
String deviceName,
|
||||
String encryptedDeviceName,
|
||||
int deviceId,
|
||||
IdentityKeyPair identityKey,
|
||||
int registrationId,
|
||||
|
@ -191,7 +191,7 @@ public class SignalAccount implements Closeable {
|
|||
account.uuid = uuid;
|
||||
account.password = password;
|
||||
account.profileKey = profileKey;
|
||||
account.deviceName = deviceName;
|
||||
account.encryptedDeviceName = encryptedDeviceName;
|
||||
account.deviceId = deviceId;
|
||||
|
||||
account.initStores(dataPath, identityKey, registrationId);
|
||||
|
@ -307,7 +307,7 @@ public class SignalAccount implements Closeable {
|
|||
}
|
||||
}
|
||||
if (rootNode.hasNonNull("deviceName")) {
|
||||
deviceName = rootNode.get("deviceName").asText();
|
||||
encryptedDeviceName = rootNode.get("deviceName").asText();
|
||||
}
|
||||
if (rootNode.hasNonNull("deviceId")) {
|
||||
deviceId = rootNode.get("deviceId").asInt();
|
||||
|
@ -579,7 +579,7 @@ public class SignalAccount implements Closeable {
|
|||
rootNode.put("version", CURRENT_STORAGE_VERSION)
|
||||
.put("username", username)
|
||||
.put("uuid", uuid == null ? null : uuid.toString())
|
||||
.put("deviceName", deviceName)
|
||||
.put("deviceName", encryptedDeviceName)
|
||||
.put("deviceId", deviceId)
|
||||
.put("isMultiDevice", isMultiDevice)
|
||||
.put("password", password)
|
||||
|
@ -708,8 +708,8 @@ public class SignalAccount implements Closeable {
|
|||
return recipientStore.resolveRecipientTrusted(getSelfAddress());
|
||||
}
|
||||
|
||||
public String getDeviceName() {
|
||||
return deviceName;
|
||||
public String getEncryptedDeviceName() {
|
||||
return encryptedDeviceName;
|
||||
}
|
||||
|
||||
public int getDeviceId() {
|
||||
|
@ -823,7 +823,7 @@ public class SignalAccount implements Closeable {
|
|||
|
||||
public void finishRegistration(final UUID uuid, final MasterKey masterKey, final String pin) {
|
||||
this.pinMasterKey = masterKey;
|
||||
this.deviceName = null;
|
||||
this.encryptedDeviceName = null;
|
||||
this.deviceId = SignalServiceAddress.DEFAULT_DEVICE_ID;
|
||||
this.isMultiDevice = false;
|
||||
this.registered = true;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue