Update libsignal

This commit is contained in:
AsamK 2020-12-21 10:25:36 +01:00
parent b4311c7b76
commit 644aacf595
9 changed files with 72 additions and 46 deletions

View file

@ -1,6 +1,8 @@
# Changelog # Changelog
## [Unreleased] ## [Unreleased]
**Attention**: For all functionality an additional native library is now required: [libsignal-client](https://github.com/signalapp/libsignal-client/).
See https://github.com/AsamK/signal-cli/wiki/Provide-native-lib-for-libsignal for more information.
## [0.7.4] - 2021-01-19 ## [0.7.4] - 2021-01-19
### Changed ### Changed

View file

@ -17,7 +17,8 @@ repositories {
} }
dependencies { dependencies {
implementation 'com.github.turasa:signal-service-java:2.15.3_unofficial_17' implementation 'com.google.protobuf:protobuf-javalite:3.10.0'
implementation 'com.github.turasa:signal-service-java:2.15.3_unofficial_18'
implementation 'org.bouncycastle:bcprov-jdk15on:1.68' implementation 'org.bouncycastle:bcprov-jdk15on:1.68'
implementation 'net.sourceforge.argparse4j:argparse4j:0.8.1' implementation 'net.sourceforge.argparse4j:argparse4j:0.8.1'
implementation 'com.github.hypfvieh:dbus-java:3.2.4' implementation 'com.github.hypfvieh:dbus-java:3.2.4'

View file

@ -318,6 +318,9 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler {
if (receiptMessage.isReadReceipt()) { if (receiptMessage.isReadReceipt()) {
System.out.println(" - Is read receipt"); System.out.println(" - Is read receipt");
} }
if (receiptMessage.isViewedReceipt()) {
System.out.println(" - Is viewed receipt");
}
System.out.println(" - Timestamps:"); System.out.println(" - Timestamps:");
for (long timestamp : receiptMessage.getTimestamps()) { for (long timestamp : receiptMessage.getTimestamps()) {
System.out.println(" " + DateUtils.formatTimestamp(timestamp)); System.out.println(" " + DateUtils.formatTimestamp(timestamp));
@ -397,6 +400,11 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler {
System.out.println(" Has signed group change: " + groupInfo.hasSignedGroupChange()); System.out.println(" Has signed group change: " + groupInfo.hasSignedGroupChange());
} }
} }
if (message.getGroupCallUpdate().isPresent()) {
final SignalServiceDataMessage.GroupCallUpdate groupCallUpdate = message.getGroupCallUpdate().get();
System.out.println("Group call update:");
System.out.println(" - Era id: " + groupCallUpdate.getEraId());
}
if (message.getPreviews().isPresent()) { if (message.getPreviews().isPresent()) {
final List<SignalServiceDataMessage.Preview> previews = message.getPreviews().get(); final List<SignalServiceDataMessage.Preview> previews = message.getPreviews().get();
System.out.println("Previews:"); System.out.println("Previews:");

View file

@ -219,6 +219,7 @@ public class Manager implements Closeable {
account.getDeviceId()), account.getDeviceId()),
userAgent, userAgent,
groupsV2Operations, groupsV2Operations,
ServiceConfig.AUTOMATIC_NETWORK_RETRY,
timer); timer);
this.groupsV2Api = accountManager.getGroupsV2Api(); this.groupsV2Api = accountManager.getGroupsV2Api();
final KeyBackupService keyBackupService = ServiceConfig.createKeyBackupService(accountManager); final KeyBackupService keyBackupService = ServiceConfig.createKeyBackupService(accountManager);
@ -234,7 +235,8 @@ public class Manager implements Closeable {
userAgent, userAgent,
null, null,
timer, timer,
clientZkProfileOperations); clientZkProfileOperations,
ServiceConfig.AUTOMATIC_NETWORK_RETRY);
this.account.setResolver(this::resolveSignalServiceAddress); this.account.setResolver(this::resolveSignalServiceAddress);
@ -352,10 +354,19 @@ public class Manager implements Closeable {
* if it's Optional.absent(), the avatar will be removed * if it's Optional.absent(), the avatar will be removed
*/ */
public void setProfile(String name, Optional<File> avatar) throws IOException { public void setProfile(String name, Optional<File> avatar) throws IOException {
// TODO
String about = null;
String aboutEmoji = null;
try (final StreamDetails streamDetails = avatar == null try (final StreamDetails streamDetails = avatar == null
? avatarStore.retrieveProfileAvatar(getSelfAddress()) ? avatarStore.retrieveProfileAvatar(getSelfAddress())
: avatar.isPresent() ? Utils.createStreamDetailsFromFile(avatar.get()) : null) { : avatar.isPresent() ? Utils.createStreamDetailsFromFile(avatar.get()) : null) {
accountManager.setVersionedProfile(account.getUuid(), account.getProfileKey(), name, streamDetails); accountManager.setVersionedProfile(account.getUuid(),
account.getProfileKey(),
name,
about,
aboutEmoji,
streamDetails);
} }
if (avatar != null) { if (avatar != null) {
@ -378,6 +389,7 @@ public class Manager implements Closeable {
// If this is the master device, other users can't send messages to this number anymore. // If this is the master device, other users can't send messages to this number anymore.
// If this is a linked device, other users can still send messages, but this device doesn't receive them anymore. // If this is a linked device, other users can still send messages, but this device doesn't receive them anymore.
accountManager.setGcmId(Optional.absent()); accountManager.setGcmId(Optional.absent());
accountManager.deleteAccount();
account.setRegistered(false); account.setRegistered(false);
account.save(); account.save();
@ -499,7 +511,8 @@ public class Manager implements Closeable {
Optional.absent(), Optional.absent(),
clientZkProfileOperations, clientZkProfileOperations,
executor, executor,
ServiceConfig.MAX_ENVELOPE_SIZE); ServiceConfig.MAX_ENVELOPE_SIZE,
ServiceConfig.AUTOMATIC_NETWORK_RETRY);
} }
private SignalProfile getRecipientProfile( private SignalProfile getRecipientProfile(
@ -1250,7 +1263,7 @@ public class Manager implements Closeable {
private Map<String, UUID> getRegisteredUsers(final Set<String> numbersMissingUuid) throws IOException { private Map<String, UUID> getRegisteredUsers(final Set<String> numbersMissingUuid) throws IOException {
try { try {
return accountManager.getRegisteredUsers(getIasKeyStore(), numbersMissingUuid, CDS_MRENCLAVE); return accountManager.getRegisteredUsers(getIasKeyStore(), numbersMissingUuid, CDS_MRENCLAVE);
} catch (Quote.InvalidQuoteFormatException | UnauthenticatedQuoteException | SignatureException | UnauthenticatedResponseException e) { } catch (Quote.InvalidQuoteFormatException | UnauthenticatedQuoteException | SignatureException | UnauthenticatedResponseException | InvalidKeyException e) {
throw new IOException(e); throw new IOException(e);
} }
} }
@ -1391,10 +1404,13 @@ public class Manager implements Closeable {
if (e.getCause() instanceof org.whispersystems.libsignal.UntrustedIdentityException) { if (e.getCause() instanceof org.whispersystems.libsignal.UntrustedIdentityException) {
org.whispersystems.libsignal.UntrustedIdentityException identityException = (org.whispersystems.libsignal.UntrustedIdentityException) e org.whispersystems.libsignal.UntrustedIdentityException identityException = (org.whispersystems.libsignal.UntrustedIdentityException) e
.getCause(); .getCause();
account.getSignalProtocolStore() final IdentityKey untrustedIdentity = identityException.getUntrustedIdentity();
.saveIdentity(resolveSignalServiceAddress(identityException.getName()), if (untrustedIdentity != null) {
identityException.getUntrustedIdentity(), account.getSignalProtocolStore()
TrustLevel.UNTRUSTED); .saveIdentity(resolveSignalServiceAddress(identityException.getName()),
untrustedIdentity,
TrustLevel.UNTRUSTED);
}
throw identityException; throw identityException;
} }
throw new AssertionError(e); throw new AssertionError(e);

View file

@ -70,6 +70,7 @@ public class ProvisioningManager {
new DynamicCredentialsProvider(null, null, password, null, SignalServiceAddress.DEFAULT_DEVICE_ID), new DynamicCredentialsProvider(null, null, password, null, SignalServiceAddress.DEFAULT_DEVICE_ID),
userAgent, userAgent,
groupsV2Operations, groupsV2Operations,
ServiceConfig.AUTOMATIC_NETWORK_RETRY,
timer); timer);
} }

View file

@ -70,7 +70,7 @@ public class RegistrationManager implements Closeable {
account.getUsername(), account.getUsername(),
account.getPassword(), account.getPassword(),
account.getSignalingKey(), account.getSignalingKey(),
SignalServiceAddress.DEFAULT_DEVICE_ID), userAgent, null, timer); SignalServiceAddress.DEFAULT_DEVICE_ID), userAgent, null, ServiceConfig.AUTOMATIC_NETWORK_RETRY, timer);
final KeyBackupService keyBackupService = ServiceConfig.createKeyBackupService(accountManager); final KeyBackupService keyBackupService = ServiceConfig.createKeyBackupService(accountManager);
this.pinHelper = new PinHelper(keyBackupService); this.pinHelper = new PinHelper(keyBackupService);
} }

