From b2a32666e9d75dcc61288a78cfadaaade4867901 Mon Sep 17 00:00:00 2001 From: AsamK Date: Sat, 23 Sep 2023 11:51:50 +0200 Subject: [PATCH] Store serviceId in protocol stores as TEXT ServiceIds are no longer just UUIDs, they can now have prefixes like "PNI:" --- .../manager/storage/AccountDatabase.java | 147 +++++++++++++++++- .../signal/manager/storage/SignalAccount.java | 3 +- .../asamk/signal/manager/storage/Utils.java | 2 +- .../storage/identities/IdentityInfo.java | 12 +- .../storage/identities/IdentityKeyStore.java | 82 ++++++---- .../identities/LegacyIdentityKeyStore.java | 2 +- .../identities/SignalIdentityKeyStore.java | 14 +- .../protocol/LegacyJsonIdentityKeyStore.java | 2 +- .../protocol/LegacyJsonSessionStore.java | 2 +- .../storage/recipients/RecipientStore.java | 5 +- .../storage/sendLog/MessageSendLogStore.java | 20 +-- .../LegacySenderKeyRecordStore.java | 4 +- .../LegacySenderKeySharedStore.java | 2 +- .../senderKeys/SenderKeyRecordStore.java | 33 ++-- .../senderKeys/SenderKeySharedStore.java | 35 ++--- .../storage/sessions/LegacySessionStore.java | 2 +- .../storage/sessions/SessionStore.java | 64 ++++---- 17 files changed, 287 insertions(+), 144 deletions(-) diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/AccountDatabase.java b/lib/src/main/java/org/asamk/signal/manager/storage/AccountDatabase.java index f40e23ab..ee202d39 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/AccountDatabase.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/AccountDatabase.java @@ -2,6 +2,7 @@ package org.asamk.signal.manager.storage; import com.zaxxer.hikari.HikariDataSource; +import org.asamk.signal.manager.api.Pair; import org.asamk.signal.manager.storage.groups.GroupStore; import org.asamk.signal.manager.storage.identities.IdentityKeyStore; import org.asamk.signal.manager.storage.prekeys.KyberPreKeyStore; @@ -15,16 +16,21 @@ import org.asamk.signal.manager.storage.sessions.SessionStore; import org.asamk.signal.manager.storage.stickers.StickerStore; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.api.push.ServiceId.ACI; +import org.whispersystems.signalservice.api.util.UuidUtil; import java.io.File; import java.sql.Connection; import java.sql.SQLException; +import java.util.HashMap; +import java.util.Optional; +import java.util.UUID; public class AccountDatabase extends Database { private final static Logger logger = LoggerFactory.getLogger(AccountDatabase.class); - private static final long DATABASE_VERSION = 14; + private static final long DATABASE_VERSION = 15; private AccountDatabase(final HikariDataSource dataSource) { super(logger, DATABASE_VERSION, dataSource); @@ -346,7 +352,146 @@ public class AccountDatabase extends Database { """); } } + } + if (oldVersion < 15) { + logger.debug("Updating database: Store serviceId as TEXT"); + try (final var statement = connection.createStatement()) { + statement.executeUpdate(""" + CREATE TABLE tmp_mapping_table ( + uuid BLOB NOT NULL, + address TEXT NOT NULL + ) STRICT; + """); + + final var sql = ( + """ + SELECT r.uuid, r.pni + FROM recipient r + """ + ); + final var uuidAddressMapping = new HashMap(); + try (final var preparedStatement = connection.prepareStatement(sql)) { + try (var result = Utils.executeQueryForStream(preparedStatement, (resultSet) -> { + final var pni = Optional.ofNullable(resultSet.getBytes("pni")) + .map(UuidUtil::parseOrNull) + .map(ServiceId.PNI::from); + final var serviceIdUuid = Optional.ofNullable(resultSet.getBytes("uuid")) + .map(UuidUtil::parseOrNull); + final var serviceId = serviceIdUuid.isPresent() && pni.isPresent() && serviceIdUuid.get() + .equals(pni.get().getRawUuid()) + ? pni.map(p -> p) + : serviceIdUuid.map(ACI::from); + + return new Pair<>(serviceId, pni); + })) { + result.forEach(p -> { + final var serviceId = p.first(); + final var pni = p.second(); + if (serviceId.isPresent()) { + uuidAddressMapping.put(serviceId.get().getRawUuid(), serviceId.get()); + } + if (pni.isPresent()) { + uuidAddressMapping.put(pni.get().getRawUuid(), pni.get()); + } + }); + } + } + + final var insertSql = """ + INSERT INTO tmp_mapping_table (uuid, address) + VALUES (?,?) + """; + try (final var insertStatement = connection.prepareStatement(insertSql)) { + for (final var entry : uuidAddressMapping.entrySet()) { + final var uuid = entry.getKey(); + final var serviceId = entry.getValue(); + insertStatement.setBytes(1, UuidUtil.toByteArray(uuid)); + insertStatement.setString(2, serviceId.toString()); + insertStatement.execute(); + } + } + + statement.executeUpdate(""" + CREATE TABLE identity2 ( + _id INTEGER PRIMARY KEY, + address TEXT UNIQUE NOT NULL, + identity_key BLOB NOT NULL, + added_timestamp INTEGER NOT NULL, + trust_level INTEGER NOT NULL + ) STRICT; + INSERT INTO identity2 (_id, address, identity_key, added_timestamp, trust_level) + SELECT i._id, (SELECT t.address FROM tmp_mapping_table t WHERE t.uuid = i.uuid) address, i.identity_key, i.added_timestamp, i.trust_level + FROM identity i + WHERE address IS NOT NULL; + DROP TABLE identity; + ALTER TABLE identity2 RENAME TO identity; + CREATE TABLE message_send_log2 ( + _id INTEGER PRIMARY KEY, + content_id INTEGER NOT NULL REFERENCES message_send_log_content (_id) ON DELETE CASCADE, + address TEXT NOT NULL, + device_id INTEGER NOT NULL + ) STRICT; + INSERT INTO message_send_log2 (_id, content_id, address, device_id) + SELECT m._id, m.content_id, (SELECT t.address FROM tmp_mapping_table t WHERE t.uuid = m.uuid) address, m.device_id + FROM message_send_log m + WHERE address IS NOT NULL; + DROP INDEX msl_recipient_index; + DROP INDEX msl_content_index; + DROP TABLE message_send_log; + ALTER TABLE message_send_log2 RENAME TO message_send_log; + CREATE INDEX msl_recipient_index ON message_send_log (address, device_id, content_id); + CREATE INDEX msl_content_index ON message_send_log (content_id); + + CREATE TABLE sender_key2 ( + _id INTEGER PRIMARY KEY, + address TEXT NOT NULL, + device_id INTEGER NOT NULL, + distribution_id BLOB NOT NULL, + record BLOB NOT NULL, + created_timestamp INTEGER NOT NULL, + UNIQUE(address, device_id, distribution_id) + ) STRICT; + INSERT INTO sender_key2 (_id, address, device_id, distribution_id, record, created_timestamp) + SELECT s._id, (SELECT t.address FROM tmp_mapping_table t WHERE t.uuid = s.uuid) address, s.device_id, s.distribution_id, s.record, s.created_timestamp + FROM sender_key s + WHERE address IS NOT NULL; + DROP TABLE sender_key; + ALTER TABLE sender_key2 RENAME TO sender_key; + + CREATE TABLE sender_key_shared2 ( + _id INTEGER PRIMARY KEY, + address TEXT NOT NULL, + device_id INTEGER NOT NULL, + distribution_id BLOB NOT NULL, + timestamp INTEGER NOT NULL, + UNIQUE(address, device_id, distribution_id) + ) STRICT; + INSERT INTO sender_key_shared2 (_id, address, device_id, distribution_id, timestamp) + SELECT s._id, (SELECT t.address FROM tmp_mapping_table t WHERE t.uuid = s.uuid) address, s.device_id, s.distribution_id, s.timestamp + FROM sender_key_shared s + WHERE address IS NOT NULL; + DROP TABLE sender_key_shared; + ALTER TABLE sender_key_shared2 RENAME TO sender_key_shared; + + CREATE TABLE session2 ( + _id INTEGER PRIMARY KEY, + account_id_type INTEGER NOT NULL, + address TEXT NOT NULL, + device_id INTEGER NOT NULL, + record BLOB NOT NULL, + UNIQUE(account_id_type, address, device_id) + ) STRICT; + INSERT INTO session2 (_id, account_id_type, address, device_id, record) + SELECT s._id, s.account_id_type, (SELECT t.address FROM tmp_mapping_table t WHERE t.uuid = s.uuid) address, s.device_id, s.record + FROM session s + WHERE address IS NOT NULL; + DROP TABLE session; + ALTER TABLE session2 RENAME TO session; + + DROP TABLE tmp_mapping_table; + """); + } } } } diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/SignalAccount.java b/lib/src/main/java/org/asamk/signal/manager/storage/SignalAccount.java index 6ae2aaa4..1619eabd 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/SignalAccount.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/SignalAccount.java @@ -1841,8 +1841,7 @@ public class SignalAccount implements Closeable { public SignalIdentityKeyStore getIdentityKeyStore() { return getOrCreate(() -> identityKeyStore, - () -> identityKeyStore = new SignalIdentityKeyStore(getRecipientResolver(), - () -> identityKeyPair, + () -> identityKeyStore = new SignalIdentityKeyStore(() -> identityKeyPair, localRegistrationId, SignalAccount.this.getIdentityKeyStore())); } diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/Utils.java b/lib/src/main/java/org/asamk/signal/manager/storage/Utils.java index de98d7e5..fa2e8916 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/Utils.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/Utils.java @@ -56,7 +56,7 @@ public class Utils { return node; } - public static RecipientAddress getRecipientAddressFromIdentifier(final String identifier) { + public static RecipientAddress getRecipientAddressFromLegacyIdentifier(final String identifier) { if (UuidUtil.isUuid(identifier)) { return new RecipientAddress(ServiceId.parseOrThrow(identifier)); } else { diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/identities/IdentityInfo.java b/lib/src/main/java/org/asamk/signal/manager/storage/identities/IdentityInfo.java index 585ba945..d00d455c 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/identities/IdentityInfo.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/identities/IdentityInfo.java @@ -6,26 +6,26 @@ import org.whispersystems.signalservice.api.push.ServiceId; public class IdentityInfo { - private final String name; + private final String address; private final IdentityKey identityKey; private final TrustLevel trustLevel; private final long addedTimestamp; IdentityInfo( - final String name, IdentityKey identityKey, TrustLevel trustLevel, long addedTimestamp + final String address, IdentityKey identityKey, TrustLevel trustLevel, long addedTimestamp ) { - this.name = name; + this.address = address; this.identityKey = identityKey; this.trustLevel = trustLevel; this.addedTimestamp = addedTimestamp; } public ServiceId getServiceId() { - return ServiceId.parseOrThrow(name); + return ServiceId.parseOrThrow(address); } - public String getName() { - return name; + public String getAddress() { + return address; } public IdentityKey getIdentityKey() { diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/identities/IdentityKeyStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/identities/IdentityKeyStore.java index 2f8b4dac..3195df17 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/identities/IdentityKeyStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/identities/IdentityKeyStore.java @@ -37,7 +37,7 @@ public class IdentityKeyStore { statement.executeUpdate(""" CREATE TABLE identity ( _id INTEGER PRIMARY KEY, - uuid BLOB UNIQUE NOT NULL, + address TEXT UNIQUE NOT NULL, identity_key BLOB NOT NULL, added_timestamp INTEGER NOT NULL, trust_level INTEGER NOT NULL @@ -56,18 +56,22 @@ public class IdentityKeyStore { } public boolean saveIdentity(final ServiceId serviceId, final IdentityKey identityKey) { + return saveIdentity(serviceId.toString(), identityKey); + } + + boolean saveIdentity(final String address, final IdentityKey identityKey) { if (isRetryingDecryption) { return false; } try (final var connection = database.getConnection()) { - final var identityInfo = loadIdentity(connection, serviceId); + final var identityInfo = loadIdentity(connection, address); if (identityInfo != null && identityInfo.getIdentityKey().equals(identityKey)) { // Identity already exists, not updating the trust level - logger.trace("Not storing new identity for recipient {}, identity already stored", serviceId); + logger.trace("Not storing new identity for recipient {}, identity already stored", address); return false; } - saveNewIdentity(connection, serviceId, identityKey, identityInfo == null); + saveNewIdentity(connection, address, identityKey, identityInfo == null); return true; } catch (SQLException e) { throw new RuntimeException("Failed update identity store", e); @@ -80,7 +84,8 @@ public class IdentityKeyStore { public boolean setIdentityTrustLevel(ServiceId serviceId, IdentityKey identityKey, TrustLevel trustLevel) { try (final var connection = database.getConnection()) { - final var identityInfo = loadIdentity(connection, serviceId); + final var address = serviceId.toString(); + final var identityInfo = loadIdentity(connection, address); if (identityInfo == null) { logger.debug("Not updating trust level for recipient {}, identity not found", serviceId); return false; @@ -95,7 +100,7 @@ public class IdentityKeyStore { } logger.debug("Updating trust level for recipient {} with trust {}", serviceId, trustLevel); - final var newIdentityInfo = new IdentityInfo(serviceId, + final var newIdentityInfo = new IdentityInfo(address, identityKey, trustLevel, identityInfo.getDateAddedTimestamp()); @@ -107,31 +112,35 @@ public class IdentityKeyStore { } public boolean isTrustedIdentity(ServiceId serviceId, IdentityKey identityKey, Direction direction) { + return isTrustedIdentity(serviceId.toString(), identityKey, direction); + } + + public boolean isTrustedIdentity(String address, IdentityKey identityKey, Direction direction) { if (trustNewIdentity == TrustNewIdentity.ALWAYS) { return true; } try (final var connection = database.getConnection()) { // TODO implement possibility for different handling of incoming/outgoing trust decisions - var identityInfo = loadIdentity(connection, serviceId); + var identityInfo = loadIdentity(connection, address); if (identityInfo == null) { - logger.debug("Initial identity found for {}, saving.", serviceId); - saveNewIdentity(connection, serviceId, identityKey, true); - identityInfo = loadIdentity(connection, serviceId); + logger.debug("Initial identity found for {}, saving.", address); + saveNewIdentity(connection, address, identityKey, true); + identityInfo = loadIdentity(connection, address); } else if (!identityInfo.getIdentityKey().equals(identityKey)) { // Identity found, but different if (direction == Direction.SENDING) { - logger.debug("Changed identity found for {}, saving.", serviceId); - saveNewIdentity(connection, serviceId, identityKey, false); - identityInfo = loadIdentity(connection, serviceId); + logger.debug("Changed identity found for {}, saving.", address); + saveNewIdentity(connection, address, identityKey, false); + identityInfo = loadIdentity(connection, address); } else { - logger.trace("Trusting identity for {} for {}: {}", serviceId, direction, false); + logger.trace("Trusting identity for {} for {}: {}", address, direction, false); return false; } } final var isTrusted = identityInfo != null && identityInfo.isTrusted(); - logger.trace("Trusting identity for {} for {}: {}", serviceId, direction, isTrusted); + logger.trace("Trusting identity for {} for {}: {}", address, direction, isTrusted); return isTrusted; } catch (SQLException e) { throw new RuntimeException("Failed read from identity store", e); @@ -139,8 +148,12 @@ public class IdentityKeyStore { } public IdentityInfo getIdentityInfo(ServiceId serviceId) { + return getIdentityInfo(serviceId.toString()); + } + + public IdentityInfo getIdentityInfo(String address) { try (final var connection = database.getConnection()) { - return loadIdentity(connection, serviceId); + return loadIdentity(connection, address); } catch (SQLException e) { throw new RuntimeException("Failed read from identity store", e); } @@ -150,7 +163,7 @@ public class IdentityKeyStore { try (final var connection = database.getConnection()) { final var sql = ( """ - SELECT i.uuid, i.identity_key, i.added_timestamp, i.trust_level + SELECT i.address, i.identity_key, i.added_timestamp, i.trust_level FROM %s AS i """ ).formatted(TABLE_IDENTITY); @@ -166,7 +179,7 @@ public class IdentityKeyStore { public void deleteIdentity(final ServiceId serviceId) { try (final var connection = database.getConnection()) { - deleteIdentity(connection, serviceId); + deleteIdentity(connection, serviceId.toString()); } catch (SQLException e) { throw new RuntimeException("Failed update identity store", e); } @@ -188,34 +201,37 @@ public class IdentityKeyStore { } private IdentityInfo loadIdentity( - final Connection connection, final ServiceId serviceId + final Connection connection, final String address ) throws SQLException { final var sql = ( """ - SELECT i.uuid, i.identity_key, i.added_timestamp, i.trust_level + SELECT i.address, i.identity_key, i.added_timestamp, i.trust_level FROM %s AS i - WHERE i.uuid = ? + WHERE i.address = ? """ ).formatted(TABLE_IDENTITY); try (final var statement = connection.prepareStatement(sql)) { - statement.setBytes(1, serviceId.toByteArray()); + statement.setString(1, address); return Utils.executeQueryForOptional(statement, this::getIdentityInfoFromResultSet).orElse(null); } } private void saveNewIdentity( final Connection connection, - final ServiceId serviceId, + final String address, final IdentityKey identityKey, final boolean firstIdentity ) throws SQLException { final var trustLevel = trustNewIdentity == TrustNewIdentity.ALWAYS || ( trustNewIdentity == TrustNewIdentity.ON_FIRST_USE && firstIdentity ) ? TrustLevel.TRUSTED_UNVERIFIED : TrustLevel.UNTRUSTED; - logger.debug("Storing new identity for recipient {} with trust {}", serviceId, trustLevel); - final var newIdentityInfo = new IdentityInfo(serviceId, identityKey, trustLevel, System.currentTimeMillis()); + logger.debug("Storing new identity for recipient {} with trust {}", address, trustLevel); + final var newIdentityInfo = new IdentityInfo(address, identityKey, trustLevel, System.currentTimeMillis()); storeIdentity(connection, newIdentityInfo); - identityChanges.onNext(serviceId); + final var serviceId = ServiceId.parseOrNull(address); + if (serviceId != null) { + identityChanges.onNext(serviceId); + } } private void storeIdentity(final Connection connection, final IdentityInfo identityInfo) throws SQLException { @@ -225,12 +241,12 @@ public class IdentityKeyStore { identityInfo.getDateAddedTimestamp()); final var sql = ( """ - INSERT OR REPLACE INTO %s (uuid, identity_key, added_timestamp, trust_level) + INSERT OR REPLACE INTO %s (address, identity_key, added_timestamp, trust_level) VALUES (?, ?, ?, ?) """ ).formatted(TABLE_IDENTITY); try (final var statement = connection.prepareStatement(sql)) { - statement.setBytes(1, identityInfo.getServiceId().toByteArray()); + statement.setString(1, identityInfo.getAddress()); statement.setBytes(2, identityInfo.getIdentityKey().serialize()); statement.setLong(3, identityInfo.getDateAddedTimestamp()); statement.setInt(4, identityInfo.getTrustLevel().ordinal()); @@ -238,27 +254,27 @@ public class IdentityKeyStore { } } - private void deleteIdentity(final Connection connection, final ServiceId serviceId) throws SQLException { + private void deleteIdentity(final Connection connection, final String address) throws SQLException { final var sql = ( """ DELETE FROM %s AS i - WHERE i.uuid = ? + WHERE i.address = ? """ ).formatted(TABLE_IDENTITY); try (final var statement = connection.prepareStatement(sql)) { - statement.setBytes(1, serviceId.toByteArray()); + statement.setString(1, address); statement.executeUpdate(); } } private IdentityInfo getIdentityInfoFromResultSet(ResultSet resultSet) throws SQLException { try { - final var serviceId = ServiceId.parseOrThrow(resultSet.getBytes("uuid")); + final var address = resultSet.getString("address"); final var id = new IdentityKey(resultSet.getBytes("identity_key")); final var trustLevel = TrustLevel.fromInt(resultSet.getInt("trust_level")); final var added = resultSet.getLong("added_timestamp"); - return new IdentityInfo(serviceId, id, trustLevel, added); + return new IdentityInfo(address, id, trustLevel, added); } catch (InvalidKeyException e) { logger.warn("Failed to load identity key, resetting: {}", e.getMessage()); return null; diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/identities/LegacyIdentityKeyStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/identities/LegacyIdentityKeyStore.java index 88e23e75..27cb6f84 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/identities/LegacyIdentityKeyStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/identities/LegacyIdentityKeyStore.java @@ -84,7 +84,7 @@ public class LegacyIdentityKeyStore { var added = storage.addedTimestamp(); final var serviceId = address.serviceId().get(); - return new IdentityInfo(serviceId, id, trustLevel, added); + return new IdentityInfo(serviceId.toString(), id, trustLevel, added); } catch (IOException | InvalidKeyException e) { logger.warn("Failed to load identity key: {}", e.getMessage()); return null; diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/identities/SignalIdentityKeyStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/identities/SignalIdentityKeyStore.java index 66dfec4e..5a1a676e 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/identities/SignalIdentityKeyStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/identities/SignalIdentityKeyStore.java @@ -1,10 +1,8 @@ package org.asamk.signal.manager.storage.identities; -import org.asamk.signal.manager.storage.recipients.RecipientResolver; import org.signal.libsignal.protocol.IdentityKey; import org.signal.libsignal.protocol.IdentityKeyPair; import org.signal.libsignal.protocol.SignalProtocolAddress; -import org.whispersystems.signalservice.api.push.ServiceId; import java.util.function.Supplier; @@ -15,7 +13,6 @@ public class SignalIdentityKeyStore implements org.signal.libsignal.protocol.sta private final IdentityKeyStore identityKeyStore; public SignalIdentityKeyStore( - final RecipientResolver resolver, final Supplier identityKeyPairSupplier, final int localRegistrationId, final IdentityKeyStore identityKeyStore @@ -37,22 +34,17 @@ public class SignalIdentityKeyStore implements org.signal.libsignal.protocol.sta @Override public boolean saveIdentity(SignalProtocolAddress address, IdentityKey identityKey) { - final var serviceId = ServiceId.parseOrThrow(address.getName()); - - return identityKeyStore.saveIdentity(serviceId, identityKey); + return identityKeyStore.saveIdentity(address.getName(), identityKey); } @Override public boolean isTrustedIdentity(SignalProtocolAddress address, IdentityKey identityKey, Direction direction) { - final var serviceId = ServiceId.parseOrThrow(address.getName()); - - return identityKeyStore.isTrustedIdentity(serviceId, identityKey, direction); + return identityKeyStore.isTrustedIdentity(address.getName(), identityKey, direction); } @Override public IdentityKey getIdentity(SignalProtocolAddress address) { - final var serviceId = ServiceId.parseOrThrow(address.getName()); - final var identityInfo = identityKeyStore.getIdentityInfo(serviceId); + final var identityInfo = identityKeyStore.getIdentityInfo(address.getName()); return identityInfo == null ? null : identityInfo.getIdentityKey(); } } diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/protocol/LegacyJsonIdentityKeyStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/protocol/LegacyJsonIdentityKeyStore.java index 56986333..1e95eaff 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/protocol/LegacyJsonIdentityKeyStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/protocol/LegacyJsonIdentityKeyStore.java @@ -100,7 +100,7 @@ public class LegacyJsonIdentityKeyStore { ? UuidUtil.parseOrNull(trustedKey.get("uuid").asText()) : null; final var address = uuid == null - ? Utils.getRecipientAddressFromIdentifier(trustedKeyName) + ? Utils.getRecipientAddressFromLegacyIdentifier(trustedKeyName) : new RecipientAddress(ACI.from(uuid), trustedKeyName); try { var id = new IdentityKey(Base64.getDecoder().decode(trustedKey.get("identityKey").asText()), 0); diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/protocol/LegacyJsonSessionStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/protocol/LegacyJsonSessionStore.java index 73a85f76..ee675d78 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/protocol/LegacyJsonSessionStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/protocol/LegacyJsonSessionStore.java @@ -47,7 +47,7 @@ public class LegacyJsonSessionStore { var uuid = session.hasNonNull("uuid") ? UuidUtil.parseOrNull(session.get("uuid").asText()) : null; final var address = uuid == null - ? Utils.getRecipientAddressFromIdentifier(sessionName) + ? Utils.getRecipientAddressFromLegacyIdentifier(sessionName) : new RecipientAddress(ACI.from(uuid), sessionName); final var deviceId = session.get("deviceId").asInt(); final var record = Base64.getDecoder().decode(session.get("record").asText()); diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientStore.java index f19111b0..9ef734c7 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientStore.java @@ -151,8 +151,9 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re @Override public RecipientId resolveRecipient(final String identifier) { - if (UuidUtil.isUuid(identifier)) { - return resolveRecipient(ServiceId.parseOrThrow(identifier)); + final var serviceId = ServiceId.parseOrNull(identifier); + if (serviceId != null) { + return resolveRecipient(serviceId); } else { return resolveRecipientByNumber(identifier); } diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/sendLog/MessageSendLogStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/sendLog/MessageSendLogStore.java index 88ebe3b2..08b23933 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/sendLog/MessageSendLogStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/sendLog/MessageSendLogStore.java @@ -67,7 +67,7 @@ public class MessageSendLogStore implements AutoCloseable { CREATE TABLE message_send_log ( _id INTEGER PRIMARY KEY, content_id INTEGER NOT NULL REFERENCES message_send_log_content (_id) ON DELETE CASCADE, - uuid BLOB NOT NULL, + address TEXT NOT NULL, device_id INTEGER NOT NULL ) STRICT; CREATE TABLE message_send_log_content ( @@ -79,7 +79,7 @@ public class MessageSendLogStore implements AutoCloseable { urgent INTEGER NOT NULL ) STRICT; CREATE INDEX mslc_timestamp_index ON message_send_log_content (timestamp); - CREATE INDEX msl_recipient_index ON message_send_log (uuid, device_id, content_id); + CREATE INDEX msl_recipient_index ON message_send_log (address, device_id, content_id); CREATE INDEX msl_content_index ON message_send_log (content_id); """); } @@ -92,13 +92,13 @@ public class MessageSendLogStore implements AutoCloseable { SELECT group_id, content, content_hint, urgent FROM %s l INNER JOIN %s lc ON l.content_id = lc._id - WHERE l.uuid = ? AND l.device_id = ? AND lc.timestamp = ? + WHERE l.address = ? AND l.device_id = ? AND lc.timestamp = ? """.formatted(TABLE_MESSAGE_SEND_LOG, TABLE_MESSAGE_SEND_LOG_CONTENT); try (final var connection = database.getConnection()) { deleteOutdatedEntries(connection); try (final var statement = connection.prepareStatement(sql)) { - statement.setBytes(1, serviceId.toByteArray()); + statement.setString(1, serviceId.toString()); statement.setInt(2, deviceId); statement.setLong(3, timestamp); try (var result = Utils.executeQueryForStream(statement, this::getMessageSendLogEntryFromResultSet)) { @@ -202,13 +202,13 @@ public class MessageSendLogStore implements AutoCloseable { public void deleteEntryForRecipientNonGroup(long sentTimestamp, ServiceId serviceId) { final var sql = """ DELETE FROM %s AS lc - WHERE lc.timestamp = ? AND lc.group_id IS NULL AND lc._id IN (SELECT content_id FROM %s l WHERE l.uuid = ?) + WHERE lc.timestamp = ? AND lc.group_id IS NULL AND lc._id IN (SELECT content_id FROM %s l WHERE l.address = ?) """.formatted(TABLE_MESSAGE_SEND_LOG_CONTENT, TABLE_MESSAGE_SEND_LOG); try (final var connection = database.getConnection()) { connection.setAutoCommit(false); try (final var statement = connection.prepareStatement(sql)) { statement.setLong(1, sentTimestamp); - statement.setBytes(2, serviceId.toByteArray()); + statement.setString(2, serviceId.toString()); statement.executeUpdate(); } @@ -226,14 +226,14 @@ public class MessageSendLogStore implements AutoCloseable { public void deleteEntriesForRecipient(List sentTimestamps, ServiceId serviceId, int deviceId) { final var sql = """ DELETE FROM %s AS l - WHERE l.content_id IN (SELECT _id FROM %s lc WHERE lc.timestamp = ?) AND l.uuid = ? AND l.device_id = ? + WHERE l.content_id IN (SELECT _id FROM %s lc WHERE lc.timestamp = ?) AND l.address = ? AND l.device_id = ? """.formatted(TABLE_MESSAGE_SEND_LOG, TABLE_MESSAGE_SEND_LOG_CONTENT); try (final var connection = database.getConnection()) { connection.setAutoCommit(false); try (final var statement = connection.prepareStatement(sql)) { for (final var sentTimestamp : sentTimestamps) { statement.setLong(1, sentTimestamp); - statement.setBytes(2, serviceId.toByteArray()); + statement.setString(2, serviceId.toString()); statement.setInt(3, deviceId); statement.executeUpdate(); } @@ -342,13 +342,13 @@ public class MessageSendLogStore implements AutoCloseable { final long contentId, final List recipientDevices, final Connection connection ) throws SQLException { final var sql = """ - INSERT INTO %s (uuid, device_id, content_id) + INSERT INTO %s (address, device_id, content_id) VALUES (?,?,?) """.formatted(TABLE_MESSAGE_SEND_LOG); try (final var statement = connection.prepareStatement(sql)) { for (final var recipientDevice : recipientDevices) { for (final var deviceId : recipientDevice.deviceIds()) { - statement.setBytes(1, recipientDevice.serviceId().toByteArray()); + statement.setString(1, recipientDevice.serviceId().toString()); statement.setInt(2, deviceId); statement.setLong(3, contentId); statement.executeUpdate(); diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/senderKeys/LegacySenderKeyRecordStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/senderKeys/LegacySenderKeyRecordStore.java index d1794156..64928624 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/senderKeys/LegacySenderKeyRecordStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/senderKeys/LegacySenderKeyRecordStore.java @@ -41,7 +41,9 @@ public class LegacySenderKeyRecordStore { if (record == null || serviceId.isEmpty()) { return null; } - return new Pair<>(new SenderKeyRecordStore.Key(serviceId.get(), key.deviceId, key.distributionId), record); + return new Pair<>(new SenderKeyRecordStore.Key(serviceId.get().toString(), + key.deviceId, + key.distributionId), record); }).filter(Objects::nonNull).toList(); senderKeyStore.addLegacySenderKeys(senderKeys); diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/senderKeys/LegacySenderKeySharedStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/senderKeys/LegacySenderKeySharedStore.java index b46f8506..bbd05dea 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/senderKeys/LegacySenderKeySharedStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/senderKeys/LegacySenderKeySharedStore.java @@ -40,7 +40,7 @@ public class LegacySenderKeySharedStore { if (serviceId.isEmpty()) { continue; } - final var entry = new SenderKeySharedEntry(serviceId.get(), senderKey.deviceId); + final var entry = new SenderKeySharedEntry(serviceId.get().toString(), senderKey.deviceId); final var distributionId = DistributionId.from(senderKey.distributionId); var entries = sharedSenderKeys.get(distributionId); if (entries == null) { diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/senderKeys/SenderKeyRecordStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/senderKeys/SenderKeyRecordStore.java index 5e42a924..e321e9ea 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/senderKeys/SenderKeyRecordStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/senderKeys/SenderKeyRecordStore.java @@ -31,12 +31,12 @@ public class SenderKeyRecordStore implements SenderKeyStore { statement.executeUpdate(""" CREATE TABLE sender_key ( _id INTEGER PRIMARY KEY, - uuid BLOB NOT NULL, + address TEXT NOT NULL, device_id INTEGER NOT NULL, distribution_id BLOB NOT NULL, record BLOB NOT NULL, created_timestamp INTEGER NOT NULL, - UNIQUE(uuid, device_id, distribution_id) + UNIQUE(address, device_id, distribution_id) ) STRICT; """); } @@ -75,12 +75,12 @@ public class SenderKeyRecordStore implements SenderKeyStore { """ SELECT s.created_timestamp FROM %s AS s - WHERE s.uuid = ? AND s.device_id = ? AND s.distribution_id = ? + WHERE s.address = ? AND s.device_id = ? AND s.distribution_id = ? """ ).formatted(TABLE_SENDER_KEY); try (final var connection = database.getConnection()) { try (final var statement = connection.prepareStatement(sql)) { - statement.setBytes(1, selfServiceId.toByteArray()); + statement.setString(1, selfServiceId.toString()); statement.setInt(2, selfDeviceId); statement.setBytes(3, UuidUtil.toByteArray(distributionId)); return Utils.executeQueryForOptional(statement, res -> res.getLong("created_timestamp")).orElse(-1L); @@ -94,12 +94,12 @@ public class SenderKeyRecordStore implements SenderKeyStore { final var sql = ( """ DELETE FROM %s AS s - WHERE s.uuid = ? AND s.distribution_id = ? + WHERE s.address = ? AND s.distribution_id = ? """ ).formatted(TABLE_SENDER_KEY); try (final var connection = database.getConnection()) { try (final var statement = connection.prepareStatement(sql)) { - statement.setBytes(1, serviceId.toByteArray()); + statement.setString(1, serviceId.toString()); statement.setBytes(2, UuidUtil.toByteArray(distributionId)); statement.executeUpdate(); } @@ -145,8 +145,7 @@ public class SenderKeyRecordStore implements SenderKeyStore { } private Key getKey(final SignalProtocolAddress address, final UUID distributionId) { - final var serviceId = ServiceId.parseOrThrow(address.getName()); - return new Key(serviceId, address.getDeviceId(), distributionId); + return new Key(address.getName(), address.getDeviceId(), distributionId); } private SenderKeyRecord loadSenderKey(final Connection connection, final Key key) throws SQLException { @@ -154,11 +153,11 @@ public class SenderKeyRecordStore implements SenderKeyStore { """ SELECT s.record FROM %s AS s - WHERE s.uuid = ? AND s.device_id = ? AND s.distribution_id = ? + WHERE s.address = ? AND s.device_id = ? AND s.distribution_id = ? """ ).formatted(TABLE_SENDER_KEY); try (final var statement = connection.prepareStatement(sql)) { - statement.setBytes(1, key.serviceId().toByteArray()); + statement.setString(1, key.address()); statement.setInt(2, key.deviceId()); statement.setBytes(3, UuidUtil.toByteArray(key.distributionId())); return Utils.executeQueryForOptional(statement, this::getSenderKeyRecordFromResultSet).orElse(null); @@ -171,11 +170,11 @@ public class SenderKeyRecordStore implements SenderKeyStore { final var sqlUpdate = """ UPDATE %s SET record = ? - WHERE uuid = ? AND device_id = ? and distribution_id = ? + WHERE address = ? AND device_id = ? and distribution_id = ? """.formatted(TABLE_SENDER_KEY); try (final var statement = connection.prepareStatement(sqlUpdate)) { statement.setBytes(1, senderKeyRecord.serialize()); - statement.setBytes(2, key.serviceId().toByteArray()); + statement.setString(2, key.address()); statement.setLong(3, key.deviceId()); statement.setBytes(4, UuidUtil.toByteArray(key.distributionId())); final var rows = statement.executeUpdate(); @@ -187,12 +186,12 @@ public class SenderKeyRecordStore implements SenderKeyStore { // Record doesn't exist yet, creating a new one final var sqlInsert = ( """ - INSERT OR REPLACE INTO %s (uuid, device_id, distribution_id, record, created_timestamp) + INSERT OR REPLACE INTO %s (address, device_id, distribution_id, record, created_timestamp) VALUES (?, ?, ?, ?, ?) """ ).formatted(TABLE_SENDER_KEY); try (final var statement = connection.prepareStatement(sqlInsert)) { - statement.setBytes(1, key.serviceId().toByteArray()); + statement.setString(1, key.address()); statement.setInt(2, key.deviceId()); statement.setBytes(3, UuidUtil.toByteArray(key.distributionId())); statement.setBytes(4, senderKeyRecord.serialize()); @@ -205,11 +204,11 @@ public class SenderKeyRecordStore implements SenderKeyStore { final var sql = ( """ DELETE FROM %s AS s - WHERE s.uuid = ? + WHERE s.address = ? """ ).formatted(TABLE_SENDER_KEY); try (final var statement = connection.prepareStatement(sql)) { - statement.setBytes(1, serviceId.toByteArray()); + statement.setString(1, serviceId.toString()); statement.executeUpdate(); } } @@ -225,5 +224,5 @@ public class SenderKeyRecordStore implements SenderKeyStore { } } - record Key(ServiceId serviceId, int deviceId, UUID distributionId) {} + record Key(String address, int deviceId, UUID distributionId) {} } diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/senderKeys/SenderKeySharedStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/senderKeys/SenderKeySharedStore.java index 112c358c..0b17d479 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/senderKeys/SenderKeySharedStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/senderKeys/SenderKeySharedStore.java @@ -30,11 +30,11 @@ public class SenderKeySharedStore { statement.executeUpdate(""" CREATE TABLE sender_key_shared ( _id INTEGER PRIMARY KEY, - uuid BLOB NOT NULL, + address TEXT NOT NULL, device_id INTEGER NOT NULL, distribution_id BLOB NOT NULL, timestamp INTEGER NOT NULL, - UNIQUE(uuid, device_id, distribution_id) + UNIQUE(address, device_id, distribution_id) ) STRICT; """); } @@ -48,7 +48,7 @@ public class SenderKeySharedStore { try (final var connection = database.getConnection()) { final var sql = ( """ - SELECT s.uuid, s.device_id + SELECT s.address, s.device_id FROM %s AS s WHERE s.distribution_id = ? """ @@ -56,7 +56,7 @@ public class SenderKeySharedStore { try (final var statement = connection.prepareStatement(sql)) { statement.setBytes(1, UuidUtil.toByteArray(distributionId.asUuid())); return Utils.executeQueryForStream(statement, this::getSenderKeySharedEntryFromResultSet) - .map(k -> k.serviceId.toProtocolAddress(k.deviceId())) + .map(k -> new SignalProtocolAddress(k.address, k.deviceId())) .collect(Collectors.toSet()); } } catch (SQLException e) { @@ -68,7 +68,7 @@ public class SenderKeySharedStore { final DistributionId distributionId, final Collection addresses ) { final var newEntries = addresses.stream() - .map(a -> new SenderKeySharedEntry(ServiceId.parseOrThrow(a.getName()), a.getDeviceId())) + .map(a -> new SenderKeySharedEntry(a.getName(), a.getDeviceId())) .collect(Collectors.toSet()); try (final var connection = database.getConnection()) { @@ -82,8 +82,7 @@ public class SenderKeySharedStore { public void clearSenderKeySharedWith(final Collection addresses) { final var entriesToDelete = addresses.stream() - .filter(a -> UuidUtil.isUuid(a.getName())) - .map(a -> new SenderKeySharedEntry(ServiceId.parseOrThrow(a.getName()), a.getDeviceId())) + .map(a -> new SenderKeySharedEntry(a.getName(), a.getDeviceId())) .collect(Collectors.toSet()); try (final var connection = database.getConnection()) { @@ -91,12 +90,12 @@ public class SenderKeySharedStore { final var sql = ( """ DELETE FROM %s AS s - WHERE uuid = ? AND device_id = ? + WHERE address = ? AND device_id = ? """ ).formatted(TABLE_SENDER_KEY_SHARED); try (final var statement = connection.prepareStatement(sql)) { for (final var entry : entriesToDelete) { - statement.setBytes(1, entry.serviceId().toByteArray()); + statement.setString(1, entry.address()); statement.setInt(2, entry.deviceId()); statement.executeUpdate(); } @@ -127,11 +126,11 @@ public class SenderKeySharedStore { final var sql = ( """ DELETE FROM %s AS s - WHERE uuid = ? + WHERE address = ? """ ).formatted(TABLE_SENDER_KEY_SHARED); try (final var statement = connection.prepareStatement(sql)) { - statement.setBytes(1, serviceId.toByteArray()); + statement.setString(1, serviceId.toString()); statement.executeUpdate(); } } catch (SQLException e) { @@ -146,11 +145,11 @@ public class SenderKeySharedStore { final var sql = ( """ DELETE FROM %s AS s - WHERE uuid = ? AND device_id = ? AND distribution_id = ? + WHERE address = ? AND device_id = ? AND distribution_id = ? """ ).formatted(TABLE_SENDER_KEY_SHARED); try (final var statement = connection.prepareStatement(sql)) { - statement.setBytes(1, serviceId.toByteArray()); + statement.setString(1, serviceId.toString()); statement.setInt(2, deviceId); statement.setBytes(3, UuidUtil.toByteArray(distributionId.asUuid())); statement.executeUpdate(); @@ -197,13 +196,13 @@ public class SenderKeySharedStore { ) throws SQLException { final var sql = ( """ - INSERT OR REPLACE INTO %s (uuid, device_id, distribution_id, timestamp) + INSERT OR REPLACE INTO %s (address, device_id, distribution_id, timestamp) VALUES (?, ?, ?, ?) """ ).formatted(TABLE_SENDER_KEY_SHARED); try (final var statement = connection.prepareStatement(sql)) { for (final var entry : newEntries) { - statement.setBytes(1, entry.serviceId().toByteArray()); + statement.setString(1, entry.toString()); statement.setInt(2, entry.deviceId()); statement.setBytes(3, UuidUtil.toByteArray(distributionId.asUuid())); statement.setLong(4, System.currentTimeMillis()); @@ -213,10 +212,10 @@ public class SenderKeySharedStore { } private SenderKeySharedEntry getSenderKeySharedEntryFromResultSet(ResultSet resultSet) throws SQLException { - final var serviceId = ServiceId.parseOrThrow(resultSet.getBytes("uuid")); + final var address = resultSet.getString("address"); final var deviceId = resultSet.getInt("device_id"); - return new SenderKeySharedEntry(serviceId, deviceId); + return new SenderKeySharedEntry(address, deviceId); } - record SenderKeySharedEntry(ServiceId serviceId, int deviceId) {} + record SenderKeySharedEntry(String address, int deviceId) {} } diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/sessions/LegacySessionStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/sessions/LegacySessionStore.java index 71cd9231..517271da 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/sessions/LegacySessionStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/sessions/LegacySessionStore.java @@ -37,7 +37,7 @@ public class LegacySessionStore { if (record == null || serviceId.isEmpty()) { return null; } - return new Pair<>(new SessionStore.Key(serviceId.get(), key.deviceId()), record); + return new Pair<>(new SessionStore.Key(serviceId.get().toString(), key.deviceId()), record); }).filter(Objects::nonNull).toList(); sessionStore.addLegacySessions(sessions); deleteAllSessions(sessionsPath); diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/sessions/SessionStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/sessions/SessionStore.java index 3608e0c1..ebbd87aa 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/sessions/SessionStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/sessions/SessionStore.java @@ -6,15 +6,12 @@ import org.asamk.signal.manager.storage.Utils; import org.signal.libsignal.protocol.NoSessionException; import org.signal.libsignal.protocol.SignalProtocolAddress; import org.signal.libsignal.protocol.ecc.ECPublicKey; -import org.signal.libsignal.protocol.message.CiphertextMessage; import org.signal.libsignal.protocol.state.SessionRecord; -import org.signal.libsignal.protocol.util.Hex; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.whispersystems.signalservice.api.SignalServiceSessionStore; import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.api.push.ServiceIdType; -import org.whispersystems.signalservice.api.util.UuidUtil; import java.sql.Connection; import java.sql.ResultSet; @@ -45,10 +42,10 @@ public class SessionStore implements SignalServiceSessionStore { CREATE TABLE session ( _id INTEGER PRIMARY KEY, account_id_type INTEGER NOT NULL, - uuid BLOB NOT NULL, + address TEXT NOT NULL, device_id INTEGER NOT NULL, record BLOB NOT NULL, - UNIQUE(account_id_type, uuid, device_id) + UNIQUE(account_id_type, address, device_id) ) STRICT; """); } @@ -107,13 +104,13 @@ public class SessionStore implements SignalServiceSessionStore { """ SELECT s.device_id FROM %s AS s - WHERE s.account_id_type = ? AND s.uuid = ? AND s.device_id != 1 + WHERE s.account_id_type = ? AND s.address = ? AND s.device_id != 1 """ ).formatted(TABLE_SESSION); try (final var connection = database.getConnection()) { try (final var statement = connection.prepareStatement(sql)) { statement.setInt(1, accountIdType); - statement.setBytes(2, serviceId.toByteArray()); + statement.setString(2, serviceId.toString()); return Utils.executeQueryForStream(statement, res -> res.getInt("device_id")).toList(); } } catch (SQLException e) { @@ -122,7 +119,7 @@ public class SessionStore implements SignalServiceSessionStore { } public boolean isCurrentRatchetKey(ServiceId serviceId, int deviceId, ECPublicKey ratchetKey) { - final var key = new Key(serviceId, deviceId); + final var key = new Key(serviceId.toString(), deviceId); try (final var connection = database.getConnection()) { final var session = loadSession(connection, key); @@ -177,7 +174,7 @@ public class SessionStore implements SignalServiceSessionStore { public void deleteAllSessions(ServiceId serviceId) { try (final var connection = database.getConnection()) { - deleteAllSessions(connection, serviceId); + deleteAllSessions(connection, serviceId.toString()); } catch (SQLException e) { throw new RuntimeException("Failed update session store", e); } @@ -185,10 +182,6 @@ public class SessionStore implements SignalServiceSessionStore { @Override public void archiveSession(final SignalProtocolAddress address) { - if (!UuidUtil.isUuid(address.getName())) { - return; - } - final var key = getKey(address); try (final var connection = database.getConnection()) { @@ -207,15 +200,13 @@ public class SessionStore implements SignalServiceSessionStore { @Override public Set getAllAddressesWithActiveSessions(final List addressNames) { final var serviceIdsCommaSeparated = addressNames.stream() - .map(ServiceId::parseOrThrow) - .map(ServiceId::toByteArray) - .map(uuid -> "x'" + Hex.toStringCondensed(uuid) + "'") + .map(address -> "'" + address.replaceAll("'", "''") + "'") .collect(Collectors.joining(",")); final var sql = ( """ - SELECT s.uuid, s.device_id, s.record + SELECT s.address, s.device_id, s.record FROM %s AS s - WHERE s.account_id_type = ? AND s.uuid IN (%s) + WHERE s.account_id_type = ? AND s.address IN (%s) """ ).formatted(TABLE_SESSION, serviceIdsCommaSeparated); try (final var connection = database.getConnection()) { @@ -225,7 +216,7 @@ public class SessionStore implements SignalServiceSessionStore { res -> new Pair<>(getKeyFromResultSet(res), getSessionRecordFromResultSet(res))) .filter(pair -> isActive(pair.second())) .map(Pair::first) - .map(key -> key.serviceId().toProtocolAddress(key.deviceId())) + .map(key -> new SignalProtocolAddress(key.address(), key.deviceId())) .collect(Collectors.toSet()); } } catch (SQLException e) { @@ -236,7 +227,7 @@ public class SessionStore implements SignalServiceSessionStore { public void archiveAllSessions() { final var sql = ( """ - SELECT s.uuid, s.device_id, s.record + SELECT s.address, s.device_id, s.record FROM %s AS s WHERE s.account_id_type = ? """ @@ -264,9 +255,9 @@ public class SessionStore implements SignalServiceSessionStore { public void archiveSessions(final ServiceId serviceId) { final var sql = ( """ - SELECT s.uuid, s.device_id, s.record + SELECT s.address, s.device_id, s.record FROM %s AS s - WHERE s.account_id_type = ? AND s.uuid = ? + WHERE s.account_id_type = ? AND s.address = ? """ ).formatted(TABLE_SESSION); try (final var connection = database.getConnection()) { @@ -274,7 +265,7 @@ public class SessionStore implements SignalServiceSessionStore { final List> records; try (final var statement = connection.prepareStatement(sql)) { statement.setInt(1, accountIdType); - statement.setBytes(2, serviceId.toByteArray()); + statement.setString(2, serviceId.toString()); records = Utils.executeQueryForStream(statement, res -> new Pair<>(getKeyFromResultSet(res), getSessionRecordFromResultSet(res))) .filter(Objects::nonNull) @@ -306,8 +297,7 @@ public class SessionStore implements SignalServiceSessionStore { } private Key getKey(final SignalProtocolAddress address) { - final var serviceId = ServiceId.parseOrThrow(address.getName()); - return new Key(serviceId, address.getDeviceId()); + return new Key(address.getName(), address.getDeviceId()); } private SessionRecord loadSession(Connection connection, final Key key) throws SQLException { @@ -321,21 +311,21 @@ public class SessionStore implements SignalServiceSessionStore { """ SELECT s.record FROM %s AS s - WHERE s.account_id_type = ? AND s.uuid = ? AND s.device_id = ? + WHERE s.account_id_type = ? AND s.address = ? AND s.device_id = ? """ ).formatted(TABLE_SESSION); try (final var statement = connection.prepareStatement(sql)) { statement.setInt(1, accountIdType); - statement.setBytes(2, key.serviceId().toByteArray()); + statement.setString(2, key.address()); statement.setInt(3, key.deviceId()); return Utils.executeQueryForOptional(statement, this::getSessionRecordFromResultSet).orElse(null); } } private Key getKeyFromResultSet(ResultSet resultSet) throws SQLException { - final var serviceId = ServiceId.parseOrThrow(resultSet.getBytes("uuid")); + final var address = resultSet.getString("address"); final var deviceId = resultSet.getInt("device_id"); - return new Key(serviceId, deviceId); + return new Key(address, deviceId); } private SessionRecord getSessionRecordFromResultSet(ResultSet resultSet) throws SQLException { @@ -356,19 +346,19 @@ public class SessionStore implements SignalServiceSessionStore { } final var sql = """ - INSERT OR REPLACE INTO %s (account_id_type, uuid, device_id, record) + INSERT OR REPLACE INTO %s (account_id_type, address, device_id, record) VALUES (?, ?, ?, ?) """.formatted(TABLE_SESSION); try (final var statement = connection.prepareStatement(sql)) { statement.setInt(1, accountIdType); - statement.setBytes(2, key.serviceId().toByteArray()); + statement.setString(2, key.address()); statement.setInt(3, key.deviceId()); statement.setBytes(4, session.serialize()); statement.executeUpdate(); } } - private void deleteAllSessions(final Connection connection, final ServiceId serviceId) throws SQLException { + private void deleteAllSessions(final Connection connection, final String address) throws SQLException { synchronized (cachedSessions) { cachedSessions.clear(); } @@ -376,12 +366,12 @@ public class SessionStore implements SignalServiceSessionStore { final var sql = ( """ DELETE FROM %s AS s - WHERE s.account_id_type = ? AND s.uuid = ? + WHERE s.account_id_type = ? AND s.address = ? """ ).formatted(TABLE_SESSION); try (final var statement = connection.prepareStatement(sql)) { statement.setInt(1, accountIdType); - statement.setBytes(2, serviceId.toByteArray()); + statement.setString(2, address); statement.executeUpdate(); } } @@ -394,12 +384,12 @@ public class SessionStore implements SignalServiceSessionStore { final var sql = ( """ DELETE FROM %s AS s - WHERE s.account_id_type = ? AND s.uuid = ? AND s.device_id = ? + WHERE s.account_id_type = ? AND s.address = ? AND s.device_id = ? """ ).formatted(TABLE_SESSION); try (final var statement = connection.prepareStatement(sql)) { statement.setInt(1, accountIdType); - statement.setBytes(2, key.serviceId().toByteArray()); + statement.setString(2, key.address()); statement.setInt(3, key.deviceId()); statement.executeUpdate(); } @@ -409,5 +399,5 @@ public class SessionStore implements SignalServiceSessionStore { return record != null && record.hasSenderChain(); } - record Key(ServiceId serviceId, int deviceId) {} + record Key(String address, int deviceId) {} } -- 2.50.1