mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-23 10:05:15 +00:00
clean up signal service protocols
This commit is contained in:
parent
1db9ccdf27
commit
8c016b3802
@ -99,8 +99,6 @@ import org.session.libsignal.service.loki.api.SnodeAPI;
|
||||
import org.session.libsignal.service.loki.api.SwarmAPI;
|
||||
import org.session.libsignal.service.loki.api.fileserver.FileServerAPI;
|
||||
import org.session.libsignal.service.loki.api.opengroups.PublicChatAPI;
|
||||
import org.session.libsignal.service.loki.api.shelved.p2p.LokiP2PAPI;
|
||||
import org.session.libsignal.service.loki.api.shelved.p2p.LokiP2PAPIDelegate;
|
||||
import org.session.libsignal.service.loki.database.LokiAPIDatabaseProtocol;
|
||||
import org.session.libsignal.service.loki.utilities.mentions.MentionsManager;
|
||||
|
||||
@ -127,7 +125,7 @@ import static nl.komponents.kovenant.android.KovenantAndroid.stopKovenant;
|
||||
*
|
||||
* @author Moxie Marlinspike
|
||||
*/
|
||||
public class ApplicationContext extends MultiDexApplication implements DependencyInjector, DefaultLifecycleObserver, LokiP2PAPIDelegate {
|
||||
public class ApplicationContext extends MultiDexApplication implements DependencyInjector, DefaultLifecycleObserver {
|
||||
|
||||
private static final String TAG = ApplicationContext.class.getSimpleName();
|
||||
|
||||
@ -183,7 +181,6 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
SnodeAPI.Companion.configureIfNeeded(userPublicKey, apiDB, broadcaster);
|
||||
MentionsManager.Companion.configureIfNeeded(userPublicKey, threadDB, userDB);
|
||||
}
|
||||
setUpP2PAPIIfNeeded();
|
||||
PushNotificationAPI.Companion.configureIfNeeded(BuildConfig.DEBUG);
|
||||
setUpStorageAPIIfNeeded();
|
||||
resubmitProfilePictureIfNeeded();
|
||||
@ -423,22 +420,12 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
public boolean setUpStorageAPIIfNeeded() {
|
||||
String userPublicKey = TextSecurePreferences.getLocalNumber(this);
|
||||
if (userPublicKey == null || !IdentityKeyUtil.hasIdentityKey(this)) { return false; }
|
||||
boolean isDebugMode = BuildConfig.DEBUG;
|
||||
byte[] userPrivateKey = IdentityKeyUtil.getIdentityKeyPair(this).getPrivateKey().serialize();
|
||||
LokiAPIDatabaseProtocol apiDB = DatabaseFactory.getLokiAPIDatabase(this);
|
||||
FileServerAPI.Companion.configure(userPublicKey, userPrivateKey, apiDB);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setUpP2PAPIIfNeeded() {
|
||||
String hexEncodedPublicKey = TextSecurePreferences.getLocalNumber(this);
|
||||
if (hexEncodedPublicKey == null) { return; }
|
||||
LokiP2PAPI.Companion.configure(hexEncodedPublicKey, (isOnline, contactPublicKey) -> {
|
||||
// TODO: Implement
|
||||
return null;
|
||||
}, this);
|
||||
}
|
||||
|
||||
public void registerForFCMIfNeeded(Boolean force) {
|
||||
Context context = this;
|
||||
FirebaseInstanceId.getInstance().getInstanceId().addOnCompleteListener(task -> {
|
||||
@ -457,11 +444,6 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ping(@NotNull String s) {
|
||||
// TODO: Implement
|
||||
}
|
||||
|
||||
private void setUpPollingIfNeeded() {
|
||||
String userPublicKey = TextSecurePreferences.getLocalNumber(this);
|
||||
if (userPublicKey == null) return;
|
||||
|
@ -34,14 +34,12 @@ import org.thoughtcrime.securesms.transport.RetryLaterException;
|
||||
import org.thoughtcrime.securesms.transport.UndeliverableMessageException;
|
||||
import org.session.libsignal.libsignal.util.guava.Optional;
|
||||
import org.session.libsignal.service.api.SignalServiceMessageSender;
|
||||
import org.session.libsignal.service.api.crypto.UntrustedIdentityException;
|
||||
import org.session.libsignal.service.api.messages.SendMessageResult;
|
||||
import org.session.libsignal.service.api.messages.SignalServiceAttachment;
|
||||
import org.session.libsignal.service.api.messages.SignalServiceDataMessage;
|
||||
import org.session.libsignal.service.api.messages.SignalServiceDataMessage.Preview;
|
||||
import org.session.libsignal.service.api.messages.shared.SharedContact;
|
||||
import org.session.libsignal.service.api.push.SignalServiceAddress;
|
||||
import org.session.libsignal.service.api.push.exceptions.UnregisteredUserException;
|
||||
import org.session.libsignal.service.loki.api.SnodeAPI;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
@ -300,9 +298,6 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
|
||||
return isUnidentified;
|
||||
}
|
||||
}
|
||||
} catch (UnregisteredUserException e) {
|
||||
warn(TAG, e);
|
||||
throw new InsecureFallbackApprovalException(e);
|
||||
} catch (FileNotFoundException e) {
|
||||
warn(TAG, e);
|
||||
throw new UndeliverableMessageException(e);
|
||||
|
@ -30,7 +30,6 @@ import org.session.libsignal.service.api.crypto.UntrustedIdentityException;
|
||||
import org.session.libsignal.service.api.messages.SendMessageResult;
|
||||
import org.session.libsignal.service.api.messages.SignalServiceDataMessage;
|
||||
import org.session.libsignal.service.api.push.SignalServiceAddress;
|
||||
import org.session.libsignal.service.api.push.exceptions.UnregisteredUserException;
|
||||
import org.session.libsignal.service.loki.api.SnodeAPI;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -240,9 +239,6 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
|
||||
return isUnidentified;
|
||||
}
|
||||
}
|
||||
} catch (UnregisteredUserException e) {
|
||||
warn(TAG, "Failure", e);
|
||||
throw new InsecureFallbackApprovalException(e);
|
||||
} catch (IOException e) {
|
||||
warn(TAG, "Failure", e);
|
||||
throw new RetryLaterException(e);
|
||||
|
@ -191,7 +191,6 @@ class BackupRestoreViewModel(application: Application): AndroidViewModel(applica
|
||||
TextSecurePreferences.setHasSeenWelcomeScreen(context, true)
|
||||
val application = ApplicationContext.getInstance(context)
|
||||
application.setUpStorageAPIIfNeeded()
|
||||
application.setUpP2PAPIIfNeeded()
|
||||
|
||||
BackupRestoreResult.SUCCESS
|
||||
} catch (e: DatabaseDowngradeException) {
|
||||
|
@ -9,11 +9,11 @@ import android.widget.TextView.OnEditorActionListener
|
||||
import android.widget.Toast
|
||||
import kotlinx.android.synthetic.main.activity_display_name.*
|
||||
import network.loki.messenger.R
|
||||
import org.session.libsession.utilities.SSKEnvironment.ProfileManagerProtocol
|
||||
import org.thoughtcrime.securesms.BaseActionBarActivity
|
||||
import org.thoughtcrime.securesms.loki.utilities.push
|
||||
import org.thoughtcrime.securesms.loki.utilities.setUpActionBarSessionLogo
|
||||
import org.session.libsession.utilities.TextSecurePreferences
|
||||
import org.session.libsignal.service.api.crypto.ProfileCipher
|
||||
|
||||
class DisplayNameActivity : BaseActionBarActivity() {
|
||||
|
||||
@ -41,7 +41,7 @@ class DisplayNameActivity : BaseActionBarActivity() {
|
||||
if (displayName.isEmpty()) {
|
||||
return Toast.makeText(this, R.string.activity_display_name_display_name_missing_error, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
if (displayName.toByteArray().size > ProfileCipher.NAME_PADDED_LENGTH) {
|
||||
if (displayName.toByteArray().size > ProfileManagerProtocol.Companion.NAME_PADDED_LENGTH) {
|
||||
return Toast.makeText(this, R.string.activity_display_name_display_name_too_long_error, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
val inputMethodManager = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
|
||||
|
@ -154,7 +154,6 @@ class PNModeActivity : BaseActionBarActivity() {
|
||||
TextSecurePreferences.setIsUsingFCM(this, (selectedOptionView == fcmOptionView))
|
||||
val application = ApplicationContext.getInstance(this)
|
||||
application.setUpStorageAPIIfNeeded()
|
||||
application.setUpP2PAPIIfNeeded()
|
||||
val intent = Intent(this, HomeActivity::class.java)
|
||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
show(intent)
|
||||
|
@ -41,11 +41,11 @@ import org.thoughtcrime.securesms.mms.GlideApp
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
||||
import org.thoughtcrime.securesms.permissions.Permissions
|
||||
import org.session.libsession.messaging.avatars.AvatarHelper
|
||||
import org.session.libsession.utilities.SSKEnvironment.ProfileManagerProtocol
|
||||
import org.thoughtcrime.securesms.profiles.ProfileMediaConstraints
|
||||
import org.thoughtcrime.securesms.util.BitmapDecodingException
|
||||
import org.thoughtcrime.securesms.util.BitmapUtil
|
||||
import org.session.libsession.utilities.TextSecurePreferences
|
||||
import org.session.libsignal.service.api.crypto.ProfileCipher
|
||||
import org.session.libsignal.service.api.util.StreamDetails
|
||||
import org.session.libsignal.service.loki.api.fileserver.FileServerAPI
|
||||
import java.io.ByteArrayInputStream
|
||||
@ -225,7 +225,7 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
|
||||
Toast.makeText(this, R.string.activity_settings_display_name_missing_error, Toast.LENGTH_SHORT).show()
|
||||
return false
|
||||
}
|
||||
if (displayName.toByteArray().size > ProfileCipher.NAME_PADDED_LENGTH) {
|
||||
if (displayName.toByteArray().size > ProfileManagerProtocol.Companion.NAME_PADDED_LENGTH) {
|
||||
Toast.makeText(this, R.string.activity_settings_display_name_too_long_error, Toast.LENGTH_SHORT).show()
|
||||
return false
|
||||
}
|
||||
|
@ -24,6 +24,10 @@ class SSKEnvironment(
|
||||
}
|
||||
|
||||
interface ProfileManagerProtocol {
|
||||
companion object {
|
||||
const val NAME_PADDED_LENGTH = 26
|
||||
}
|
||||
|
||||
fun setDisplayName(context: Context, recipient: Recipient, displayName: String)
|
||||
fun setProfilePictureURL(context: Context, recipient: Recipient, profilePictureURL: String)
|
||||
fun setProfileKey(context: Context, recipient: Recipient, profileKey: ByteArray)
|
||||
|
@ -5,8 +5,6 @@
|
||||
*/
|
||||
package org.session.libsignal.libsignal;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class InvalidMessageException extends Exception {
|
||||
|
||||
public InvalidMessageException() {}
|
||||
@ -22,8 +20,4 @@ public class InvalidMessageException extends Exception {
|
||||
public InvalidMessageException(String detailMessage, Throwable throwable) {
|
||||
super(detailMessage, throwable);
|
||||
}
|
||||
|
||||
public InvalidMessageException(String detailMessage, List<Exception> exceptions) {
|
||||
super(detailMessage, exceptions.get(0));
|
||||
}
|
||||
}
|
||||
|
@ -7,13 +7,7 @@ package org.session.libsignal.libsignal.ecc;
|
||||
|
||||
import org.whispersystems.curve25519.Curve25519;
|
||||
import org.whispersystems.curve25519.Curve25519KeyPair;
|
||||
import org.whispersystems.curve25519.VrfSignatureVerificationFailedException;
|
||||
import org.session.libsignal.libsignal.InvalidKeyException;
|
||||
import org.session.libsignal.libsignal.ecc.DjbECPrivateKey;
|
||||
import org.session.libsignal.libsignal.ecc.DjbECPublicKey;
|
||||
import org.session.libsignal.libsignal.ecc.ECKeyPair;
|
||||
import org.session.libsignal.libsignal.ecc.ECPrivateKey;
|
||||
import org.session.libsignal.libsignal.ecc.ECPublicKey;
|
||||
|
||||
import static org.whispersystems.curve25519.Curve25519.BEST;
|
||||
|
||||
@ -21,10 +15,6 @@ public class Curve {
|
||||
|
||||
public static final int DJB_TYPE = 0x05;
|
||||
|
||||
public static boolean isNative() {
|
||||
return Curve25519.getInstance(BEST).isNative();
|
||||
}
|
||||
|
||||
public static ECKeyPair generateKeyPair() {
|
||||
Curve25519KeyPair keyPair = Curve25519.getInstance(BEST).generateKeyPair();
|
||||
return new ECKeyPair(new DjbECPublicKey(keyPair.getPublicKey()), new DjbECPrivateKey(keyPair.getPrivateKey()));
|
||||
@ -56,89 +46,4 @@ public class Curve {
|
||||
public static ECPrivateKey decodePrivatePoint(byte[] bytes) {
|
||||
return new DjbECPrivateKey(bytes);
|
||||
}
|
||||
|
||||
public static byte[] calculateAgreement(ECPublicKey publicKey, ECPrivateKey privateKey)
|
||||
throws InvalidKeyException
|
||||
{
|
||||
if (publicKey == null) {
|
||||
throw new InvalidKeyException("public value is null");
|
||||
}
|
||||
|
||||
if (privateKey == null) {
|
||||
throw new InvalidKeyException("private value is null");
|
||||
}
|
||||
|
||||
if (publicKey.getType() != privateKey.getType()) {
|
||||
throw new InvalidKeyException("Public and private keys must be of the same type!");
|
||||
}
|
||||
|
||||
if (publicKey.getType() == DJB_TYPE) {
|
||||
return Curve25519.getInstance(BEST)
|
||||
.calculateAgreement(((DjbECPublicKey) publicKey).getPublicKey(),
|
||||
((DjbECPrivateKey) privateKey).getPrivateKey());
|
||||
} else {
|
||||
throw new InvalidKeyException("Unknown type: " + publicKey.getType());
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean verifySignature(ECPublicKey signingKey, byte[] message, byte[] signature)
|
||||
throws InvalidKeyException
|
||||
{
|
||||
if (signingKey == null || message == null || signature == null) {
|
||||
throw new InvalidKeyException("Values must not be null");
|
||||
}
|
||||
|
||||
if (signingKey.getType() == DJB_TYPE) {
|
||||
return Curve25519.getInstance(BEST)
|
||||
.verifySignature(((DjbECPublicKey) signingKey).getPublicKey(), message, signature);
|
||||
} else {
|
||||
throw new InvalidKeyException("Unknown type: " + signingKey.getType());
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] calculateSignature(ECPrivateKey signingKey, byte[] message)
|
||||
throws InvalidKeyException
|
||||
{
|
||||
if (signingKey == null || message == null) {
|
||||
throw new InvalidKeyException("Values must not be null");
|
||||
}
|
||||
|
||||
if (signingKey.getType() == DJB_TYPE) {
|
||||
return Curve25519.getInstance(BEST)
|
||||
.calculateSignature(((DjbECPrivateKey) signingKey).getPrivateKey(), message);
|
||||
} else {
|
||||
throw new InvalidKeyException("Unknown type: " + signingKey.getType());
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] calculateVrfSignature(ECPrivateKey signingKey, byte[] message)
|
||||
throws InvalidKeyException
|
||||
{
|
||||
if (signingKey == null || message == null) {
|
||||
throw new InvalidKeyException("Values must not be null");
|
||||
}
|
||||
|
||||
if (signingKey.getType() == DJB_TYPE) {
|
||||
return Curve25519.getInstance(BEST)
|
||||
.calculateVrfSignature(((DjbECPrivateKey)signingKey).getPrivateKey(), message);
|
||||
} else {
|
||||
throw new InvalidKeyException("Unknown type: " + signingKey.getType());
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] verifyVrfSignature(ECPublicKey signingKey, byte[] message, byte[] signature)
|
||||
throws InvalidKeyException, VrfSignatureVerificationFailedException
|
||||
{
|
||||
if (signingKey == null || message == null || signature == null) {
|
||||
throw new InvalidKeyException("Values must not be null");
|
||||
}
|
||||
|
||||
if (signingKey.getType() == DJB_TYPE) {
|
||||
return Curve25519.getInstance(BEST)
|
||||
.verifyVrfSignature(((DjbECPublicKey) signingKey).getPublicKey(), message, signature);
|
||||
} else {
|
||||
throw new InvalidKeyException("Unknown type: " + signingKey.getType());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -5,9 +5,6 @@
|
||||
*/
|
||||
package org.session.libsignal.libsignal.ecc;
|
||||
|
||||
import org.session.libsignal.libsignal.ecc.ECPrivateKey;
|
||||
import org.session.libsignal.libsignal.ecc.ECPublicKey;
|
||||
|
||||
public class ECKeyPair {
|
||||
|
||||
private final ECPublicKey publicKey;
|
||||
|
@ -1,18 +0,0 @@
|
||||
package org.session.libsignal.libsignal.util;
|
||||
|
||||
public abstract class ByteArrayComparator {
|
||||
|
||||
protected int compare(byte[] left, byte[] right) {
|
||||
for (int i = 0, j = 0; i < left.length && j < right.length; i++, j++) {
|
||||
int a = (left[i] & 0xff);
|
||||
int b = (right[j] & 0xff);
|
||||
|
||||
if (a != b) {
|
||||
return a - b;
|
||||
}
|
||||
}
|
||||
|
||||
return left.length - right.length;
|
||||
}
|
||||
|
||||
}
|
@ -5,12 +5,6 @@
|
||||
*/
|
||||
package org.session.libsignal.libsignal.util;
|
||||
|
||||
import org.session.libsignal.libsignal.IdentityKey;
|
||||
import org.session.libsignal.libsignal.IdentityKeyPair;
|
||||
import org.session.libsignal.libsignal.InvalidKeyException;
|
||||
import org.session.libsignal.libsignal.ecc.Curve;
|
||||
import org.session.libsignal.libsignal.ecc.ECKeyPair;
|
||||
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
|
||||
|
@ -16,14 +16,8 @@
|
||||
|
||||
package org.session.libsignal.libsignal.util.guava;
|
||||
|
||||
import org.session.libsignal.libsignal.util.guava.Function;
|
||||
import org.session.libsignal.libsignal.util.guava.Optional;
|
||||
import org.session.libsignal.libsignal.util.guava.Supplier;
|
||||
|
||||
import static org.session.libsignal.libsignal.util.guava.Preconditions.checkNotNull;
|
||||
|
||||
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -16,12 +16,9 @@
|
||||
|
||||
package org.session.libsignal.libsignal.util.guava;
|
||||
|
||||
import org.session.libsignal.libsignal.util.guava.Supplier;
|
||||
|
||||
import static org.session.libsignal.libsignal.util.guava.Preconditions.checkNotNull;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
|
@ -26,7 +26,6 @@ import org.session.libsignal.service.api.messages.SignalServiceTypingMessage;
|
||||
import org.session.libsignal.service.api.messages.shared.SharedContact;
|
||||
import org.session.libsignal.service.api.push.SignalServiceAddress;
|
||||
import org.session.libsignal.service.api.push.exceptions.PushNetworkException;
|
||||
import org.session.libsignal.service.api.push.exceptions.UnregisteredUserException;
|
||||
import org.session.libsignal.service.internal.crypto.PaddingInputStream;
|
||||
import org.session.libsignal.service.internal.push.OutgoingPushMessage;
|
||||
import org.session.libsignal.service.internal.push.OutgoingPushMessageList;
|
||||
@ -486,7 +485,6 @@ public class SignalServiceMessageSender {
|
||||
int ttl,
|
||||
boolean isClosedGroup,
|
||||
boolean notifyPNServer)
|
||||
throws IOException
|
||||
{
|
||||
List<SendMessageResult> results = new LinkedList<>();
|
||||
Iterator<SignalServiceAddress> recipientIterator = recipients.iterator();
|
||||
@ -494,17 +492,8 @@ public class SignalServiceMessageSender {
|
||||
|
||||
while (recipientIterator.hasNext()) {
|
||||
SignalServiceAddress recipient = recipientIterator.next();
|
||||
|
||||
try {
|
||||
SendMessageResult result = sendMessage(messageID, recipient, unidentifiedAccessIterator.next(), timestamp, content, online, ttl, true, isClosedGroup, notifyPNServer, Optional.absent());
|
||||
results.add(result);
|
||||
} catch (UnregisteredUserException e) {
|
||||
Log.w(TAG, e);
|
||||
results.add(SendMessageResult.unregisteredFailure(recipient));
|
||||
} catch (PushNetworkException e) {
|
||||
Log.w(TAG, e);
|
||||
results.add(SendMessageResult.networkFailure(recipient));
|
||||
}
|
||||
SendMessageResult result = sendMessage(messageID, recipient, unidentifiedAccessIterator.next(), timestamp, content, online, ttl, true, isClosedGroup, notifyPNServer, Optional.absent());
|
||||
results.add(result);
|
||||
}
|
||||
|
||||
return results;
|
||||
@ -534,7 +523,6 @@ public class SignalServiceMessageSender {
|
||||
boolean isClosedGroup,
|
||||
boolean notifyPNServer,
|
||||
Optional<String> syncTarget)
|
||||
throws IOException
|
||||
{
|
||||
boolean isSelfSend = syncTarget.isPresent() && !syncTarget.get().isEmpty();
|
||||
long threadID;
|
||||
@ -544,16 +532,10 @@ public class SignalServiceMessageSender {
|
||||
threadID = threadDatabase.getThreadID(recipient.getNumber());
|
||||
}
|
||||
PublicChat publicChat = threadDatabase.getPublicChat(threadID);
|
||||
try {
|
||||
if (publicChat != null) {
|
||||
return sendMessageToPublicChat(messageID, recipient, timestamp, content, publicChat);
|
||||
} else {
|
||||
return sendMessageToPrivateChat(messageID, recipient, unidentifiedAccess, timestamp, content, online, ttl, useFallbackEncryption, isClosedGroup, notifyPNServer, syncTarget);
|
||||
}
|
||||
} catch (PushNetworkException e) {
|
||||
return SendMessageResult.networkFailure(recipient);
|
||||
} catch (UntrustedIdentityException e) {
|
||||
return SendMessageResult.identityFailure(recipient, e.getIdentityKey());
|
||||
if (publicChat != null) {
|
||||
return sendMessageToPublicChat(messageID, recipient, timestamp, content, publicChat);
|
||||
} else {
|
||||
return sendMessageToPrivateChat(messageID, recipient, unidentifiedAccess, timestamp, content, online, ttl, useFallbackEncryption, isClosedGroup, notifyPNServer, syncTarget);
|
||||
}
|
||||
}
|
||||
|
||||
@ -659,7 +641,6 @@ public class SignalServiceMessageSender {
|
||||
boolean isClosedGroup,
|
||||
final boolean notifyPNServer,
|
||||
Optional<String> syncTarget)
|
||||
throws IOException, UntrustedIdentityException
|
||||
{
|
||||
final SettableFuture<?>[] future = { new SettableFuture<Unit>() };
|
||||
OutgoingPushMessageList messages = getSessionProtocolEncryptedMessage(recipient, timestamp, content);
|
||||
@ -840,9 +821,4 @@ public class SignalServiceMessageSender {
|
||||
|
||||
return new OutgoingPushMessageList(publicKey, timestamp, messages, false);
|
||||
}
|
||||
|
||||
public static interface EventListener {
|
||||
|
||||
public void onSecurityEvent(SignalServiceAddress address);
|
||||
}
|
||||
}
|
||||
|
@ -8,11 +8,9 @@ package org.session.libsignal.service.api.crypto;
|
||||
|
||||
import org.session.libsignal.libsignal.InvalidMacException;
|
||||
import org.session.libsignal.libsignal.InvalidMessageException;
|
||||
import org.session.libsignal.libsignal.kdf.HKDFv3;
|
||||
import org.session.libsignal.service.internal.util.ContentLengthInputStream;
|
||||
import org.session.libsignal.service.internal.util.Util;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FilterInputStream;
|
||||
@ -86,32 +84,6 @@ public class AttachmentCipherInputStream extends FilterInputStream {
|
||||
}
|
||||
}
|
||||
|
||||
public static InputStream createForStickerData(byte[] data, byte[] packKey)
|
||||
throws InvalidMessageException, IOException
|
||||
{
|
||||
try {
|
||||
byte[] combinedKeyMaterial = new HKDFv3().deriveSecrets(packKey, "Sticker Pack".getBytes(), 64);
|
||||
byte[][] parts = Util.split(combinedKeyMaterial, CIPHER_KEY_SIZE, MAC_KEY_SIZE);
|
||||
Mac mac = Mac.getInstance("HmacSHA256");
|
||||
mac.init(new SecretKeySpec(parts[1], "HmacSHA256"));
|
||||
|
||||
if (data.length <= BLOCK_SIZE + mac.getMacLength()) {
|
||||
throw new InvalidMessageException("Message shorter than crypto overhead!");
|
||||
}
|
||||
|
||||
InputStream inputStream = new ByteArrayInputStream(data);
|
||||
verifyMac(inputStream, data.length, mac, null);
|
||||
|
||||
return new AttachmentCipherInputStream(new ByteArrayInputStream(data), parts[0], data.length - BLOCK_SIZE - mac.getMacLength());
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new AssertionError(e);
|
||||
} catch (InvalidKeyException e) {
|
||||
throw new AssertionError(e);
|
||||
} catch (InvalidMacException e) {
|
||||
throw new InvalidMessageException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private AttachmentCipherInputStream(InputStream inputStream, byte[] cipherKey, long totalDataSize)
|
||||
throws IOException
|
||||
{
|
||||
|
@ -1,123 +0,0 @@
|
||||
package org.session.libsignal.service.api.crypto;
|
||||
|
||||
|
||||
import org.session.libsignal.libsignal.util.ByteUtil;
|
||||
import org.session.libsignal.service.api.crypto.InvalidCiphertextException;
|
||||
import org.session.libsignal.service.api.crypto.UnidentifiedAccess;
|
||||
import org.session.libsignal.service.internal.util.Util;
|
||||
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import javax.crypto.spec.GCMParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
public class ProfileCipher {
|
||||
|
||||
public static final int NAME_PADDED_LENGTH = 26;
|
||||
|
||||
private final byte[] key;
|
||||
|
||||
public ProfileCipher(byte[] key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public byte[] encryptName(byte[] input, int paddedLength) {
|
||||
try {
|
||||
byte[] inputPadded = new byte[paddedLength];
|
||||
|
||||
if (input.length > inputPadded.length) {
|
||||
throw new IllegalArgumentException("Input is too long: " + new String(input));
|
||||
}
|
||||
|
||||
System.arraycopy(input, 0, inputPadded, 0, input.length);
|
||||
|
||||
byte[] nonce = Util.getSecretBytes(12);
|
||||
|
||||
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"), new GCMParameterSpec(128, nonce));
|
||||
|
||||
return ByteUtil.combine(nonce, cipher.doFinal(inputPadded));
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new AssertionError(e);
|
||||
} catch (InvalidAlgorithmParameterException e) {
|
||||
throw new AssertionError(e);
|
||||
} catch (BadPaddingException e) {
|
||||
throw new AssertionError(e);
|
||||
} catch (NoSuchPaddingException e) {
|
||||
throw new AssertionError(e);
|
||||
} catch (IllegalBlockSizeException e) {
|
||||
throw new AssertionError(e);
|
||||
} catch (InvalidKeyException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] decryptName(byte[] input) throws InvalidCiphertextException {
|
||||
try {
|
||||
if (input.length < 12 + 16 + 1) {
|
||||
throw new InvalidCiphertextException("Too short: " + input.length);
|
||||
}
|
||||
|
||||
byte[] nonce = new byte[12];
|
||||
System.arraycopy(input, 0, nonce, 0, nonce.length);
|
||||
|
||||
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
|
||||
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"), new GCMParameterSpec(128, nonce));
|
||||
|
||||
byte[] paddedPlaintext = cipher.doFinal(input, nonce.length, input.length - nonce.length);
|
||||
int plaintextLength = 0;
|
||||
|
||||
for (int i=paddedPlaintext.length-1;i>=0;i--) {
|
||||
if (paddedPlaintext[i] != (byte)0x00) {
|
||||
plaintextLength = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
byte[] plaintext = new byte[plaintextLength];
|
||||
System.arraycopy(paddedPlaintext, 0, plaintext, 0, plaintextLength);
|
||||
|
||||
return plaintext;
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new AssertionError(e);
|
||||
} catch (InvalidAlgorithmParameterException e) {
|
||||
throw new AssertionError(e);
|
||||
} catch (NoSuchPaddingException e) {
|
||||
throw new AssertionError(e);
|
||||
} catch (IllegalBlockSizeException e) {
|
||||
throw new AssertionError(e);
|
||||
} catch (InvalidKeyException e) {
|
||||
throw new InvalidCiphertextException(e);
|
||||
} catch (BadPaddingException e) {
|
||||
throw new InvalidCiphertextException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean verifyUnidentifiedAccess(byte[] theirUnidentifiedAccessVerifier) {
|
||||
try {
|
||||
if (theirUnidentifiedAccessVerifier == null || theirUnidentifiedAccessVerifier.length == 0) return false;
|
||||
|
||||
byte[] unidentifiedAccessKey = UnidentifiedAccess.deriveAccessKeyFrom(key);
|
||||
|
||||
Mac mac = Mac.getInstance("HmacSHA256");
|
||||
mac.init(new SecretKeySpec(unidentifiedAccessKey, "HmacSHA256"));
|
||||
|
||||
byte[] ourUnidentifiedAccessVerifier = mac.doFinal(new byte[32]);
|
||||
|
||||
return MessageDigest.isEqual(theirUnidentifiedAccessVerifier, ourUnidentifiedAccessVerifier);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new AssertionError(e);
|
||||
} catch (InvalidKeyException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -19,10 +19,6 @@ public class UntrustedIdentityException extends Exception {
|
||||
this.identityKey = identityKey;
|
||||
}
|
||||
|
||||
public UntrustedIdentityException(UntrustedIdentityException e) {
|
||||
this(e.getMessage(), e.getE164Number(), e.getIdentityKey());
|
||||
}
|
||||
|
||||
public IdentityKey getIdentityKey() {
|
||||
return identityKey;
|
||||
}
|
||||
|
@ -1,23 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2014-2016 Open Whisper Systems
|
||||
*
|
||||
* Licensed according to the LICENSE file in this repository.
|
||||
*/
|
||||
|
||||
package org.session.libsignal.service.api.push.exceptions;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class UnregisteredUserException extends IOException {
|
||||
|
||||
private final String e164number;
|
||||
|
||||
public UnregisteredUserException(String e164number, Exception exception) {
|
||||
super(exception);
|
||||
this.e164number = e164number;
|
||||
}
|
||||
|
||||
public String getE164Number() {
|
||||
return e164number;
|
||||
}
|
||||
}
|
@ -1,70 +0,0 @@
|
||||
package org.session.libsignal.service.loki.api.shelved.p2p
|
||||
|
||||
import java.util.*
|
||||
import kotlin.concurrent.timer
|
||||
|
||||
class LokiP2PAPI private constructor(private val userHexEncodedPublicKey: String, private val onPeerConnectionStatusChanged: (Boolean, String) -> Void, private val delegate: LokiP2PAPIDelegate) {
|
||||
internal val peerInfo = mutableMapOf<String, PeerInfo>()
|
||||
private val pingIntervals = mutableMapOf<String, Int>()
|
||||
private val timers = mutableMapOf<String, Timer>()
|
||||
|
||||
// region Settings
|
||||
/**
|
||||
* The pinging interval for offline users.
|
||||
*/
|
||||
private val offlinePingInterval = 2 * 60 * 1000
|
||||
// endregion
|
||||
|
||||
// region Types
|
||||
internal data class PeerInfo(val contactHexEncodedPublicKey: String, val address: String, val port: Int, val isOnline: Boolean)
|
||||
// endregion
|
||||
|
||||
// region Initialization
|
||||
companion object {
|
||||
private var isConfigured = false
|
||||
|
||||
lateinit var shared: LokiP2PAPI
|
||||
|
||||
/**
|
||||
* Must be called before `LokiAPI` is used.
|
||||
*/
|
||||
fun configure(userHexEncodedPublicKey: String, onPeerConnectionStatusChanged: (Boolean, String) -> Void, delegate: LokiP2PAPIDelegate) {
|
||||
if (isConfigured) { return }
|
||||
shared = LokiP2PAPI(userHexEncodedPublicKey, onPeerConnectionStatusChanged, delegate)
|
||||
isConfigured = true
|
||||
}
|
||||
}
|
||||
// endregion
|
||||
|
||||
// region Public API
|
||||
fun handlePeerInfoReceived(contactHexEncodedPublicKey: String, address: String, port: Int, isP2PMessage: Boolean) {
|
||||
// Avoid peers pinging eachother at the same time by staggering their timers
|
||||
val pingInterval = if (contactHexEncodedPublicKey < this.userHexEncodedPublicKey) 1 * 60 else 2 * 60
|
||||
pingIntervals[contactHexEncodedPublicKey] = pingInterval
|
||||
val oldPeerInfo = peerInfo[contactHexEncodedPublicKey]
|
||||
val newPeerInfo = PeerInfo(contactHexEncodedPublicKey, address, port, false)
|
||||
peerInfo[contactHexEncodedPublicKey] = newPeerInfo
|
||||
// Ping the peer back and mark them online based on the result of that call if either:
|
||||
// • We didn't know about the peer at all, i.e. no P2P connection was established yet during this session
|
||||
// • The message wasn't a P2P message, i.e. no P2P connection was established yet during this session or it was dropped for some reason
|
||||
// • The peer was marked offline before; test the new P2P connection
|
||||
// • The peer's address and/or port changed; test the new P2P connection
|
||||
if (oldPeerInfo == null || !isP2PMessage || !oldPeerInfo.isOnline || oldPeerInfo.address != address || oldPeerInfo.port != port) {
|
||||
delegate.ping(contactHexEncodedPublicKey)
|
||||
} else {
|
||||
mark(true, contactHexEncodedPublicKey)
|
||||
}
|
||||
}
|
||||
|
||||
fun mark(isOnline: Boolean, contactHexEncodedPublicKey: String) {
|
||||
val oldTimer = timers[contactHexEncodedPublicKey]
|
||||
oldTimer?.cancel()
|
||||
val pingInterval = if (isOnline) { pingIntervals[contactHexEncodedPublicKey]!! } else { offlinePingInterval }
|
||||
val newTimer = timer(period = pingInterval.toLong()) { delegate.ping(contactHexEncodedPublicKey) }
|
||||
timers[contactHexEncodedPublicKey] = newTimer
|
||||
val updatedPeerInfo = peerInfo[contactHexEncodedPublicKey]!!.copy(isOnline = isOnline)
|
||||
peerInfo[contactHexEncodedPublicKey] = updatedPeerInfo
|
||||
onPeerConnectionStatusChanged(isOnline, contactHexEncodedPublicKey)
|
||||
}
|
||||
// endregion
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
package org.session.libsignal.service.loki.api.shelved.p2p
|
||||
|
||||
interface LokiP2PAPIDelegate {
|
||||
|
||||
fun ping(contactHexEncodedPublicKey: String)
|
||||
}
|
Loading…
Reference in New Issue
Block a user