View file

@ -36,8 +36,9 @@ public class ServiceConfig {
final static int PREKEY_MINIMUM_COUNT = 20; final static int PREKEY_MINIMUM_COUNT = 20;
final static int PREKEY_BATCH_SIZE = 100; final static int PREKEY_BATCH_SIZE = 100;
final static int MAX_ATTACHMENT_SIZE = 150 * 1024 * 1024; final static int MAX_ATTACHMENT_SIZE = 150 * 1024 * 1024;
final static int MAX_ENVELOPE_SIZE = 0; final static long MAX_ENVELOPE_SIZE = 0;
final static long AVATAR_DOWNLOAD_FAILSAFE_MAX_SIZE = 10 * 1024 * 1024; final static long AVATAR_DOWNLOAD_FAILSAFE_MAX_SIZE = 10 * 1024 * 1024;
final static boolean AUTOMATIC_NETWORK_RETRY = true;
final static String CDS_MRENCLAVE = "c98e00a4e3ff977a56afefe7362a27e4961e4f19e211febfbb19b897e6b80b15"; final static String CDS_MRENCLAVE = "c98e00a4e3ff977a56afefe7362a27e4961e4f19e211febfbb19b897e6b80b15";

View file

@ -1,6 +1,7 @@
package org.asamk.signal.manager.helper; package org.asamk.signal.manager.helper;
import org.asamk.signal.manager.util.PinHashing; import org.asamk.signal.manager.util.PinHashing;
import org.whispersystems.libsignal.InvalidKeyException;
import org.whispersystems.signalservice.api.KbsPinData; import org.whispersystems.signalservice.api.KbsPinData;
import org.whispersystems.signalservice.api.KeyBackupService; import org.whispersystems.signalservice.api.KeyBackupService;
import org.whispersystems.signalservice.api.KeyBackupServicePinException; import org.whispersystems.signalservice.api.KeyBackupServicePinException;
@ -82,7 +83,7 @@ public class PinHelper {
throw new AssertionError("Null not expected"); throw new AssertionError("Null not expected");
} }
return kbsData; return kbsData;
} catch (UnauthenticatedResponseException e) { } catch (UnauthenticatedResponseException | InvalidKeyException e) {
throw new IOException(e); throw new IOException(e);
} }
} }

