mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-28 12:35:17 +00:00
Merge pull request #1594 from bemusementpark/shared-random
Share SecureRandom
This commit is contained in:
commit
415264eb0d
@ -33,18 +33,16 @@ import android.view.View
|
|||||||
import com.annimon.stream.Stream
|
import com.annimon.stream.Stream
|
||||||
import com.google.android.mms.pdu_alt.CharacterSets
|
import com.google.android.mms.pdu_alt.CharacterSets
|
||||||
import com.google.android.mms.pdu_alt.EncodedStringValue
|
import com.google.android.mms.pdu_alt.EncodedStringValue
|
||||||
|
import network.loki.messenger.R
|
||||||
|
import org.session.libsignal.utilities.Log
|
||||||
|
import org.thoughtcrime.securesms.components.ComposeText
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.io.UnsupportedEncodingException
|
import java.io.UnsupportedEncodingException
|
||||||
import java.security.SecureRandom
|
|
||||||
import java.util.Arrays
|
|
||||||
import java.util.Collections
|
import java.util.Collections
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
import network.loki.messenger.R
|
|
||||||
import org.session.libsignal.utilities.Log
|
|
||||||
import org.thoughtcrime.securesms.components.ComposeText
|
|
||||||
|
|
||||||
object Util {
|
object Util {
|
||||||
private val TAG: String = Log.tag(Util::class.java)
|
private val TAG: String = Log.tag(Util::class.java)
|
||||||
@ -248,32 +246,6 @@ object Util {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getSecretBytes(size: Int): ByteArray {
|
|
||||||
return getSecretBytes(SecureRandom(), size)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getSecretBytes(secureRandom: SecureRandom, size: Int): ByteArray {
|
|
||||||
val secret = ByteArray(size)
|
|
||||||
secureRandom.nextBytes(secret)
|
|
||||||
return secret
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T> getRandomElement(elements: Array<T>): T {
|
|
||||||
return elements[SecureRandom().nextInt(elements.size)]
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T> getRandomElement(elements: List<T>): T {
|
|
||||||
return elements[SecureRandom().nextInt(elements.size)]
|
|
||||||
}
|
|
||||||
|
|
||||||
fun equals(a: Any?, b: Any?): Boolean {
|
|
||||||
return a === b || (a != null && a == b)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun hashCode(vararg objects: Any?): Int {
|
|
||||||
return objects.contentHashCode()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun uri(uri: String?): Uri? {
|
fun uri(uri: String?): Uri? {
|
||||||
return if (uri == null) null
|
return if (uri == null) null
|
||||||
else Uri.parse(uri)
|
else Uri.parse(uri)
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
package org.thoughtcrime.securesms.crypto;
|
package org.thoughtcrime.securesms.crypto;
|
||||||
|
|
||||||
|
|
||||||
|
import static org.session.libsignal.utilities.Util.SECURE_RANDOM;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import org.session.libsession.utilities.TextSecurePreferences;
|
import org.session.libsession.utilities.TextSecurePreferences;
|
||||||
|
|
||||||
import java.security.SecureRandom;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A provider that is responsible for creating or retrieving the AttachmentSecret model.
|
* A provider that is responsible for creating or retrieving the AttachmentSecret model.
|
||||||
*
|
*
|
||||||
@ -81,9 +81,8 @@ public class AttachmentSecretProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private AttachmentSecret createAndStoreAttachmentSecret(@NonNull Context context) {
|
private AttachmentSecret createAndStoreAttachmentSecret(@NonNull Context context) {
|
||||||
SecureRandom random = new SecureRandom();
|
|
||||||
byte[] secret = new byte[32];
|
byte[] secret = new byte[32];
|
||||||
random.nextBytes(secret);
|
SECURE_RANDOM.nextBytes(secret);
|
||||||
|
|
||||||
AttachmentSecret attachmentSecret = new AttachmentSecret(null, null, secret);
|
AttachmentSecret attachmentSecret = new AttachmentSecret(null, null, secret);
|
||||||
storeAttachmentSecret(context, attachmentSecret);
|
storeAttachmentSecret(context, attachmentSecret);
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package org.thoughtcrime.securesms.crypto;
|
package org.thoughtcrime.securesms.crypto;
|
||||||
|
|
||||||
|
|
||||||
|
import static org.session.libsignal.utilities.Util.SECURE_RANDOM;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
@ -8,7 +10,6 @@ import androidx.annotation.NonNull;
|
|||||||
import org.session.libsession.utilities.TextSecurePreferences;
|
import org.session.libsession.utilities.TextSecurePreferences;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.SecureRandom;
|
|
||||||
|
|
||||||
public class DatabaseSecretProvider {
|
public class DatabaseSecretProvider {
|
||||||
|
|
||||||
@ -60,9 +61,8 @@ public class DatabaseSecretProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private DatabaseSecret createAndStoreDatabaseSecret(@NonNull Context context) {
|
private DatabaseSecret createAndStoreDatabaseSecret(@NonNull Context context) {
|
||||||
SecureRandom random = new SecureRandom();
|
|
||||||
byte[] secret = new byte[32];
|
byte[] secret = new byte[32];
|
||||||
random.nextBytes(secret);
|
SECURE_RANDOM.nextBytes(secret);
|
||||||
|
|
||||||
DatabaseSecret databaseSecret = new DatabaseSecret(secret);
|
DatabaseSecret databaseSecret = new DatabaseSecret(secret);
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package org.thoughtcrime.securesms.crypto;
|
package org.thoughtcrime.securesms.crypto;
|
||||||
|
|
||||||
|
|
||||||
|
import static org.session.libsignal.utilities.Util.SECURE_RANDOM;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
|
|
||||||
@ -11,7 +13,6 @@ import java.io.OutputStream;
|
|||||||
import java.security.InvalidAlgorithmParameterException;
|
import java.security.InvalidAlgorithmParameterException;
|
||||||
import java.security.InvalidKeyException;
|
import java.security.InvalidKeyException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.SecureRandom;
|
|
||||||
|
|
||||||
import javax.crypto.Cipher;
|
import javax.crypto.Cipher;
|
||||||
import javax.crypto.CipherOutputStream;
|
import javax.crypto.CipherOutputStream;
|
||||||
@ -31,7 +32,7 @@ public class ModernEncryptingPartOutputStream {
|
|||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
byte[] random = new byte[32];
|
byte[] random = new byte[32];
|
||||||
new SecureRandom().nextBytes(random);
|
SECURE_RANDOM.nextBytes(random);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Mac mac = Mac.getInstance("HmacSHA256");
|
Mac mac = Mac.getInstance("HmacSHA256");
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package org.thoughtcrime.securesms.database;
|
package org.thoughtcrime.securesms.database;
|
||||||
|
|
||||||
|
import static org.session.libsignal.utilities.Util.SECURE_RANDOM;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@ -26,7 +28,6 @@ import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
|
|||||||
import org.thoughtcrime.securesms.util.BitmapUtil;
|
import org.thoughtcrime.securesms.util.BitmapUtil;
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.security.SecureRandom;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -303,7 +304,7 @@ public class GroupDatabase extends Database implements LokiOpenGroupDatabaseProt
|
|||||||
public void updateProfilePicture(String groupID, byte[] newValue) {
|
public void updateProfilePicture(String groupID, byte[] newValue) {
|
||||||
long avatarId;
|
long avatarId;
|
||||||
|
|
||||||
if (newValue != null) avatarId = Math.abs(new SecureRandom().nextLong());
|
if (newValue != null) avatarId = Math.abs(SECURE_RANDOM.nextLong());
|
||||||
else avatarId = 0;
|
else avatarId = 0;
|
||||||
|
|
||||||
|
|
||||||
@ -458,12 +459,6 @@ public class GroupDatabase extends Database implements LokiOpenGroupDatabaseProt
|
|||||||
database.update(TABLE_NAME, values, GROUP_ID + " = ?", new String[] {groupId});
|
database.update(TABLE_NAME, values, GROUP_ID + " = ?", new String[] {groupId});
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] allocateGroupId() {
|
|
||||||
byte[] groupId = new byte[16];
|
|
||||||
new SecureRandom().nextBytes(groupId);
|
|
||||||
return groupId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasGroup(@NonNull String groupId) {
|
public boolean hasGroup(@NonNull String groupId) {
|
||||||
try (Cursor cursor = databaseHelper.getReadableDatabase().rawQuery(
|
try (Cursor cursor = databaseHelper.getReadableDatabase().rawQuery(
|
||||||
"SELECT 1 FROM " + TABLE_NAME + " WHERE " + GROUP_ID + " = ? LIMIT 1",
|
"SELECT 1 FROM " + TABLE_NAME + " WHERE " + GROUP_ID + " = ? LIMIT 1",
|
||||||
|
@ -46,11 +46,11 @@ import org.session.libsession.utilities.IdentityKeyMismatchList
|
|||||||
import org.session.libsession.utilities.NetworkFailure
|
import org.session.libsession.utilities.NetworkFailure
|
||||||
import org.session.libsession.utilities.NetworkFailureList
|
import org.session.libsession.utilities.NetworkFailureList
|
||||||
import org.session.libsession.utilities.TextSecurePreferences.Companion.isReadReceiptsEnabled
|
import org.session.libsession.utilities.TextSecurePreferences.Companion.isReadReceiptsEnabled
|
||||||
import org.session.libsession.utilities.Util.toIsoBytes
|
|
||||||
import org.session.libsession.utilities.recipients.Recipient
|
import org.session.libsession.utilities.recipients.Recipient
|
||||||
import org.session.libsignal.utilities.JsonUtil
|
import org.session.libsignal.utilities.JsonUtil
|
||||||
import org.session.libsignal.utilities.Log
|
import org.session.libsignal.utilities.Log
|
||||||
import org.session.libsignal.utilities.ThreadUtils.queue
|
import org.session.libsignal.utilities.ThreadUtils.queue
|
||||||
|
import org.session.libsignal.utilities.Util.SECURE_RANDOM
|
||||||
import org.session.libsignal.utilities.guava.Optional
|
import org.session.libsignal.utilities.guava.Optional
|
||||||
import org.thoughtcrime.securesms.attachments.MmsNotificationAttachment
|
import org.thoughtcrime.securesms.attachments.MmsNotificationAttachment
|
||||||
import org.thoughtcrime.securesms.database.SmsDatabase.InsertListener
|
import org.thoughtcrime.securesms.database.SmsDatabase.InsertListener
|
||||||
@ -66,7 +66,6 @@ import org.thoughtcrime.securesms.mms.SlideDeck
|
|||||||
import org.thoughtcrime.securesms.util.asSequence
|
import org.thoughtcrime.securesms.util.asSequence
|
||||||
import java.io.Closeable
|
import java.io.Closeable
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.security.SecureRandom
|
|
||||||
import java.util.LinkedList
|
import java.util.LinkedList
|
||||||
|
|
||||||
class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : MessagingDatabase(context, databaseHelper) {
|
class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : MessagingDatabase(context, databaseHelper) {
|
||||||
@ -1200,7 +1199,7 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa
|
|||||||
|
|
||||||
inner class OutgoingMessageReader(private val message: OutgoingMediaMessage?,
|
inner class OutgoingMessageReader(private val message: OutgoingMediaMessage?,
|
||||||
private val threadId: Long) {
|
private val threadId: Long) {
|
||||||
private val id = SecureRandom().nextLong()
|
private val id = SECURE_RANDOM.nextLong()
|
||||||
val current: MessageRecord
|
val current: MessageRecord
|
||||||
get() {
|
get() {
|
||||||
val slideDeck = SlideDeck(context, message!!.attachments)
|
val slideDeck = SlideDeck(context, message!!.attachments)
|
||||||
|
@ -17,6 +17,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.thoughtcrime.securesms.database;
|
package org.thoughtcrime.securesms.database;
|
||||||
|
|
||||||
|
import static org.session.libsignal.utilities.Util.SECURE_RANDOM;
|
||||||
|
|
||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
@ -49,7 +51,6 @@ import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
|
|||||||
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
|
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.SecureRandom;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
@ -784,7 +785,7 @@ public class SmsDatabase extends MessagingDatabase {
|
|||||||
public OutgoingMessageReader(OutgoingTextMessage message, long threadId) {
|
public OutgoingMessageReader(OutgoingTextMessage message, long threadId) {
|
||||||
this.message = message;
|
this.message = message;
|
||||||
this.threadId = threadId;
|
this.threadId = threadId;
|
||||||
this.id = new SecureRandom().nextLong();
|
this.id = SECURE_RANDOM.nextLong();
|
||||||
}
|
}
|
||||||
|
|
||||||
public MessageRecord getCurrent() {
|
public MessageRecord getCurrent() {
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
package org.thoughtcrime.securesms.glide;
|
package org.thoughtcrime.securesms.glide;
|
||||||
|
|
||||||
|
import static org.session.libsignal.utilities.Util.SECURE_RANDOM;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.SecureRandom;
|
|
||||||
|
|
||||||
import okhttp3.Headers;
|
import okhttp3.Headers;
|
||||||
import okhttp3.Interceptor;
|
import okhttp3.Interceptor;
|
||||||
@ -30,15 +31,15 @@ public class PaddedHeadersInterceptor implements Interceptor {
|
|||||||
|
|
||||||
private @NonNull Headers getPaddedHeaders(@NonNull Headers headers) {
|
private @NonNull Headers getPaddedHeaders(@NonNull Headers headers) {
|
||||||
return headers.newBuilder()
|
return headers.newBuilder()
|
||||||
.add(PADDING_HEADER, getRandomString(new SecureRandom(), MIN_RANDOM_BYTES, MAX_RANDOM_BYTES))
|
.add(PADDING_HEADER, getRandomString(MIN_RANDOM_BYTES, MAX_RANDOM_BYTES))
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static @NonNull String getRandomString(@NonNull SecureRandom secureRandom, int minLength, int maxLength) {
|
private static @NonNull String getRandomString(int minLength, int maxLength) {
|
||||||
char[] buffer = new char[secureRandom.nextInt(maxLength - minLength) + minLength];
|
char[] buffer = new char[SECURE_RANDOM.nextInt(maxLength - minLength) + minLength];
|
||||||
|
|
||||||
for (int i = 0 ; i < buffer.length; i++) {
|
for (int i = 0 ; i < buffer.length; i++) {
|
||||||
buffer[i] = (char) (secureRandom.nextInt(74) + 48); // Random char from 0-Z
|
buffer[i] = (char) (SECURE_RANDOM.nextInt(74) + 48); // Random char from 0-Z
|
||||||
}
|
}
|
||||||
|
|
||||||
return new String(buffer);
|
return new String(buffer);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package org.thoughtcrime.securesms.logging;
|
package org.thoughtcrime.securesms.logging;
|
||||||
|
|
||||||
import static org.session.libsignal.crypto.CipherUtil.CIPHER_LOCK;
|
import static org.session.libsignal.crypto.CipherUtil.CIPHER_LOCK;
|
||||||
|
import static org.session.libsignal.utilities.Util.SECURE_RANDOM;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
@ -17,7 +18,6 @@ import java.io.IOException;
|
|||||||
import java.security.InvalidAlgorithmParameterException;
|
import java.security.InvalidAlgorithmParameterException;
|
||||||
import java.security.InvalidKeyException;
|
import java.security.InvalidKeyException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.SecureRandom;
|
|
||||||
|
|
||||||
import javax.crypto.BadPaddingException;
|
import javax.crypto.BadPaddingException;
|
||||||
import javax.crypto.Cipher;
|
import javax.crypto.Cipher;
|
||||||
@ -64,7 +64,7 @@ class LogFile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void writeEntry(@NonNull String entry) throws IOException {
|
void writeEntry(@NonNull String entry) throws IOException {
|
||||||
new SecureRandom().nextBytes(ivBuffer);
|
SECURE_RANDOM.nextBytes(ivBuffer);
|
||||||
|
|
||||||
byte[] plaintext = entry.getBytes();
|
byte[] plaintext = entry.getBytes();
|
||||||
try {
|
try {
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package org.thoughtcrime.securesms.logging;
|
package org.thoughtcrime.securesms.logging;
|
||||||
|
|
||||||
|
import static org.session.libsignal.utilities.Util.SECURE_RANDOM;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
@ -9,7 +11,6 @@ import org.session.libsignal.utilities.Base64;
|
|||||||
import org.session.libsession.utilities.TextSecurePreferences;
|
import org.session.libsession.utilities.TextSecurePreferences;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.SecureRandom;
|
|
||||||
|
|
||||||
class LogSecretProvider {
|
class LogSecretProvider {
|
||||||
|
|
||||||
@ -40,9 +41,8 @@ class LogSecretProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] createAndStoreSecret(@NonNull Context context) {
|
private static byte[] createAndStoreSecret(@NonNull Context context) {
|
||||||
SecureRandom random = new SecureRandom();
|
|
||||||
byte[] secret = new byte[32];
|
byte[] secret = new byte[32];
|
||||||
random.nextBytes(secret);
|
SECURE_RANDOM.nextBytes(secret);
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(secret);
|
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(secret);
|
||||||
|
@ -21,7 +21,6 @@ import android.content.res.Resources
|
|||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import androidx.annotation.DrawableRes
|
import androidx.annotation.DrawableRes
|
||||||
import com.squareup.phrase.Phrase
|
import com.squareup.phrase.Phrase
|
||||||
import java.security.SecureRandom
|
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
import org.session.libsession.messaging.sending_receiving.attachments.Attachment
|
import org.session.libsession.messaging.sending_receiving.attachments.Attachment
|
||||||
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentTransferProgress
|
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentTransferProgress
|
||||||
@ -29,6 +28,7 @@ import org.session.libsession.messaging.sending_receiving.attachments.UriAttachm
|
|||||||
import org.session.libsession.utilities.StringSubstitutionConstants.EMOJI_KEY
|
import org.session.libsession.utilities.StringSubstitutionConstants.EMOJI_KEY
|
||||||
import org.session.libsession.utilities.Util.equals
|
import org.session.libsession.utilities.Util.equals
|
||||||
import org.session.libsession.utilities.Util.hashCode
|
import org.session.libsession.utilities.Util.hashCode
|
||||||
|
import org.session.libsignal.utilities.Util.SECURE_RANDOM
|
||||||
import org.session.libsignal.utilities.guava.Optional
|
import org.session.libsignal.utilities.guava.Optional
|
||||||
import org.thoughtcrime.securesms.conversation.v2.Util
|
import org.thoughtcrime.securesms.conversation.v2.Util
|
||||||
import org.thoughtcrime.securesms.util.MediaUtil
|
import org.thoughtcrime.securesms.util.MediaUtil
|
||||||
@ -160,7 +160,7 @@ abstract class Slide(@JvmField protected val context: Context, protected val att
|
|||||||
): Attachment {
|
): Attachment {
|
||||||
val resolvedType =
|
val resolvedType =
|
||||||
Optional.fromNullable(MediaUtil.getMimeType(context, uri)).or(defaultMime)
|
Optional.fromNullable(MediaUtil.getMimeType(context, uri)).or(defaultMime)
|
||||||
val fastPreflightId = SecureRandom().nextLong().toString()
|
val fastPreflightId = SECURE_RANDOM.nextLong().toString()
|
||||||
return UriAttachment(
|
return UriAttachment(
|
||||||
uri,
|
uri,
|
||||||
if (hasThumbnail) uri else null,
|
if (hasThumbnail) uri else null,
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package org.thoughtcrime.securesms.net;
|
package org.thoughtcrime.securesms.net;
|
||||||
|
|
||||||
|
import static org.session.libsignal.utilities.Util.SECURE_RANDOM;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
@ -15,7 +17,6 @@ import org.session.libsignal.utilities.guava.Optional;
|
|||||||
import java.io.FilterInputStream;
|
import java.io.FilterInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.security.SecureRandom;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -54,7 +55,7 @@ public class ChunkedDataFetcher {
|
|||||||
private RequestController fetchChunksWithUnknownTotalSize(@NonNull String url, @NonNull Callback callback) {
|
private RequestController fetchChunksWithUnknownTotalSize(@NonNull String url, @NonNull Callback callback) {
|
||||||
CompositeRequestController compositeController = new CompositeRequestController();
|
CompositeRequestController compositeController = new CompositeRequestController();
|
||||||
|
|
||||||
long chunkSize = new SecureRandom().nextInt(1024) + 1024;
|
long chunkSize = SECURE_RANDOM.nextInt(1024) + 1024;
|
||||||
Request request = new Request.Builder()
|
Request request = new Request.Builder()
|
||||||
.url(url)
|
.url(url)
|
||||||
.cacheControl(NO_CACHE)
|
.cacheControl(NO_CACHE)
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package org.thoughtcrime.securesms.permissions;
|
package org.thoughtcrime.securesms.permissions;
|
||||||
|
|
||||||
|
import static org.session.libsignal.utilities.Util.SECURE_RANDOM;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.AlertDialog;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
@ -11,9 +11,7 @@ import android.os.Build;
|
|||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.util.DisplayMetrics;
|
import android.util.DisplayMetrics;
|
||||||
import android.view.Display;
|
import android.view.Display;
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
import android.widget.Button;
|
|
||||||
|
|
||||||
import androidx.annotation.DrawableRes;
|
import androidx.annotation.DrawableRes;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
@ -28,13 +26,10 @@ import org.session.libsession.utilities.ServiceUtil;
|
|||||||
import org.thoughtcrime.securesms.util.LRUCache;
|
import org.thoughtcrime.securesms.util.LRUCache;
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.security.SecureRandom;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import network.loki.messenger.R;
|
|
||||||
|
|
||||||
public class Permissions {
|
public class Permissions {
|
||||||
|
|
||||||
private static final Map<Integer, PermissionsRequest> OUTSTANDING = new LRUCache<>(2);
|
private static final Map<Integer, PermissionsRequest> OUTSTANDING = new LRUCache<>(2);
|
||||||
@ -172,7 +167,7 @@ public class Permissions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void executePermissionsRequest(PermissionsRequest request) {
|
private void executePermissionsRequest(PermissionsRequest request) {
|
||||||
int requestCode = new SecureRandom().nextInt(65434) + 100;
|
int requestCode = SECURE_RANDOM.nextInt(65434) + 100;
|
||||||
|
|
||||||
synchronized (OUTSTANDING) {
|
synchronized (OUTSTANDING) {
|
||||||
OUTSTANDING.put(requestCode, request);
|
OUTSTANDING.put(requestCode, request);
|
||||||
|
@ -62,6 +62,7 @@ import org.session.libsession.utilities.TextSecurePreferences
|
|||||||
import org.session.libsession.utilities.recipients.Recipient
|
import org.session.libsession.utilities.recipients.Recipient
|
||||||
import org.session.libsession.utilities.truncateIdForDisplay
|
import org.session.libsession.utilities.truncateIdForDisplay
|
||||||
import org.session.libsignal.utilities.Log
|
import org.session.libsignal.utilities.Log
|
||||||
|
import org.session.libsignal.utilities.Util.SECURE_RANDOM
|
||||||
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
|
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
|
||||||
import org.thoughtcrime.securesms.avatar.AvatarSelection
|
import org.thoughtcrime.securesms.avatar.AvatarSelection
|
||||||
import org.thoughtcrime.securesms.components.ProfilePictureView
|
import org.thoughtcrime.securesms.components.ProfilePictureView
|
||||||
@ -90,7 +91,6 @@ import org.thoughtcrime.securesms.util.NetworkUtils
|
|||||||
import org.thoughtcrime.securesms.util.push
|
import org.thoughtcrime.securesms.util.push
|
||||||
import org.thoughtcrime.securesms.util.show
|
import org.thoughtcrime.securesms.util.show
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.security.SecureRandom
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
@ -294,7 +294,7 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
|
|||||||
|
|
||||||
val userConfig = configFactory.user
|
val userConfig = configFactory.user
|
||||||
AvatarHelper.setAvatar(this, Address.fromSerialized(TextSecurePreferences.getLocalNumber(this)!!), profilePicture)
|
AvatarHelper.setAvatar(this, Address.fromSerialized(TextSecurePreferences.getLocalNumber(this)!!), profilePicture)
|
||||||
prefs.setProfileAvatarId(SecureRandom().nextInt() )
|
prefs.setProfileAvatarId(SECURE_RANDOM.nextInt() )
|
||||||
ProfileKeyUtil.setEncodedProfileKey(this, encodedProfileKey)
|
ProfileKeyUtil.setEncodedProfileKey(this, encodedProfileKey)
|
||||||
|
|
||||||
// Attempt to grab the details we require to update the profile picture
|
// Attempt to grab the details we require to update the profile picture
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
package org.thoughtcrime.securesms.webrtc
|
package org.thoughtcrime.securesms.webrtc
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import org.session.libsignal.crypto.shuffledRandom
|
||||||
import org.session.libsignal.utilities.Log
|
import org.session.libsignal.utilities.Log
|
||||||
import org.session.libsignal.utilities.SettableFuture
|
import org.session.libsignal.utilities.SettableFuture
|
||||||
|
import org.session.libsignal.utilities.Util.SECURE_RANDOM
|
||||||
import org.thoughtcrime.securesms.webrtc.video.Camera
|
import org.thoughtcrime.securesms.webrtc.video.Camera
|
||||||
import org.thoughtcrime.securesms.webrtc.video.CameraEventListener
|
import org.thoughtcrime.securesms.webrtc.video.CameraEventListener
|
||||||
import org.thoughtcrime.securesms.webrtc.video.CameraState
|
import org.thoughtcrime.securesms.webrtc.video.CameraState
|
||||||
@ -22,9 +24,7 @@ import org.webrtc.SurfaceTextureHelper
|
|||||||
import org.webrtc.VideoSink
|
import org.webrtc.VideoSink
|
||||||
import org.webrtc.VideoSource
|
import org.webrtc.VideoSource
|
||||||
import org.webrtc.VideoTrack
|
import org.webrtc.VideoTrack
|
||||||
import java.security.SecureRandom
|
|
||||||
import java.util.concurrent.ExecutionException
|
import java.util.concurrent.ExecutionException
|
||||||
import kotlin.random.asKotlinRandom
|
|
||||||
|
|
||||||
class PeerConnectionWrapper(private val context: Context,
|
class PeerConnectionWrapper(private val context: Context,
|
||||||
private val factory: PeerConnectionFactory,
|
private val factory: PeerConnectionFactory,
|
||||||
@ -49,8 +49,7 @@ class PeerConnectionWrapper(private val context: Context,
|
|||||||
private var isInitiator = false
|
private var isInitiator = false
|
||||||
|
|
||||||
private fun initPeerConnection() {
|
private fun initPeerConnection() {
|
||||||
val random = SecureRandom().asKotlinRandom()
|
val iceServers = listOf("freyr","angus","hereford","holstein", "brahman").shuffledRandom().take(2).map { sub ->
|
||||||
val iceServers = listOf("freyr","angus","hereford","holstein", "brahman").shuffled(random).take(2).map { sub ->
|
|
||||||
PeerConnection.IceServer.builder("turn:$sub.getsession.org")
|
PeerConnection.IceServer.builder("turn:$sub.getsession.org")
|
||||||
.setUsername("session202111")
|
.setUsername("session202111")
|
||||||
.setPassword("053c268164bc7bd7")
|
.setPassword("053c268164bc7bd7")
|
||||||
|
@ -12,11 +12,11 @@ import org.session.libsession.utilities.Util.equals
|
|||||||
import org.session.libsession.utilities.recipients.Recipient
|
import org.session.libsession.utilities.recipients.Recipient
|
||||||
import org.session.libsignal.streams.ProfileCipherInputStream
|
import org.session.libsignal.streams.ProfileCipherInputStream
|
||||||
import org.session.libsignal.utilities.Log
|
import org.session.libsignal.utilities.Log
|
||||||
|
import org.session.libsignal.utilities.Util.SECURE_RANDOM
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileInputStream
|
import java.io.FileInputStream
|
||||||
import java.io.FileOutputStream
|
import java.io.FileOutputStream
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.security.SecureRandom
|
|
||||||
import java.util.concurrent.ConcurrentSkipListSet
|
import java.util.concurrent.ConcurrentSkipListSet
|
||||||
|
|
||||||
class RetrieveProfileAvatarJob(private val profileAvatar: String?, val recipientAddress: Address): Job {
|
class RetrieveProfileAvatarJob(private val profileAvatar: String?, val recipientAddress: Address): Job {
|
||||||
@ -64,7 +64,7 @@ class RetrieveProfileAvatarJob(private val profileAvatar: String?, val recipient
|
|||||||
Log.w(TAG, "Removing profile avatar for: " + recipient.address.serialize())
|
Log.w(TAG, "Removing profile avatar for: " + recipient.address.serialize())
|
||||||
|
|
||||||
if (recipient.isLocalNumber) {
|
if (recipient.isLocalNumber) {
|
||||||
setProfileAvatarId(context, SecureRandom().nextInt())
|
setProfileAvatarId(context, SECURE_RANDOM.nextInt())
|
||||||
setProfilePictureURL(context, null)
|
setProfilePictureURL(context, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,7 +83,7 @@ class RetrieveProfileAvatarJob(private val profileAvatar: String?, val recipient
|
|||||||
decryptDestination.renameTo(AvatarHelper.getAvatarFile(context, recipient.address))
|
decryptDestination.renameTo(AvatarHelper.getAvatarFile(context, recipient.address))
|
||||||
|
|
||||||
if (recipient.isLocalNumber) {
|
if (recipient.isLocalNumber) {
|
||||||
setProfileAvatarId(context, SecureRandom().nextInt())
|
setProfileAvatarId(context, SECURE_RANDOM.nextInt())
|
||||||
setProfilePictureURL(context, profileAvatar)
|
setProfilePictureURL(context, profileAvatar)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ import org.session.libsession.messaging.jobs.JobQueue
|
|||||||
import org.session.libsession.messaging.jobs.MessageReceiveParameters
|
import org.session.libsession.messaging.jobs.MessageReceiveParameters
|
||||||
import org.session.libsession.snode.SnodeAPI
|
import org.session.libsession.snode.SnodeAPI
|
||||||
import org.session.libsession.utilities.GroupUtil
|
import org.session.libsession.utilities.GroupUtil
|
||||||
import org.session.libsignal.crypto.getRandomElementOrNull
|
import org.session.libsignal.crypto.secureRandomOrNull
|
||||||
import org.session.libsignal.utilities.Log
|
import org.session.libsignal.utilities.Log
|
||||||
import org.session.libsignal.utilities.Namespace
|
import org.session.libsignal.utilities.Namespace
|
||||||
import org.session.libsignal.utilities.defaultRequiresAuth
|
import org.session.libsignal.utilities.defaultRequiresAuth
|
||||||
@ -104,7 +104,7 @@ class ClosedGroupPollerV2 {
|
|||||||
fun poll(groupPublicKey: String): Promise<Unit, Exception> {
|
fun poll(groupPublicKey: String): Promise<Unit, Exception> {
|
||||||
if (!isPolling(groupPublicKey)) { return Promise.of(Unit) }
|
if (!isPolling(groupPublicKey)) { return Promise.of(Unit) }
|
||||||
val promise = SnodeAPI.getSwarm(groupPublicKey).bind { swarm ->
|
val promise = SnodeAPI.getSwarm(groupPublicKey).bind { swarm ->
|
||||||
val snode = swarm.getRandomElementOrNull() ?: throw InsufficientSnodesException() // Should be cryptographically secure
|
val snode = swarm.secureRandomOrNull() ?: throw InsufficientSnodesException() // Should be cryptographically secure
|
||||||
if (!isPolling(groupPublicKey)) { throw PollingCanceledException() }
|
if (!isPolling(groupPublicKey)) { throw PollingCanceledException() }
|
||||||
val currentForkInfo = SnodeAPI.forkInfo
|
val currentForkInfo = SnodeAPI.forkInfo
|
||||||
when {
|
when {
|
||||||
|
@ -19,8 +19,6 @@ import org.session.libsession.messaging.MessagingModuleConfiguration
|
|||||||
import org.session.libsession.messaging.jobs.BatchMessageReceiveJob
|
import org.session.libsession.messaging.jobs.BatchMessageReceiveJob
|
||||||
import org.session.libsession.messaging.jobs.JobQueue
|
import org.session.libsession.messaging.jobs.JobQueue
|
||||||
import org.session.libsession.messaging.jobs.MessageReceiveParameters
|
import org.session.libsession.messaging.jobs.MessageReceiveParameters
|
||||||
import org.session.libsession.messaging.messages.control.SharedConfigurationMessage
|
|
||||||
import org.session.libsession.messaging.sending_receiving.MessageReceiver
|
|
||||||
import org.session.libsession.snode.RawResponse
|
import org.session.libsession.snode.RawResponse
|
||||||
import org.session.libsession.snode.SnodeAPI
|
import org.session.libsession.snode.SnodeAPI
|
||||||
import org.session.libsession.snode.SnodeModule
|
import org.session.libsession.snode.SnodeModule
|
||||||
@ -29,7 +27,7 @@ import org.session.libsignal.utilities.Base64
|
|||||||
import org.session.libsignal.utilities.Log
|
import org.session.libsignal.utilities.Log
|
||||||
import org.session.libsignal.utilities.Namespace
|
import org.session.libsignal.utilities.Namespace
|
||||||
import org.session.libsignal.utilities.Snode
|
import org.session.libsignal.utilities.Snode
|
||||||
import java.security.SecureRandom
|
import org.session.libsignal.utilities.Util.SECURE_RANDOM
|
||||||
import java.util.Timer
|
import java.util.Timer
|
||||||
import java.util.TimerTask
|
import java.util.TimerTask
|
||||||
import kotlin.time.Duration.Companion.days
|
import kotlin.time.Duration.Companion.days
|
||||||
@ -106,7 +104,7 @@ class Poller(private val configFactory: ConfigFactoryProtocol, debounceTimer: Ti
|
|||||||
val swarm = SnodeModule.shared.storage.getSwarm(userPublicKey) ?: setOf()
|
val swarm = SnodeModule.shared.storage.getSwarm(userPublicKey) ?: setOf()
|
||||||
val unusedSnodes = swarm.subtract(usedSnodes)
|
val unusedSnodes = swarm.subtract(usedSnodes)
|
||||||
if (unusedSnodes.isNotEmpty()) {
|
if (unusedSnodes.isNotEmpty()) {
|
||||||
val index = SecureRandom().nextInt(unusedSnodes.size)
|
val index = SECURE_RANDOM.nextInt(unusedSnodes.size)
|
||||||
val nextSnode = unusedSnodes.elementAt(index)
|
val nextSnode = unusedSnodes.elementAt(index)
|
||||||
usedSnodes.add(nextSnode)
|
usedSnodes.add(nextSnode)
|
||||||
Log.d(TAG, "Polling $nextSnode.")
|
Log.d(TAG, "Polling $nextSnode.")
|
||||||
|
@ -28,7 +28,7 @@ object MessageWrapper {
|
|||||||
val webSocketMessage = createWebSocketMessage(envelope)
|
val webSocketMessage = createWebSocketMessage(envelope)
|
||||||
return webSocketMessage.toByteArray()
|
return webSocketMessage.toByteArray()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
throw if (e is Error) { e } else { Error.FailedToWrapData }
|
throw if (e is Error) e else Error.FailedToWrapData
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,15 +49,15 @@ object MessageWrapper {
|
|||||||
|
|
||||||
private fun createWebSocketMessage(envelope: Envelope): WebSocketMessage {
|
private fun createWebSocketMessage(envelope: Envelope): WebSocketMessage {
|
||||||
try {
|
try {
|
||||||
val requestBuilder = WebSocketRequestMessage.newBuilder()
|
return WebSocketMessage.newBuilder().apply {
|
||||||
requestBuilder.verb = "PUT"
|
request = WebSocketRequestMessage.newBuilder().apply {
|
||||||
requestBuilder.path = "/api/v1/message"
|
verb = "PUT"
|
||||||
requestBuilder.id = SecureRandom.getInstance("SHA1PRNG").nextLong()
|
path = "/api/v1/message"
|
||||||
requestBuilder.body = envelope.toByteString()
|
id = SecureRandom.getInstance("SHA1PRNG").nextLong()
|
||||||
val messageBuilder = WebSocketMessage.newBuilder()
|
body = envelope.toByteString()
|
||||||
messageBuilder.request = requestBuilder.build()
|
}.build()
|
||||||
messageBuilder.type = WebSocketMessage.Type.REQUEST
|
type = WebSocketMessage.Type.REQUEST
|
||||||
return messageBuilder.build()
|
}.build()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.d("Loki", "Failed to wrap envelope in web socket message: ${e.message}.")
|
Log.d("Loki", "Failed to wrap envelope in web socket message: ${e.message}.")
|
||||||
throw Error.FailedToWrapEnvelopeInWebSocketMessage
|
throw Error.FailedToWrapEnvelopeInWebSocketMessage
|
||||||
|
@ -10,11 +10,10 @@ import okhttp3.Request
|
|||||||
import org.session.libsession.messaging.file_server.FileServerApi
|
import org.session.libsession.messaging.file_server.FileServerApi
|
||||||
import org.session.libsession.utilities.AESGCM
|
import org.session.libsession.utilities.AESGCM
|
||||||
import org.session.libsession.utilities.AESGCM.EncryptionResult
|
import org.session.libsession.utilities.AESGCM.EncryptionResult
|
||||||
import org.session.libsession.utilities.Util
|
|
||||||
import org.session.libsession.utilities.getBodyForOnionRequest
|
import org.session.libsession.utilities.getBodyForOnionRequest
|
||||||
import org.session.libsession.utilities.getHeadersForOnionRequest
|
import org.session.libsession.utilities.getHeadersForOnionRequest
|
||||||
import org.session.libsignal.crypto.getRandomElement
|
import org.session.libsignal.crypto.secureRandom
|
||||||
import org.session.libsignal.crypto.getRandomElementOrNull
|
import org.session.libsignal.crypto.secureRandomOrNull
|
||||||
import org.session.libsignal.database.LokiAPIDatabaseProtocol
|
import org.session.libsignal.database.LokiAPIDatabaseProtocol
|
||||||
import org.session.libsignal.utilities.Base64
|
import org.session.libsignal.utilities.Base64
|
||||||
import org.session.libsignal.utilities.Broadcaster
|
import org.session.libsignal.utilities.Broadcaster
|
||||||
@ -149,7 +148,7 @@ object OnionRequestAPI {
|
|||||||
val reusableGuardSnodeCount = reusableGuardSnodes.count()
|
val reusableGuardSnodeCount = reusableGuardSnodes.count()
|
||||||
if (unusedSnodes.count() < (targetGuardSnodeCount - reusableGuardSnodeCount)) { throw InsufficientSnodesException() }
|
if (unusedSnodes.count() < (targetGuardSnodeCount - reusableGuardSnodeCount)) { throw InsufficientSnodesException() }
|
||||||
fun getGuardSnode(): Promise<Snode, Exception> {
|
fun getGuardSnode(): Promise<Snode, Exception> {
|
||||||
val candidate = unusedSnodes.getRandomElementOrNull()
|
val candidate = unusedSnodes.secureRandomOrNull()
|
||||||
?: return Promise.ofFail(InsufficientSnodesException())
|
?: return Promise.ofFail(InsufficientSnodesException())
|
||||||
unusedSnodes = unusedSnodes.minus(candidate)
|
unusedSnodes = unusedSnodes.minus(candidate)
|
||||||
Log.d("Loki", "Testing guard snode: $candidate.")
|
Log.d("Loki", "Testing guard snode: $candidate.")
|
||||||
@ -191,7 +190,7 @@ object OnionRequestAPI {
|
|||||||
// Don't test path snodes as this would reveal the user's IP to them
|
// Don't test path snodes as this would reveal the user's IP to them
|
||||||
guardSnodes.minus(reusableGuardSnodes).map { guardSnode ->
|
guardSnodes.minus(reusableGuardSnodes).map { guardSnode ->
|
||||||
val result = listOf( guardSnode ) + (0 until (pathSize - 1)).mapIndexed() { index, _ ->
|
val result = listOf( guardSnode ) + (0 until (pathSize - 1)).mapIndexed() { index, _ ->
|
||||||
var pathSnode = unusedSnodes.getRandomElement()
|
var pathSnode = unusedSnodes.secureRandom()
|
||||||
|
|
||||||
// remove the snode from the unused list and return it
|
// remove the snode from the unused list and return it
|
||||||
unusedSnodes = unusedSnodes.minus(pathSnode)
|
unusedSnodes = unusedSnodes.minus(pathSnode)
|
||||||
@ -228,9 +227,9 @@ object OnionRequestAPI {
|
|||||||
OnionRequestAPI.guardSnodes = guardSnodes
|
OnionRequestAPI.guardSnodes = guardSnodes
|
||||||
fun getPath(paths: List<Path>): Path {
|
fun getPath(paths: List<Path>): Path {
|
||||||
return if (snodeToExclude != null) {
|
return if (snodeToExclude != null) {
|
||||||
paths.filter { !it.contains(snodeToExclude) }.getRandomElement()
|
paths.filter { !it.contains(snodeToExclude) }.secureRandom()
|
||||||
} else {
|
} else {
|
||||||
paths.getRandomElement()
|
paths.secureRandom()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
when {
|
when {
|
||||||
@ -273,7 +272,7 @@ object OnionRequestAPI {
|
|||||||
path.removeAt(snodeIndex)
|
path.removeAt(snodeIndex)
|
||||||
val unusedSnodes = SnodeAPI.snodePool.minus(oldPaths.flatten())
|
val unusedSnodes = SnodeAPI.snodePool.minus(oldPaths.flatten())
|
||||||
if (unusedSnodes.isEmpty()) { throw InsufficientSnodesException() }
|
if (unusedSnodes.isEmpty()) { throw InsufficientSnodesException() }
|
||||||
path.add(unusedSnodes.getRandomElement())
|
path.add(unusedSnodes.secureRandom())
|
||||||
// Don't test the new snode as this would reveal the user's IP
|
// Don't test the new snode as this would reveal the user's IP
|
||||||
oldPaths.removeAt(pathIndex)
|
oldPaths.removeAt(pathIndex)
|
||||||
val newPaths = oldPaths + listOf( path )
|
val newPaths = oldPaths + listOf( path )
|
||||||
|
@ -18,7 +18,8 @@ import nl.komponents.kovenant.task
|
|||||||
import org.session.libsession.messaging.MessagingModuleConfiguration
|
import org.session.libsession.messaging.MessagingModuleConfiguration
|
||||||
import org.session.libsession.messaging.utilities.MessageWrapper
|
import org.session.libsession.messaging.utilities.MessageWrapper
|
||||||
import org.session.libsession.messaging.utilities.SodiumUtilities.sodium
|
import org.session.libsession.messaging.utilities.SodiumUtilities.sodium
|
||||||
import org.session.libsignal.crypto.getRandomElement
|
import org.session.libsignal.crypto.secureRandom
|
||||||
|
import org.session.libsignal.crypto.shuffledRandom
|
||||||
import org.session.libsignal.database.LokiAPIDatabaseProtocol
|
import org.session.libsignal.database.LokiAPIDatabaseProtocol
|
||||||
import org.session.libsignal.protos.SignalServiceProtos
|
import org.session.libsignal.protos.SignalServiceProtos
|
||||||
import org.session.libsignal.utilities.Base64
|
import org.session.libsignal.utilities.Base64
|
||||||
@ -30,6 +31,7 @@ import org.session.libsignal.utilities.Log
|
|||||||
import org.session.libsignal.utilities.Namespace
|
import org.session.libsignal.utilities.Namespace
|
||||||
import org.session.libsignal.utilities.Snode
|
import org.session.libsignal.utilities.Snode
|
||||||
import org.session.libsignal.utilities.ThreadUtils
|
import org.session.libsignal.utilities.ThreadUtils
|
||||||
|
import org.session.libsignal.utilities.Util.SECURE_RANDOM
|
||||||
import org.session.libsignal.utilities.prettifiedDescription
|
import org.session.libsignal.utilities.prettifiedDescription
|
||||||
import org.session.libsignal.utilities.retryIfNeeded
|
import org.session.libsignal.utilities.retryIfNeeded
|
||||||
import java.security.SecureRandom
|
import java.security.SecureRandom
|
||||||
@ -209,7 +211,7 @@ object SnodeAPI {
|
|||||||
Log.d("Loki", "Persisting snode pool to database.")
|
Log.d("Loki", "Persisting snode pool to database.")
|
||||||
this.snodePool = snodePool
|
this.snodePool = snodePool
|
||||||
try {
|
try {
|
||||||
deferred.resolve(snodePool.getRandomElement())
|
deferred.resolve(snodePool.secureRandom())
|
||||||
} catch (exception: Exception) {
|
} catch (exception: Exception) {
|
||||||
Log.d("Loki", "Got an empty snode pool from: $target.")
|
Log.d("Loki", "Got an empty snode pool from: $target.")
|
||||||
deferred.reject(SnodeAPI.Error.Generic)
|
deferred.reject(SnodeAPI.Error.Generic)
|
||||||
@ -224,7 +226,7 @@ object SnodeAPI {
|
|||||||
}
|
}
|
||||||
return deferred.promise
|
return deferred.promise
|
||||||
} else {
|
} else {
|
||||||
return Promise.of(snodePool.getRandomElement())
|
return Promise.of(snodePool.secureRandom())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -241,8 +243,8 @@ object SnodeAPI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal fun getSingleTargetSnode(publicKey: String): Promise<Snode, Exception> {
|
internal fun getSingleTargetSnode(publicKey: String): Promise<Snode, Exception> {
|
||||||
// SecureRandom() should be cryptographically secure
|
// SecureRandom should be cryptographically secure
|
||||||
return getSwarm(publicKey).map { it.shuffled(SecureRandom()).random() }
|
return getSwarm(publicKey).map { it.shuffledRandom().random() }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Public API
|
// Public API
|
||||||
|
@ -13,6 +13,7 @@ import android.text.TextUtils
|
|||||||
import android.text.style.StyleSpan
|
import android.text.style.StyleSpan
|
||||||
import org.session.libsignal.utilities.Log
|
import org.session.libsignal.utilities.Log
|
||||||
import org.session.libsignal.utilities.Base64
|
import org.session.libsignal.utilities.Base64
|
||||||
|
import org.session.libsignal.utilities.Util.SECURE_RANDOM
|
||||||
import java.io.*
|
import java.io.*
|
||||||
import java.nio.charset.StandardCharsets
|
import java.nio.charset.StandardCharsets
|
||||||
import java.security.SecureRandom
|
import java.security.SecureRandom
|
||||||
@ -292,15 +293,10 @@ object Util {
|
|||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun getSecretBytes(size: Int): ByteArray {
|
fun getSecretBytes(size: Int): ByteArray {
|
||||||
val secret = ByteArray(size)
|
val secret = ByteArray(size)
|
||||||
getSecureRandom().nextBytes(secret)
|
SECURE_RANDOM.nextBytes(secret)
|
||||||
return secret
|
return secret
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
fun getSecureRandom(): SecureRandom {
|
|
||||||
return SecureRandom()
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun getFirstNonEmpty(vararg values: String?): String? {
|
fun getFirstNonEmpty(vararg values: String?): String? {
|
||||||
for (value in values) {
|
for (value in values) {
|
||||||
@ -317,18 +313,14 @@ object Util {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun <T> getRandomElement(elements: Array<T>): T {
|
fun <T> getRandomElement(elements: Array<T>): T = elements[SECURE_RANDOM.nextInt(elements.size)]
|
||||||
return elements[SecureRandom().nextInt(elements.size)]
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun getBoldedString(value: String?): CharSequence {
|
fun getBoldedString(value: String?): CharSequence {
|
||||||
if (value.isNullOrEmpty()) { return "" }
|
if (value.isNullOrEmpty()) { return "" }
|
||||||
val spanned = SpannableString(value)
|
return SpannableString(value).also {
|
||||||
spanned.setSpan(StyleSpan(Typeface.BOLD), 0,
|
it.setSpan(StyleSpan(Typeface.BOLD), 0, it.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||||
spanned.length,
|
}
|
||||||
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
|
||||||
return spanned
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
|
@ -1,19 +1,23 @@
|
|||||||
package org.session.libsignal.crypto
|
package org.session.libsignal.crypto
|
||||||
|
|
||||||
import java.security.SecureRandom
|
import org.session.libsignal.utilities.Util.SECURE_RANDOM
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Uses `SecureRandom` to pick an element from this collection.
|
* Uses `SecureRandom` to pick an element from this collection.
|
||||||
*/
|
*/
|
||||||
fun <T> Collection<T>.getRandomElementOrNull(): T? {
|
fun <T> Collection<T>.secureRandomOrNull(): T? {
|
||||||
if (isEmpty()) return null
|
if (isEmpty()) return null
|
||||||
val index = SecureRandom().nextInt(size) // SecureRandom() should be cryptographically secure
|
val index = SECURE_RANDOM.nextInt(size) // SecureRandom should be cryptographically secure
|
||||||
return elementAtOrNull(index)
|
return elementAtOrNull(index)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Uses `SecureRandom` to pick an element from this collection.
|
* Uses `SecureRandom` to pick an element from this collection.
|
||||||
|
*
|
||||||
|
* @throws [NullPointerException] if the [Collection] is empty
|
||||||
*/
|
*/
|
||||||
fun <T> Collection<T>.getRandomElement(): T {
|
fun <T> Collection<T>.secureRandom(): T {
|
||||||
return getRandomElementOrNull()!!
|
return secureRandomOrNull()!!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun <T> Collection<T>.shuffledRandom(): List<T> = shuffled(SECURE_RANDOM)
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
package org.session.libsignal.streams;
|
package org.session.libsignal.streams;
|
||||||
|
|
||||||
import static org.session.libsignal.crypto.CipherUtil.CIPHER_LOCK;
|
import static org.session.libsignal.crypto.CipherUtil.CIPHER_LOCK;
|
||||||
|
import static org.session.libsignal.utilities.Util.SECURE_RANDOM;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.security.InvalidAlgorithmParameterException;
|
import java.security.InvalidAlgorithmParameterException;
|
||||||
import java.security.InvalidKeyException;
|
import java.security.InvalidKeyException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.SecureRandom;
|
|
||||||
|
|
||||||
import javax.crypto.BadPaddingException;
|
import javax.crypto.BadPaddingException;
|
||||||
import javax.crypto.Cipher;
|
import javax.crypto.Cipher;
|
||||||
@ -80,7 +80,7 @@ public class ProfileCipherOutputStream extends DigestingOutputStream {
|
|||||||
|
|
||||||
private byte[] generateNonce() {
|
private byte[] generateNonce() {
|
||||||
byte[] nonce = new byte[12];
|
byte[] nonce = new byte[12];
|
||||||
new SecureRandom().nextBytes(nonce);
|
SECURE_RANDOM.nextBytes(nonce);
|
||||||
return nonce;
|
return nonce;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,8 +5,7 @@ import okhttp3.MediaType.Companion.toMediaType
|
|||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import okhttp3.RequestBody
|
import okhttp3.RequestBody
|
||||||
import okhttp3.Response
|
import org.session.libsignal.utilities.Util.SECURE_RANDOM
|
||||||
import java.security.SecureRandom
|
|
||||||
import java.security.cert.X509Certificate
|
import java.security.cert.X509Certificate
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import javax.net.ssl.SSLContext
|
import javax.net.ssl.SSLContext
|
||||||
@ -35,7 +34,7 @@ object HTTP {
|
|||||||
override fun getAcceptedIssuers(): Array<X509Certificate> { return arrayOf() }
|
override fun getAcceptedIssuers(): Array<X509Certificate> { return arrayOf() }
|
||||||
}
|
}
|
||||||
val sslContext = SSLContext.getInstance("SSL")
|
val sslContext = SSLContext.getInstance("SSL")
|
||||||
sslContext.init(null, arrayOf( trustManager ), SecureRandom())
|
sslContext.init(null, arrayOf( trustManager ), SECURE_RANDOM)
|
||||||
OkHttpClient().newBuilder()
|
OkHttpClient().newBuilder()
|
||||||
.sslSocketFactory(sslContext.socketFactory, trustManager)
|
.sslSocketFactory(sslContext.socketFactory, trustManager)
|
||||||
.hostnameVerifier { _, _ -> true }
|
.hostnameVerifier { _, _ -> true }
|
||||||
@ -55,7 +54,7 @@ object HTTP {
|
|||||||
override fun getAcceptedIssuers(): Array<X509Certificate> { return arrayOf() }
|
override fun getAcceptedIssuers(): Array<X509Certificate> { return arrayOf() }
|
||||||
}
|
}
|
||||||
val sslContext = SSLContext.getInstance("SSL")
|
val sslContext = SSLContext.getInstance("SSL")
|
||||||
sslContext.init(null, arrayOf( trustManager ), SecureRandom())
|
sslContext.init(null, arrayOf( trustManager ), SECURE_RANDOM)
|
||||||
return OkHttpClient().newBuilder()
|
return OkHttpClient().newBuilder()
|
||||||
.sslSocketFactory(sslContext.socketFactory, trustManager)
|
.sslSocketFactory(sslContext.socketFactory, trustManager)
|
||||||
.hostnameVerifier { _, _ -> true }
|
.hostnameVerifier { _, _ -> true }
|
||||||
|
@ -12,12 +12,10 @@ import java.io.InputStream;
|
|||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class Util {
|
public class Util {
|
||||||
|
public static SecureRandom SECURE_RANDOM = new SecureRandom();
|
||||||
|
|
||||||
public static byte[] join(byte[]... input) {
|
public static byte[] join(byte[]... input) {
|
||||||
try {
|
try {
|
||||||
@ -67,7 +65,7 @@ public class Util {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isEmpty(String value) {
|
public static boolean isEmpty(String value) {
|
||||||
return value == null || value.trim().length() == 0;
|
return value == null || value.trim().isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] getSecretBytes(int size) {
|
public static byte[] getSecretBytes(int size) {
|
||||||
@ -80,13 +78,6 @@ public class Util {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] getRandomLengthBytes(int maxSize) {
|
|
||||||
SecureRandom secureRandom = new SecureRandom();
|
|
||||||
byte[] result = new byte[secureRandom.nextInt(maxSize) + 1];
|
|
||||||
secureRandom.nextBytes(result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String readFully(InputStream in) throws IOException {
|
public static String readFully(InputStream in) throws IOException {
|
||||||
ByteArrayOutputStream bout = new ByteArrayOutputStream();
|
ByteArrayOutputStream bout = new ByteArrayOutputStream();
|
||||||
byte[] buffer = new byte[4096];
|
byte[] buffer = new byte[4096];
|
||||||
@ -98,7 +89,7 @@ public class Util {
|
|||||||
|
|
||||||
in.close();
|
in.close();
|
||||||
|
|
||||||
return new String(bout.toByteArray());
|
return bout.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void readFully(InputStream in, byte[] buffer) throws IOException {
|
public static void readFully(InputStream in, byte[] buffer) throws IOException {
|
||||||
@ -146,9 +137,4 @@ public class Util {
|
|||||||
}
|
}
|
||||||
return (int)value;
|
return (int)value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> List<T> immutableList(T... elements) {
|
|
||||||
return Collections.unmodifiableList(Arrays.asList(elements.clone()));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user