clean up signal service protocols

This commit is contained in:
Ryan ZHAO 2021-02-22 11:29:22 +11:00
parent 1db9ccdf27
commit 8c016b3802
22 changed files with 15 additions and 455 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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) {

View File

@ -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

View File

@ -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)

View File

@ -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
}

View File

@ -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)

View File

@ -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));
}
}

View File

@ -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());
}
}
}

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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
{

View File

@ -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);
}
}
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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
}

View File

@ -1,6 +0,0 @@
package org.session.libsignal.service.loki.api.shelved.p2p
interface LokiP2PAPIDelegate {
fun ping(contactHexEncodedPublicKey: String)
}