X-Git-Url: https://git.nmode.ca/signal-cli/blobdiff_plain/cf972e5b6c6ae51aeb8a3d4cad95d9da75b42968..e2b7bda65ba728a0a747bb0bac6fbe1e56fd2de8:/src/main/java/org/asamk/signal/storage/SignalAccount.java diff --git a/src/main/java/org/asamk/signal/storage/SignalAccount.java b/src/main/java/org/asamk/signal/storage/SignalAccount.java index 4378d052..08ed5139 100644 --- a/src/main/java/org/asamk/signal/storage/SignalAccount.java +++ b/src/main/java/org/asamk/signal/storage/SignalAccount.java @@ -9,18 +9,21 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.node.ObjectNode; + import org.asamk.signal.storage.contacts.JsonContactsStore; import org.asamk.signal.storage.groups.JsonGroupStore; 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; import org.whispersystems.libsignal.util.Medium; import org.whispersystems.signalservice.api.push.SignalServiceAddress; -import org.whispersystems.signalservice.internal.util.Base64; +import org.whispersystems.util.Base64; import java.io.File; import java.io.IOException; @@ -29,6 +32,7 @@ import java.nio.channels.Channels; import java.nio.channels.FileChannel; import java.nio.channels.FileLock; import java.util.Collection; +import java.util.UUID; public class SignalAccount { @@ -36,12 +40,13 @@ public class SignalAccount { private FileChannel fileChannel; private FileLock lock; private String username; + private UUID uuid; private int deviceId = SignalServiceAddress.DEFAULT_DEVICE_ID; private boolean isMultiDevice = false; private String password; private String registrationLockPin; private String signalingKey; - private byte[] profileKey; + private ProfileKey profileKey; private int preKeyIdOffset; private int nextSignedPreKeyId; @@ -69,7 +74,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(); @@ -86,7 +91,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(); @@ -129,13 +134,19 @@ public class SignalAccount { } private void load() throws IOException { - JsonNode rootNode = jsonProcessor.readTree(Channels.newInputStream(fileChannel)); + JsonNode rootNode; + synchronized (fileChannel) { + fileChannel.position(0); + rootNode = jsonProcessor.readTree(Channels.newInputStream(fileChannel)); + } JsonNode node = rootNode.get("deviceId"); if (node != null) { deviceId = node.asInt(); } - if (rootNode.has("isMultiDevice")) isMultiDevice = Util.getNotNullNode(rootNode, "isMultiDevice").asBoolean(); + if (rootNode.has("isMultiDevice")) { + isMultiDevice = Util.getNotNullNode(rootNode, "isMultiDevice").asBoolean(); + } username = Util.getNotNullNode(rootNode, "username").asText(); password = Util.getNotNullNode(rootNode, "password").asText(); JsonNode pinNode = rootNode.get("registrationLockPin"); @@ -154,7 +165,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); @@ -196,7 +211,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) @@ -204,10 +219,12 @@ public class SignalAccount { .putPOJO("threadStore", threadStore) ; try { - fileChannel.position(0); - jsonProcessor.writeValue(Channels.newOutputStream(fileChannel), rootNode); - fileChannel.truncate(fileChannel.position()); - fileChannel.force(false); + synchronized (fileChannel) { + fileChannel.position(0); + jsonProcessor.writeValue(Channels.newOutputStream(fileChannel), rootNode); + fileChannel.truncate(fileChannel.position()); + fileChannel.force(false); + } } catch (Exception e) { System.err.println(String.format("Error saving file: %s", e.getMessage())); } @@ -262,6 +279,14 @@ public class SignalAccount { return username; } + public UUID getUuid() { + return uuid; + } + + public SignalServiceAddress getSelfAddress() { + return new SignalServiceAddress(uuid, username); + } + public int getDeviceId() { return deviceId; } @@ -278,6 +303,10 @@ public class SignalAccount { return registrationLockPin; } + public String getRegistrationLock() { + return null; // TODO implement KBS + } + public void setRegistrationLockPin(final String registrationLockPin) { this.registrationLockPin = registrationLockPin; } @@ -290,11 +319,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; }