# Changelog
## [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
### Changed
}
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 'net.sourceforge.argparse4j:argparse4j:0.8.1'
implementation 'com.github.hypfvieh:dbus-java:3.2.4'
if (receiptMessage.isReadReceipt()) {
System.out.println(" - Is read receipt");
}
+ if (receiptMessage.isViewedReceipt()) {
+ System.out.println(" - Is viewed receipt");
+ }
System.out.println(" - Timestamps:");
for (long timestamp : receiptMessage.getTimestamps()) {
System.out.println(" " + DateUtils.formatTimestamp(timestamp));
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()) {
final List<SignalServiceDataMessage.Preview> previews = message.getPreviews().get();
System.out.println("Previews:");
account.getDeviceId()),
userAgent,
groupsV2Operations,
+ ServiceConfig.AUTOMATIC_NETWORK_RETRY,
timer);
this.groupsV2Api = accountManager.getGroupsV2Api();
final KeyBackupService keyBackupService = ServiceConfig.createKeyBackupService(accountManager);
userAgent,
null,
timer,
- clientZkProfileOperations);
+ clientZkProfileOperations,
+ ServiceConfig.AUTOMATIC_NETWORK_RETRY);
this.account.setResolver(this::resolveSignalServiceAddress);
* if it's Optional.absent(), the avatar will be removed
*/
public void setProfile(String name, Optional<File> avatar) throws IOException {
+ // TODO
+ String about = null;
+ String aboutEmoji = null;
+
try (final StreamDetails streamDetails = avatar == null
? avatarStore.retrieveProfileAvatar(getSelfAddress())
: 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 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.
accountManager.setGcmId(Optional.absent());
+ accountManager.deleteAccount();
account.setRegistered(false);
account.save();
Optional.absent(),
clientZkProfileOperations,
executor,
- ServiceConfig.MAX_ENVELOPE_SIZE);
+ ServiceConfig.MAX_ENVELOPE_SIZE,
+ ServiceConfig.AUTOMATIC_NETWORK_RETRY);
}
private SignalProfile getRecipientProfile(
private Map<String, UUID> getRegisteredUsers(final Set<String> numbersMissingUuid) throws IOException {
try {
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);
}
}
if (e.getCause() instanceof org.whispersystems.libsignal.UntrustedIdentityException) {
org.whispersystems.libsignal.UntrustedIdentityException identityException = (org.whispersystems.libsignal.UntrustedIdentityException) e
.getCause();
- account.getSignalProtocolStore()
- .saveIdentity(resolveSignalServiceAddress(identityException.getName()),
- identityException.getUntrustedIdentity(),
- TrustLevel.UNTRUSTED);
+ final IdentityKey untrustedIdentity = identityException.getUntrustedIdentity();
+ if (untrustedIdentity != null) {
+ account.getSignalProtocolStore()
+ .saveIdentity(resolveSignalServiceAddress(identityException.getName()),
+ untrustedIdentity,
+ TrustLevel.UNTRUSTED);
+ }
throw identityException;
}
throw new AssertionError(e);
new DynamicCredentialsProvider(null, null, password, null, SignalServiceAddress.DEFAULT_DEVICE_ID),
userAgent,
groupsV2Operations,
+ ServiceConfig.AUTOMATIC_NETWORK_RETRY,
timer);
}
account.getUsername(),
account.getPassword(),
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);
this.pinHelper = new PinHelper(keyBackupService);
}
final static int PREKEY_MINIMUM_COUNT = 20;
final static int PREKEY_BATCH_SIZE = 100;
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 boolean AUTOMATIC_NETWORK_RETRY = true;
final static String CDS_MRENCLAVE = "c98e00a4e3ff977a56afefe7362a27e4961e4f19e211febfbb19b897e6b80b15";
package org.asamk.signal.manager.helper;
import org.asamk.signal.manager.util.PinHashing;
+import org.whispersystems.libsignal.InvalidKeyException;
import org.whispersystems.signalservice.api.KbsPinData;
import org.whispersystems.signalservice.api.KeyBackupService;
import org.whispersystems.signalservice.api.KeyBackupServicePinException;
throw new AssertionError("Null not expected");
}
return kbsData;
- } catch (UnauthenticatedResponseException e) {
+ } catch (UnauthenticatedResponseException | InvalidKeyException e) {
throw new IOException(e);
}
}
) throws IOException {
JsonNode node = jsonParser.getCodec().readTree(jsonParser);
- try {
- int localRegistrationId = node.get("registrationId").asInt();
- IdentityKeyPair identityKeyPair = new IdentityKeyPair(Base64.getDecoder()
- .decode(node.get("identityKey").asText()));
-
- JsonIdentityKeyStore keyStore = new JsonIdentityKeyStore(identityKeyPair, localRegistrationId);
-
- JsonNode trustedKeysNode = node.get("trustedKeys");
- if (trustedKeysNode.isArray()) {
- for (JsonNode trustedKey : trustedKeysNode) {
- String trustedKeyName = trustedKey.hasNonNull("name") ? trustedKey.get("name").asText() : null;
-
- if (UuidUtil.isUuid(trustedKeyName)) {
- // Ignore identities that were incorrectly created with UUIDs as name
- continue;
- }
-
- UUID uuid = trustedKey.hasNonNull("uuid") ? UuidUtil.parseOrNull(trustedKey.get("uuid")
- .asText()) : null;
- final SignalServiceAddress serviceAddress = uuid == null
- ? Utils.getSignalServiceAddressFromIdentifier(trustedKeyName)
- : new SignalServiceAddress(uuid, trustedKeyName);
- try {
- IdentityKey id = new IdentityKey(Base64.getDecoder()
- .decode(trustedKey.get("identityKey").asText()), 0);
- TrustLevel trustLevel = trustedKey.hasNonNull("trustLevel")
- ? TrustLevel.fromInt(trustedKey.get("trustLevel").asInt())
- : TrustLevel.TRUSTED_UNVERIFIED;
- Date added = trustedKey.hasNonNull("addedTimestamp") ? new Date(trustedKey.get(
- "addedTimestamp").asLong()) : new Date();
- keyStore.saveIdentity(serviceAddress, id, trustLevel, added);
- } catch (InvalidKeyException e) {
- logger.warn("Error while decoding key for {}: {}", trustedKeyName, e.getMessage());
- }
+ int localRegistrationId = node.get("registrationId").asInt();
+ IdentityKeyPair identityKeyPair = new IdentityKeyPair(Base64.getDecoder()
+ .decode(node.get("identityKey").asText()));
+
+ JsonIdentityKeyStore keyStore = new JsonIdentityKeyStore(identityKeyPair, localRegistrationId);
+
+ JsonNode trustedKeysNode = node.get("trustedKeys");
+ if (trustedKeysNode.isArray()) {
+ for (JsonNode trustedKey : trustedKeysNode) {
+ String trustedKeyName = trustedKey.hasNonNull("name") ? trustedKey.get("name").asText() : null;
+
+ if (UuidUtil.isUuid(trustedKeyName)) {
+ // Ignore identities that were incorrectly created with UUIDs as name
+ continue;
}
- }
- return keyStore;
- } catch (InvalidKeyException e) {
- throw new IOException(e);
+ UUID uuid = trustedKey.hasNonNull("uuid")
+ ? UuidUtil.parseOrNull(trustedKey.get("uuid").asText())
+ : null;
+ final SignalServiceAddress serviceAddress = uuid == null
+ ? Utils.getSignalServiceAddressFromIdentifier(trustedKeyName)
+ : new SignalServiceAddress(uuid, trustedKeyName);
+ try {
+ IdentityKey id = new IdentityKey(Base64.getDecoder()
+ .decode(trustedKey.get("identityKey").asText()), 0);
+ TrustLevel trustLevel = trustedKey.hasNonNull("trustLevel") ? TrustLevel.fromInt(trustedKey.get(
+ "trustLevel").asInt()) : TrustLevel.TRUSTED_UNVERIFIED;
+ Date added = trustedKey.hasNonNull("addedTimestamp") ? new Date(trustedKey.get("addedTimestamp")
+ .asLong()) : new Date();
+ keyStore.saveIdentity(serviceAddress, id, trustLevel, added);
+ } catch (InvalidKeyException e) {
+ logger.warn("Error while decoding key for {}: {}", trustedKeyName, e.getMessage());
+ }
+ }
}
+
+ return keyStore;
}
}