View file

@ -194,47 +194,43 @@ public class JsonIdentityKeyStore implements IdentityKeyStore {
) throws IOException { ) throws IOException {
JsonNode node = jsonParser.getCodec().readTree(jsonParser); JsonNode node = jsonParser.getCodec().readTree(jsonParser);
try { int localRegistrationId = node.get("registrationId").asInt();
int localRegistrationId = node.get("registrationId").asInt(); IdentityKeyPair identityKeyPair = new IdentityKeyPair(Base64.getDecoder()
IdentityKeyPair identityKeyPair = new IdentityKeyPair(Base64.getDecoder() .decode(node.get("identityKey").asText()));
.decode(node.get("identityKey").asText()));
JsonIdentityKeyStore keyStore = new JsonIdentityKeyStore(identityKeyPair, localRegistrationId); JsonIdentityKeyStore keyStore = new JsonIdentityKeyStore(identityKeyPair, localRegistrationId);
JsonNode trustedKeysNode = node.get("trustedKeys"); JsonNode trustedKeysNode = node.get("trustedKeys");
if (trustedKeysNode.isArray()) { if (trustedKeysNode.isArray()) {
for (JsonNode trustedKey : trustedKeysNode) { for (JsonNode trustedKey : trustedKeysNode) {
String trustedKeyName = trustedKey.hasNonNull("name") ? trustedKey.get("name").asText() : null; String trustedKeyName = trustedKey.hasNonNull("name") ? trustedKey.get("name").asText() : null;
if (UuidUtil.isUuid(trustedKeyName)) { if (UuidUtil.isUuid(trustedKeyName)) {
// Ignore identities that were incorrectly created with UUIDs as name // Ignore identities that were incorrectly created with UUIDs as name
continue; continue;
} }
UUID uuid = trustedKey.hasNonNull("uuid") ? UuidUtil.parseOrNull(trustedKey.get("uuid") UUID uuid = trustedKey.hasNonNull("uuid")
.asText()) : null; ? UuidUtil.parseOrNull(trustedKey.get("uuid").asText())
final SignalServiceAddress serviceAddress = uuid == null : null;
? Utils.getSignalServiceAddressFromIdentifier(trustedKeyName) final SignalServiceAddress serviceAddress = uuid == null
: new SignalServiceAddress(uuid, trustedKeyName); ? Utils.getSignalServiceAddressFromIdentifier(trustedKeyName)
try { : new SignalServiceAddress(uuid, trustedKeyName);
IdentityKey id = new IdentityKey(Base64.getDecoder() try {
.decode(trustedKey.get("identityKey").asText()), 0); IdentityKey id = new IdentityKey(Base64.getDecoder()
TrustLevel trustLevel = trustedKey.hasNonNull("trustLevel") .decode(trustedKey.get("identityKey").asText()), 0);
? TrustLevel.fromInt(trustedKey.get("trustLevel").asInt()) TrustLevel trustLevel = trustedKey.hasNonNull("trustLevel") ? TrustLevel.fromInt(trustedKey.get(
: TrustLevel.TRUSTED_UNVERIFIED; "trustLevel").asInt()) : TrustLevel.TRUSTED_UNVERIFIED;
Date added = trustedKey.hasNonNull("addedTimestamp") ? new Date(trustedKey.get( Date added = trustedKey.hasNonNull("addedTimestamp") ? new Date(trustedKey.get("addedTimestamp")
"addedTimestamp").asLong()) : new Date(); .asLong()) : new Date();
keyStore.saveIdentity(serviceAddress, id, trustLevel, added); keyStore.saveIdentity(serviceAddress, id, trustLevel, added);
} catch (InvalidKeyException e) { } catch (InvalidKeyException e) {
logger.warn("Error while decoding key for {}: {}", trustedKeyName, e.getMessage()); logger.warn("Error while decoding key for {}: {}", trustedKeyName, e.getMessage());
}
} }
} }
return keyStore;
} catch (InvalidKeyException e) {
throw new IOException(e);
} }
return keyStore;
} }
} }