diff --git a/app/src/androidTest/java/org/thoughtcrime/securesms/database/RecipientTableTest_getAndPossiblyMerge.kt b/app/src/androidTest/java/org/thoughtcrime/securesms/database/RecipientTableTest_getAndPossiblyMerge.kt index 23da93e97b..9e54fb02eb 100644 --- a/app/src/androidTest/java/org/thoughtcrime/securesms/database/RecipientTableTest_getAndPossiblyMerge.kt +++ b/app/src/androidTest/java/org/thoughtcrime/securesms/database/RecipientTableTest_getAndPossiblyMerge.kt @@ -14,6 +14,7 @@ import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Test import org.junit.runner.RunWith +import org.signal.core.util.Base64 import org.signal.core.util.SqlUtil import org.signal.core.util.exists import org.signal.core.util.requireLong @@ -39,7 +40,6 @@ import org.thoughtcrime.securesms.notifications.profiles.NotificationProfile import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.recipients.RecipientId import org.thoughtcrime.securesms.sms.IncomingTextMessage -import org.thoughtcrime.securesms.util.Base64 import org.thoughtcrime.securesms.util.FeatureFlags import org.thoughtcrime.securesms.util.FeatureFlagsAccessor import org.thoughtcrime.securesms.util.Util diff --git a/app/src/androidTest/java/org/thoughtcrime/securesms/dependencies/InstrumentationApplicationDependencyProvider.kt b/app/src/androidTest/java/org/thoughtcrime/securesms/dependencies/InstrumentationApplicationDependencyProvider.kt index 3889c8688d..2a693da130 100644 --- a/app/src/androidTest/java/org/thoughtcrime/securesms/dependencies/InstrumentationApplicationDependencyProvider.kt +++ b/app/src/androidTest/java/org/thoughtcrime/securesms/dependencies/InstrumentationApplicationDependencyProvider.kt @@ -13,6 +13,7 @@ import okio.ByteString import org.mockito.kotlin.any import org.mockito.kotlin.doReturn import org.mockito.kotlin.mock +import org.signal.core.util.Base64 import org.signal.core.util.logging.Log import org.thoughtcrime.securesms.BuildConfig import org.thoughtcrime.securesms.KbsEnclave @@ -23,7 +24,6 @@ import org.thoughtcrime.securesms.testing.Get import org.thoughtcrime.securesms.testing.Verb import org.thoughtcrime.securesms.testing.runSync import org.thoughtcrime.securesms.testing.success -import org.thoughtcrime.securesms.util.Base64 import org.whispersystems.signalservice.api.KeyBackupService import org.whispersystems.signalservice.api.SignalServiceAccountManager import org.whispersystems.signalservice.api.push.TrustStore diff --git a/app/src/androidTest/java/org/thoughtcrime/securesms/jobs/RefreshOwnProfileJob__checkUsernameIsInSyncTest.kt b/app/src/androidTest/java/org/thoughtcrime/securesms/jobs/RefreshOwnProfileJob__checkUsernameIsInSyncTest.kt index 860ab4c711..814ff60fcf 100644 --- a/app/src/androidTest/java/org/thoughtcrime/securesms/jobs/RefreshOwnProfileJob__checkUsernameIsInSyncTest.kt +++ b/app/src/androidTest/java/org/thoughtcrime/securesms/jobs/RefreshOwnProfileJob__checkUsernameIsInSyncTest.kt @@ -8,6 +8,7 @@ import org.junit.Assert.assertTrue import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith +import org.signal.core.util.Base64 import org.signal.libsignal.usernames.Username import org.thoughtcrime.securesms.database.SignalDatabase import org.thoughtcrime.securesms.dependencies.InstrumentationApplicationDependencyProvider @@ -20,7 +21,6 @@ import org.thoughtcrime.securesms.testing.failure import org.thoughtcrime.securesms.testing.success import org.whispersystems.signalservice.internal.push.ReserveUsernameResponse import org.whispersystems.signalservice.internal.push.WhoAmIResponse -import org.whispersystems.util.Base64UrlSafe @Suppress("ClassName") @RunWith(AndroidJUnit4::class) @@ -58,13 +58,13 @@ class RefreshOwnProfileJob__checkUsernameIsInSyncTest { Get("/v1/accounts/whoami") { r -> MockResponse().success( WhoAmIResponse().apply { - usernameHash = Base64UrlSafe.encodeBytesWithoutPadding(Username.hash(serverUsername)) + usernameHash = Base64.encodeUrlSafeWithoutPadding(Username.hash(serverUsername)) } ) }, Put("/v1/accounts/username_hash/reserve") { r -> didReserve = true - MockResponse().success(ReserveUsernameResponse(Base64UrlSafe.encodeBytesWithoutPadding(Username.hash(username)))) + MockResponse().success(ReserveUsernameResponse(Base64.encodeUrlSafeWithoutPadding(Username.hash(username)))) }, Put("/v1/accounts/username_hash/confirm") { r -> didConfirm = true @@ -94,7 +94,7 @@ class RefreshOwnProfileJob__checkUsernameIsInSyncTest { }, Put("/v1/accounts/username_hash/reserve") { r -> didReserve = true - MockResponse().success(ReserveUsernameResponse(Base64UrlSafe.encodeBytesWithoutPadding(Username.hash(username)))) + MockResponse().success(ReserveUsernameResponse(Base64.encodeUrlSafeWithoutPadding(Username.hash(username)))) }, Put("/v1/accounts/username_hash/confirm") { r -> didConfirm = true @@ -122,13 +122,13 @@ class RefreshOwnProfileJob__checkUsernameIsInSyncTest { Get("/v1/accounts/whoami") { r -> MockResponse().success( WhoAmIResponse().apply { - usernameHash = Base64UrlSafe.encodeBytesWithoutPadding(Username.hash(username)) + usernameHash = Base64.encodeUrlSafeWithoutPadding(Username.hash(username)) } ) }, Put("/v1/accounts/username_hash/reserve") { r -> didReserve = true - MockResponse().success(ReserveUsernameResponse(Base64UrlSafe.encodeBytesWithoutPadding(Username.hash(username)))) + MockResponse().success(ReserveUsernameResponse(Base64.encodeUrlSafeWithoutPadding(Username.hash(username)))) }, Put("/v1/accounts/username_hash/confirm") { r -> didConfirm = true @@ -156,7 +156,7 @@ class RefreshOwnProfileJob__checkUsernameIsInSyncTest { Get("/v1/accounts/whoami") { r -> MockResponse().success( WhoAmIResponse().apply { - usernameHash = Base64UrlSafe.encodeBytesWithoutPadding(Username.hash("${username}23")) + usernameHash = Base64.encodeUrlSafeWithoutPadding(Username.hash("${username}23")) } ) }, diff --git a/app/src/androidTest/java/org/thoughtcrime/securesms/storage/ContactRecordProcessorTest.kt b/app/src/androidTest/java/org/thoughtcrime/securesms/storage/ContactRecordProcessorTest.kt index f7073635cc..f63fd8c667 100644 --- a/app/src/androidTest/java/org/thoughtcrime/securesms/storage/ContactRecordProcessorTest.kt +++ b/app/src/androidTest/java/org/thoughtcrime/securesms/storage/ContactRecordProcessorTest.kt @@ -6,12 +6,12 @@ import org.junit.Assert.assertNotEquals import org.junit.Before import org.junit.Test import org.junit.runner.RunWith +import org.signal.core.util.Base64 import org.signal.core.util.update import org.thoughtcrime.securesms.database.RecipientTable import org.thoughtcrime.securesms.database.SignalDatabase import org.thoughtcrime.securesms.keyvalue.SignalStore import org.thoughtcrime.securesms.recipients.RecipientId -import org.thoughtcrime.securesms.util.Base64 import org.thoughtcrime.securesms.util.FeatureFlags import org.thoughtcrime.securesms.util.FeatureFlagsAccessor import org.whispersystems.signalservice.api.push.ServiceId.ACI @@ -113,7 +113,7 @@ class ContactRecordProcessorTest { private fun setStorageId(recipientId: RecipientId, storageId: StorageId) { SignalDatabase.rawDatabase .update(RecipientTable.TABLE_NAME) - .values(RecipientTable.STORAGE_SERVICE_ID to Base64.encodeBytes(storageId.raw)) + .values(RecipientTable.STORAGE_SERVICE_ID to Base64.encodeWithPadding(storageId.raw)) .where("${RecipientTable.ID} = ?", recipientId) .run() } diff --git a/app/src/androidTest/java/org/thoughtcrime/securesms/testing/FakeClientHelpers.kt b/app/src/androidTest/java/org/thoughtcrime/securesms/testing/FakeClientHelpers.kt index d811829762..d18eb79922 100644 --- a/app/src/androidTest/java/org/thoughtcrime/securesms/testing/FakeClientHelpers.kt +++ b/app/src/androidTest/java/org/thoughtcrime/securesms/testing/FakeClientHelpers.kt @@ -1,6 +1,7 @@ package org.thoughtcrime.securesms.testing import okio.ByteString.Companion.toByteString +import org.signal.core.util.Base64 import org.signal.libsignal.internal.Native import org.signal.libsignal.internal.NativeHandleGuard import org.signal.libsignal.metadata.certificate.CertificateValidator @@ -20,7 +21,6 @@ import org.whispersystems.signalservice.internal.push.Content import org.whispersystems.signalservice.internal.push.DataMessage import org.whispersystems.signalservice.internal.push.Envelope import org.whispersystems.signalservice.internal.push.OutgoingPushMessage -import org.whispersystems.util.Base64 import java.util.Optional import java.util.UUID diff --git a/app/src/main/java/org/thoughtcrime/securesms/DeviceActivity.java b/app/src/main/java/org/thoughtcrime/securesms/DeviceActivity.java index 1f9408bd2c..0d033a8cc8 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/DeviceActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/DeviceActivity.java @@ -30,7 +30,7 @@ import org.thoughtcrime.securesms.crypto.ProfileKeyUtil; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.keyvalue.SignalStore; import org.thoughtcrime.securesms.permissions.Permissions; -import org.thoughtcrime.securesms.util.Base64; +import org.signal.core.util.Base64; import org.thoughtcrime.securesms.util.DynamicLanguage; import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme; import org.thoughtcrime.securesms.util.DynamicTheme; diff --git a/app/src/main/java/org/thoughtcrime/securesms/attachments/PointerAttachment.java b/app/src/main/java/org/thoughtcrime/securesms/attachments/PointerAttachment.java index 247f5cac50..a4265eed34 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/attachments/PointerAttachment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/attachments/PointerAttachment.java @@ -9,7 +9,7 @@ import androidx.annotation.Nullable; import org.thoughtcrime.securesms.blurhash.BlurHash; import org.thoughtcrime.securesms.database.AttachmentTable; import org.thoughtcrime.securesms.stickers.StickerLocator; -import org.thoughtcrime.securesms.util.Base64; +import org.signal.core.util.Base64; import org.whispersystems.signalservice.api.InvalidMessageStructureException; import org.whispersystems.signalservice.api.messages.SignalServiceAttachment; import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage; @@ -108,7 +108,7 @@ public class PointerAttachment extends Attachment { String encodedKey = null; if (pointer.get().asPointer().getKey() != null) { - encodedKey = Base64.encodeBytes(pointer.get().asPointer().getKey()); + encodedKey = Base64.encodeWithPadding(pointer.get().asPointer().getKey()); } return Optional.of(new PointerAttachment(pointer.get().getContentType(), @@ -144,7 +144,7 @@ public class PointerAttachment extends Attachment { pointer.getFileName(), thumbnail != null ? thumbnail.asPointer().getCdnNumber() : 0, thumbnail != null ? thumbnail.asPointer().getRemoteId().toString() : "0", - thumbnail != null && thumbnail.asPointer().getKey() != null ? Base64.encodeBytes(thumbnail.asPointer().getKey()) : null, + thumbnail != null && thumbnail.asPointer().getKey() != null ? Base64.encodeWithPadding(thumbnail.asPointer().getKey()) : null, null, thumbnail != null ? thumbnail.asPointer().getDigest().orElse(null) : null, thumbnail != null ? thumbnail.asPointer().getIncrementalDigest().orElse(null) : null, @@ -175,7 +175,7 @@ public class PointerAttachment extends Attachment { quotedAttachment.fileName, thumbnail != null ? thumbnail.asPointer().getCdnNumber() : 0, thumbnail != null ? thumbnail.asPointer().getRemoteId().toString() : "0", - thumbnail != null && thumbnail.asPointer().getKey() != null ? Base64.encodeBytes(thumbnail.asPointer().getKey()) : null, + thumbnail != null && thumbnail.asPointer().getKey() != null ? Base64.encodeWithPadding(thumbnail.asPointer().getKey()) : null, null, thumbnail != null ? thumbnail.asPointer().getDigest().orElse(null) : null, thumbnail != null ? thumbnail.asPointer().getIncrementalDigest().orElse(null) : null, diff --git a/app/src/main/java/org/thoughtcrime/securesms/audio/AudioHash.java b/app/src/main/java/org/thoughtcrime/securesms/audio/AudioHash.java index 703467828e..701a379361 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/audio/AudioHash.java +++ b/app/src/main/java/org/thoughtcrime/securesms/audio/AudioHash.java @@ -8,7 +8,7 @@ import androidx.annotation.Nullable; import org.thoughtcrime.securesms.database.model.databaseprotos.AudioWaveFormData; import org.thoughtcrime.securesms.util.ParcelUtil; -import org.whispersystems.util.Base64; +import org.signal.core.util.Base64; import java.io.IOException; import java.util.Objects; @@ -27,7 +27,7 @@ public final class AudioHash implements Parcelable { } public AudioHash(@NonNull AudioWaveFormData audioWaveForm) { - this(Base64.encodeBytes(audioWaveForm.encode()), audioWaveForm); + this(Base64.encodeWithPadding(audioWaveForm.encode()), audioWaveForm); } protected AudioHash(Parcel in) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/badges/gifts/Gifts.kt b/app/src/main/java/org/thoughtcrime/securesms/badges/gifts/Gifts.kt index 43672fbe38..897152302c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/badges/gifts/Gifts.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/badges/gifts/Gifts.kt @@ -1,13 +1,13 @@ package org.thoughtcrime.securesms.badges.gifts import android.content.Context +import org.signal.core.util.Base64 import org.signal.libsignal.zkgroup.InvalidInputException import org.signal.libsignal.zkgroup.receipts.ReceiptCredentialPresentation import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.database.model.databaseprotos.GiftBadge import org.thoughtcrime.securesms.mms.OutgoingMessage import org.thoughtcrime.securesms.recipients.Recipient -import org.thoughtcrime.securesms.util.Base64 import java.lang.Integer.min import java.util.concurrent.TimeUnit @@ -32,7 +32,7 @@ object Gifts { ): OutgoingMessage { return OutgoingMessage( threadRecipient = recipient, - body = Base64.encodeBytes(giftBadge.encode()), + body = Base64.encodeWithPadding(giftBadge.encode()), isSecure = true, sentTimeMillis = sentTimestamp, expiresIn = expiresIn, diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/InternalConversationSettingsFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/InternalConversationSettingsFragment.kt index f608b6f175..4211571526 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/InternalConversationSettingsFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/InternalConversationSettingsFragment.kt @@ -7,6 +7,7 @@ import androidx.fragment.app.viewModels import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import com.google.android.material.dialog.MaterialAlertDialogBuilder +import org.signal.core.util.Base64 import org.signal.core.util.Hex import org.signal.core.util.concurrent.SignalExecutors import org.signal.core.util.isAbsent @@ -27,7 +28,6 @@ import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.recipients.RecipientForeverObserver import org.thoughtcrime.securesms.recipients.RecipientId import org.thoughtcrime.securesms.subscription.Subscriber -import org.thoughtcrime.securesms.util.Base64 import org.thoughtcrime.securesms.util.FeatureFlags import org.thoughtcrime.securesms.util.SpanUtil import org.thoughtcrime.securesms.util.Util @@ -110,7 +110,7 @@ class InternalConversationSettingsFragment : DSLSettingsFragment( summary = DSLSettingsText.from("[${recipient.profileName.givenName}] [${state.recipient.profileName.familyName}]") ) - val profileKeyBase64 = recipient.profileKey?.let(Base64::encodeBytes) ?: "None" + val profileKeyBase64 = recipient.profileKey?.let(Base64::encodeWithPadding) ?: "None" longClickPref( title = DSLSettingsText.from("Profile Key (Base64)"), summary = DSLSettingsText.from(profileKeyBase64), diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/drafts/DraftRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/drafts/DraftRepository.kt index 53f15a8b34..3073bf5c44 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/drafts/DraftRepository.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/drafts/DraftRepository.kt @@ -6,6 +6,7 @@ import android.text.Spannable import android.text.SpannableString import io.reactivex.rxjava3.core.Maybe import io.reactivex.rxjava3.schedulers.Schedulers +import org.signal.core.util.Base64 import org.signal.core.util.StreamUtil import org.signal.core.util.concurrent.MaybeCompat import org.signal.core.util.concurrent.SignalExecutors @@ -41,7 +42,6 @@ import org.thoughtcrime.securesms.mms.SlideFactory import org.thoughtcrime.securesms.mms.StickerSlide import org.thoughtcrime.securesms.providers.BlobProvider import org.thoughtcrime.securesms.recipients.Recipient -import org.thoughtcrime.securesms.util.Base64 import org.thoughtcrime.securesms.util.MediaUtil import org.thoughtcrime.securesms.util.concurrent.SerialMonoLifoExecutor import org.thoughtcrime.securesms.util.hasTextSlide diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/drafts/DraftViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/drafts/DraftViewModel.kt index 709fd450a1..5e558dee8f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/drafts/DraftViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/drafts/DraftViewModel.kt @@ -4,6 +4,7 @@ import androidx.lifecycle.ViewModel import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers import io.reactivex.rxjava3.core.Flowable import io.reactivex.rxjava3.core.Maybe +import org.signal.core.util.Base64 import org.thoughtcrime.securesms.components.location.SignalPlace import org.thoughtcrime.securesms.database.DraftTable.Draft import org.thoughtcrime.securesms.database.MentionUtil @@ -12,7 +13,6 @@ import org.thoughtcrime.securesms.database.model.MessageId import org.thoughtcrime.securesms.database.model.databaseprotos.BodyRangeList import org.thoughtcrime.securesms.mms.QuoteId import org.thoughtcrime.securesms.recipients.RecipientId -import org.thoughtcrime.securesms.util.Base64 import org.thoughtcrime.securesms.util.rx.RxStore /** @@ -148,5 +148,5 @@ private fun String.toTextDraft(): Draft? { } private fun BodyRangeList.toDraft(): Draft { - return Draft(Draft.BODY_RANGES, Base64.encodeBytes(encode())) + return Draft(Draft.BODY_RANGES, Base64.encodeWithPadding(encode())) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/crypto/AsymmetricMasterCipher.java b/app/src/main/java/org/thoughtcrime/securesms/crypto/AsymmetricMasterCipher.java index a7d6d6ad67..512a317129 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/crypto/AsymmetricMasterCipher.java +++ b/app/src/main/java/org/thoughtcrime/securesms/crypto/AsymmetricMasterCipher.java @@ -24,7 +24,7 @@ import org.signal.libsignal.protocol.ecc.Curve; import org.signal.libsignal.protocol.ecc.ECKeyPair; import org.signal.libsignal.protocol.ecc.ECPrivateKey; import org.signal.libsignal.protocol.ecc.ECPublicKey; -import org.thoughtcrime.securesms.util.Base64; +import org.signal.core.util.Base64; import org.thoughtcrime.securesms.util.Util; import java.io.IOException; @@ -99,7 +99,7 @@ public class AsymmetricMasterCipher { } public String encryptBody(String body) { - return Base64.encodeBytes(encryptBytes(body.getBytes())); + return Base64.encodeWithPadding(encryptBytes(body.getBytes())); } private MasterCipher getMasterCipherForSecret(byte[] secretBytes) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/crypto/MasterCipher.java b/app/src/main/java/org/thoughtcrime/securesms/crypto/MasterCipher.java index b19be31194..0e0f19968e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/crypto/MasterCipher.java +++ b/app/src/main/java/org/thoughtcrime/securesms/crypto/MasterCipher.java @@ -23,7 +23,7 @@ import org.signal.core.util.logging.Log; import org.signal.libsignal.protocol.InvalidMessageException; import org.signal.libsignal.protocol.ecc.Curve; import org.signal.libsignal.protocol.ecc.ECPrivateKey; -import org.thoughtcrime.securesms.util.Base64; +import org.signal.core.util.Base64; import org.signal.core.util.Hex; import java.io.IOException; @@ -153,7 +153,7 @@ public class MasterCipher { private String encryptAndEncodeBytes(@NonNull byte[] bytes) { byte[] encryptedAndMacBody = encryptBytes(bytes); - return Base64.encodeBytes(encryptedAndMacBody); + return Base64.encodeWithPadding(encryptedAndMacBody); } private byte[] verifyMacBody(@NonNull Mac hmac, @NonNull byte[] encryptedAndMac) throws InvalidMessageException { diff --git a/app/src/main/java/org/thoughtcrime/securesms/crypto/MasterSecretUtil.java b/app/src/main/java/org/thoughtcrime/securesms/crypto/MasterSecretUtil.java index 73952301b6..ece764c290 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/crypto/MasterSecretUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/crypto/MasterSecretUtil.java @@ -30,7 +30,7 @@ import org.signal.libsignal.protocol.ecc.Curve; import org.signal.libsignal.protocol.ecc.ECKeyPair; import org.signal.libsignal.protocol.ecc.ECPrivateKey; import org.signal.libsignal.protocol.ecc.ECPublicKey; -import org.thoughtcrime.securesms.util.Base64; +import org.signal.core.util.Base64; import org.thoughtcrime.securesms.util.Util; import java.io.IOException; @@ -216,7 +216,7 @@ public class MasterSecretUtil { private static void save(Context context, String key, byte[] value) { if (!getSharedPreferences(context) .edit() - .putString(key, Base64.encodeBytes(value)) + .putString(key, Base64.encodeWithPadding(value)) .commit()) { throw new AssertionError("failed to save a shared pref in MasterSecretUtil"); diff --git a/app/src/main/java/org/thoughtcrime/securesms/crypto/ProfileKeyUtil.java b/app/src/main/java/org/thoughtcrime/securesms/crypto/ProfileKeyUtil.java index 9b742d56af..4b431c0f96 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/crypto/ProfileKeyUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/crypto/ProfileKeyUtil.java @@ -7,7 +7,7 @@ import org.signal.core.util.logging.Log; import org.signal.libsignal.zkgroup.InvalidInputException; import org.signal.libsignal.zkgroup.profiles.ProfileKey; import org.thoughtcrime.securesms.recipients.Recipient; -import org.thoughtcrime.securesms.util.Base64; +import org.signal.core.util.Base64; import org.thoughtcrime.securesms.util.Util; import java.io.IOException; diff --git a/app/src/main/java/org/thoughtcrime/securesms/crypto/UnidentifiedAccessUtil.java b/app/src/main/java/org/thoughtcrime/securesms/crypto/UnidentifiedAccessUtil.java index 797e4fa04b..08a5aef231 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/crypto/UnidentifiedAccessUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/crypto/UnidentifiedAccessUtil.java @@ -22,7 +22,7 @@ import org.thoughtcrime.securesms.keyvalue.PhoneNumberPrivacyValues; import org.thoughtcrime.securesms.keyvalue.SignalStore; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; -import org.thoughtcrime.securesms.util.Base64; +import org.signal.core.util.Base64; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.Util; import org.whispersystems.signalservice.api.crypto.UnidentifiedAccess; diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/AttachmentTable.java b/app/src/main/java/org/thoughtcrime/securesms/database/AttachmentTable.java index 07cfe2b1a9..42775e72af 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/AttachmentTable.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/AttachmentTable.java @@ -37,6 +37,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import org.json.JSONArray; import org.json.JSONException; +import org.signal.core.util.Base64; import org.signal.core.util.CursorExtensionsKt; import org.signal.core.util.CursorUtil; import org.signal.core.util.SQLiteDatabaseExtensionsKt; @@ -60,7 +61,6 @@ import org.thoughtcrime.securesms.mms.MmsException; import org.thoughtcrime.securesms.mms.PartAuthority; import org.thoughtcrime.securesms.mms.SentMediaQuality; import org.thoughtcrime.securesms.stickers.StickerLocator; -import org.thoughtcrime.securesms.util.Base64; import org.thoughtcrime.securesms.util.FileUtils; import org.thoughtcrime.securesms.util.JsonUtils; import org.thoughtcrime.securesms.util.MediaUtil; @@ -1189,7 +1189,7 @@ public class AttachmentTable extends DatabaseTable { DigestInputStream digestInputStream = new DigestInputStream(in, messageDigest); Pair out = ModernEncryptingPartOutputStream.createFor(attachmentSecret, tempFile, false); long length = StreamUtil.copy(digestInputStream, out.second); - String hash = Base64.encodeBytes(digestInputStream.getMessageDigest().digest()); + String hash = Base64.encodeWithPadding(digestInputStream.getMessageDigest().digest()); if (!tempFile.renameTo(destination)) { Log.w(TAG, "Couldn't rename " + tempFile.getPath() + " to " + destination.getPath()); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/DistributionListTables.kt b/app/src/main/java/org/thoughtcrime/securesms/database/DistributionListTables.kt index 68b82947e8..2379a49869 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/DistributionListTables.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/DistributionListTables.kt @@ -4,6 +4,7 @@ import android.content.ContentValues import android.content.Context import android.database.Cursor import androidx.core.content.contentValuesOf +import org.signal.core.util.Base64 import org.signal.core.util.CursorUtil import org.signal.core.util.SqlUtil import org.signal.core.util.delete @@ -23,7 +24,6 @@ import org.thoughtcrime.securesms.database.model.StoryType import org.thoughtcrime.securesms.recipients.RecipientId import org.thoughtcrime.securesms.storage.StorageRecordUpdate import org.thoughtcrime.securesms.storage.StorageSyncHelper -import org.thoughtcrime.securesms.util.Base64 import org.whispersystems.signalservice.api.push.DistributionId import org.whispersystems.signalservice.api.storage.SignalStoryDistributionListRecord import org.whispersystems.signalservice.api.util.UuidUtil @@ -55,7 +55,7 @@ class DistributionListTables constructor(context: Context?, databaseHelper: Sign contentValuesOf( RecipientTable.TYPE to RecipientTable.RecipientType.DISTRIBUTION_LIST.id, RecipientTable.DISTRIBUTION_LIST_ID to DistributionListId.MY_STORY_ID, - RecipientTable.STORAGE_SERVICE_ID to Base64.encodeBytes(StorageSyncHelper.generateKey()), + RecipientTable.STORAGE_SERVICE_ID to Base64.encodeWithPadding(StorageSyncHelper.generateKey()), RecipientTable.PROFILE_SHARING to 1 ) ) diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/IdentityTable.kt b/app/src/main/java/org/thoughtcrime/securesms/database/IdentityTable.kt index 55178915a6..706eb6c403 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/IdentityTable.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/IdentityTable.kt @@ -19,6 +19,7 @@ package org.thoughtcrime.securesms.database import android.content.Context import androidx.core.content.contentValuesOf import org.greenrobot.eventbus.EventBus +import org.signal.core.util.Base64 import org.signal.core.util.delete import org.signal.core.util.exists import org.signal.core.util.firstOrNull @@ -38,7 +39,6 @@ import org.thoughtcrime.securesms.dependencies.ApplicationDependencies import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.recipients.RecipientId import org.thoughtcrime.securesms.storage.StorageSyncHelper -import org.thoughtcrime.securesms.util.Base64 import org.thoughtcrime.securesms.util.IdentityUtil import org.whispersystems.signalservice.api.push.ServiceId import org.whispersystems.signalservice.api.util.UuidUtil @@ -146,7 +146,7 @@ class IdentityTable internal constructor(context: Context?, databaseHelper: Sign val updated = writableDatabase .update(TABLE_NAME) .values(VERIFIED to verifiedStatus.toInt()) - .where("$ADDRESS = ? AND $IDENTITY_KEY = ?", addressName, Base64.encodeBytes(identityKey.serialize())) + .where("$ADDRESS = ? AND $IDENTITY_KEY = ?", addressName, Base64.encodeWithPadding(identityKey.serialize())) .run() if (updated > 0) { @@ -211,14 +211,14 @@ class IdentityTable internal constructor(context: Context?, databaseHelper: Sign private fun hasMatchingKey(addressName: String, identityKey: IdentityKey): Boolean { return readableDatabase .exists(TABLE_NAME) - .where("$ADDRESS = ? AND $IDENTITY_KEY = ?", addressName, Base64.encodeBytes(identityKey.serialize())) + .where("$ADDRESS = ? AND $IDENTITY_KEY = ?", addressName, Base64.encodeWithPadding(identityKey.serialize())) .run() } private fun hasMatchingStatus(addressName: String, identityKey: IdentityKey, verifiedStatus: VerifiedStatus): Boolean { return readableDatabase .exists(TABLE_NAME) - .where("$ADDRESS = ? AND $IDENTITY_KEY = ? AND $VERIFIED = ?", addressName, Base64.encodeBytes(identityKey.serialize()), verifiedStatus.toInt()) + .where("$ADDRESS = ? AND $IDENTITY_KEY = ? AND $VERIFIED = ?", addressName, Base64.encodeWithPadding(identityKey.serialize()), verifiedStatus.toInt()) .run() } @@ -233,7 +233,7 @@ class IdentityTable internal constructor(context: Context?, databaseHelper: Sign ) { val contentValues = contentValuesOf( ADDRESS to addressName, - IDENTITY_KEY to Base64.encodeBytes(identityKey.serialize()), + IDENTITY_KEY to Base64.encodeWithPadding(identityKey.serialize()), TIMESTAMP to timestamp, VERIFIED to verifiedStatus.toInt(), NONBLOCKING_APPROVAL to if (nonBlockingApproval) 1 else 0, diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MessageTable.kt b/app/src/main/java/org/thoughtcrime/securesms/database/MessageTable.kt index b4f877aefd..98d92062ad 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MessageTable.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MessageTable.kt @@ -28,6 +28,7 @@ import com.google.android.mms.pdu_alt.PduHeaders import org.json.JSONArray import org.json.JSONException import org.json.JSONObject +import org.signal.core.util.Base64 import org.signal.core.util.CursorUtil import org.signal.core.util.SqlUtil import org.signal.core.util.SqlUtil.appendArg @@ -131,7 +132,6 @@ import org.thoughtcrime.securesms.revealable.ViewOnceUtil import org.thoughtcrime.securesms.sms.IncomingGroupUpdateMessage import org.thoughtcrime.securesms.sms.IncomingTextMessage import org.thoughtcrime.securesms.stories.Stories.isFeatureEnabled -import org.thoughtcrime.securesms.util.Base64 import org.thoughtcrime.securesms.util.FeatureFlags import org.thoughtcrime.securesms.util.JsonUtils import org.thoughtcrime.securesms.util.MediaUtil @@ -861,7 +861,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat DATE_RECEIVED to timestamp, DATE_SENT to timestamp, READ to if (markRead) 1 else 0, - BODY to Base64.encodeBytes(updateDetails), + BODY to Base64.encodeWithPadding(updateDetails), TYPE to MessageTypes.GROUP_CALL_TYPE, THREAD_ID to threadId ) @@ -891,7 +891,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat val updateDetail = GroupCallUpdateDetailsUtil.parse(message.body) val contentValues = contentValuesOf( - BODY to Base64.encodeBytes(updateDetail.newBuilder().startedCallTimestamp(timestamp).build().encode()), + BODY to Base64.encodeWithPadding(updateDetail.newBuilder().startedCallTimestamp(timestamp).build().encode()), DATE_SENT to timestamp, DATE_RECEIVED to timestamp ) @@ -1179,7 +1179,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat READ to 1, TYPE to MessageTypes.PROFILE_CHANGE_TYPE, THREAD_ID to threadId, - BODY to Base64.encodeBytes(profileChangeDetails) + BODY to Base64.encodeWithPadding(profileChangeDetails) ) db.insert(TABLE_NAME, null, values) notifyConversationListeners(threadId) @@ -1286,7 +1286,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat READ to 1, TYPE to MessageTypes.THREAD_MERGE_TYPE, THREAD_ID to threadId, - BODY to Base64.encodeBytes(event.encode()) + BODY to Base64.encodeWithPadding(event.encode()) ) .run() ApplicationDependencies.getDatabaseObserver().notifyConversationListeners(threadId) @@ -1305,7 +1305,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat READ to 1, TYPE to MessageTypes.SESSION_SWITCHOVER_TYPE, THREAD_ID to threadId, - BODY to Base64.encodeBytes(event.encode()) + BODY to Base64.encodeWithPadding(event.encode()) ) .run() ApplicationDependencies.getDatabaseObserver().notifyConversationListeners(threadId) @@ -2914,7 +2914,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat updated = db .update(TABLE_NAME) - .values(BODY to Base64.encodeBytes(updatedBadge.encode())) + .values(BODY to Base64.encodeWithPadding(updatedBadge.encode())) .where("$ID = ?", messageId) .run() > 0 diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/OneTimePreKeyTable.kt b/app/src/main/java/org/thoughtcrime/securesms/database/OneTimePreKeyTable.kt index 3c934d5c4a..c40a4eb8ab 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/OneTimePreKeyTable.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/OneTimePreKeyTable.kt @@ -2,6 +2,7 @@ package org.thoughtcrime.securesms.database import android.content.Context import androidx.core.content.contentValuesOf +import org.signal.core.util.Base64 import org.signal.core.util.SqlUtil import org.signal.core.util.delete import org.signal.core.util.logging.Log @@ -11,7 +12,6 @@ import org.signal.libsignal.protocol.InvalidKeyException import org.signal.libsignal.protocol.ecc.Curve import org.signal.libsignal.protocol.ecc.ECKeyPair import org.signal.libsignal.protocol.state.PreKeyRecord -import org.thoughtcrime.securesms.util.Base64 import org.whispersystems.signalservice.api.push.ServiceId import java.io.IOException @@ -62,8 +62,8 @@ class OneTimePreKeyTable(context: Context, databaseHelper: SignalDatabase) : Dat val contentValues = contentValuesOf( ACCOUNT_ID to serviceId.toString(), KEY_ID to keyId, - PUBLIC_KEY to Base64.encodeBytes(record.keyPair.publicKey.serialize()), - PRIVATE_KEY to Base64.encodeBytes(record.keyPair.privateKey.serialize()) + PUBLIC_KEY to Base64.encodeWithPadding(record.keyPair.publicKey.serialize()), + PRIVATE_KEY to Base64.encodeWithPadding(record.keyPair.privateKey.serialize()) ) writableDatabase.replace(TABLE_NAME, null, contentValues) diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/PaymentTable.java b/app/src/main/java/org/thoughtcrime/securesms/database/PaymentTable.java index a6590a9cc7..2fa52aa55b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/PaymentTable.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/PaymentTable.java @@ -32,7 +32,7 @@ import org.thoughtcrime.securesms.payments.Payment; import org.thoughtcrime.securesms.payments.State; import org.thoughtcrime.securesms.payments.proto.PaymentMetaData; import org.thoughtcrime.securesms.recipients.RecipientId; -import org.thoughtcrime.securesms.util.Base64; +import org.signal.core.util.Base64; import org.thoughtcrime.securesms.util.livedata.LiveDataUtil; import org.whispersystems.signalservice.api.payments.Money; import org.whispersystems.signalservice.api.util.UuidUtil; @@ -239,7 +239,7 @@ public final class PaymentTable extends DatabaseTable implements RecipientIdData } if (receipt != null) { values.put(RECEIPT, receipt); - values.put(PUBLIC_KEY, Base64.encodeBytes(PaymentMetaDataUtil.receiptPublic(PaymentMetaDataUtil.fromReceipt(receipt)))); + values.put(PUBLIC_KEY, Base64.encodeWithPadding(PaymentMetaDataUtil.receiptPublic(PaymentMetaDataUtil.fromReceipt(receipt)))); } else { values.putNull(RECEIPT); values.putNull(PUBLIC_KEY); @@ -468,7 +468,7 @@ public final class PaymentTable extends DatabaseTable implements RecipientIdData values.put(TRANSACTION, transaction); values.put(RECEIPT, receipt); try { - values.put(PUBLIC_KEY, Base64.encodeBytes(PaymentMetaDataUtil.receiptPublic(PaymentMetaDataUtil.fromReceipt(receipt)))); + values.put(PUBLIC_KEY, Base64.encodeWithPadding(PaymentMetaDataUtil.receiptPublic(PaymentMetaDataUtil.fromReceipt(receipt)))); values.put(META_DATA, PaymentMetaDataUtil.fromReceiptAndTransaction(receipt, transaction).encode()); } catch (SerializationException e) { throw new IllegalArgumentException(e); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/RecipientTable.kt b/app/src/main/java/org/thoughtcrime/securesms/database/RecipientTable.kt index 03ff8123af..1f8cafa905 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/RecipientTable.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/RecipientTable.kt @@ -10,6 +10,7 @@ import androidx.annotation.VisibleForTesting import androidx.core.content.contentValuesOf import app.cash.exhaustive.Exhaustive import okio.ByteString.Companion.toByteString +import org.signal.core.util.Base64 import org.signal.core.util.Bitmask import org.signal.core.util.CursorUtil import org.signal.core.util.SqlUtil @@ -93,7 +94,6 @@ import org.thoughtcrime.securesms.service.webrtc.links.CallLinkRoomId import org.thoughtcrime.securesms.storage.StorageRecordUpdate import org.thoughtcrime.securesms.storage.StorageSyncHelper import org.thoughtcrime.securesms.storage.StorageSyncModels -import org.thoughtcrime.securesms.util.Base64 import org.thoughtcrime.securesms.util.FeatureFlags import org.thoughtcrime.securesms.util.GroupUtil import org.thoughtcrime.securesms.util.IdentityUtil @@ -530,7 +530,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da ContentValues().apply { put(TYPE, RecipientType.DISTRIBUTION_LIST.id) put(DISTRIBUTION_LIST_ID, distributionListId.serialize()) - put(STORAGE_SERVICE_ID, Base64.encodeBytes(storageId ?: StorageSyncHelper.generateKey())) + put(STORAGE_SERVICE_ID, Base64.encodeWithPadding(storageId ?: StorageSyncHelper.generateKey())) put(PROFILE_SHARING, 1) } ).recipientId @@ -596,7 +596,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da } else { put(TYPE, RecipientType.GV1.id) } - put(STORAGE_SERVICE_ID, Base64.encodeBytes(StorageSyncHelper.generateKey())) + put(STORAGE_SERVICE_ID, Base64.encodeWithPadding(StorageSyncHelper.generateKey())) } } @@ -716,7 +716,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da } fun getByStorageId(storageId: ByteArray): RecipientRecord? { - val result = getRecordForSync("$TABLE_NAME.$STORAGE_SERVICE_ID = ?", arrayOf(Base64.encodeBytes(storageId))) + val result = getRecordForSync("$TABLE_NAME.$STORAGE_SERVICE_ID = ?", arrayOf(Base64.encodeWithPadding(storageId))) return if (result.isNotEmpty()) { result[0] @@ -774,7 +774,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da val query = "$ID = ?" for ((key, value) in storageIds) { val values = ContentValues().apply { - put(STORAGE_SERVICE_ID, Base64.encodeBytes(value.raw)) + put(STORAGE_SERVICE_ID, Base64.encodeWithPadding(value.raw)) } db.update(TABLE_NAME, values, query, arrayOf(key.serialize())) } @@ -826,13 +826,13 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da val values = getValuesForStorageContact(update.new, false) try { - val updateCount = db.update(TABLE_NAME, values, "$STORAGE_SERVICE_ID = ?", arrayOf(Base64.encodeBytes(update.old.id.raw))) + val updateCount = db.update(TABLE_NAME, values, "$STORAGE_SERVICE_ID = ?", arrayOf(Base64.encodeWithPadding(update.old.id.raw))) if (updateCount < 1) { throw AssertionError("Had an update, but it didn't match any rows!") } } catch (e: SQLiteConstraintException) { Log.w(TAG, "[applyStorageSyncContactUpdate] Failed to update a user by storageId.") - var recipientId = getByColumn(STORAGE_SERVICE_ID, Base64.encodeBytes(update.old.id.raw)).get() + var recipientId = getByColumn(STORAGE_SERVICE_ID, Base64.encodeWithPadding(update.old.id.raw)).get() Log.w(TAG, "[applyStorageSyncContactUpdate] Found user $recipientId. Possibly merging.") recipientId = getAndPossiblyMergePnpVerified(update.new.aci.orElse(null), update.new.pni.orElse(null), update.new.number.orElse(null)) @@ -885,7 +885,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da fun applyStorageSyncGroupV1Update(update: StorageRecordUpdate) { val values = getValuesForStorageGroupV1(update.new, false) - val updateCount = writableDatabase.update(TABLE_NAME, values, STORAGE_SERVICE_ID + " = ?", arrayOf(Base64.encodeBytes(update.old.id.raw))) + val updateCount = writableDatabase.update(TABLE_NAME, values, STORAGE_SERVICE_ID + " = ?", arrayOf(Base64.encodeWithPadding(update.old.id.raw))) if (updateCount < 1) { throw AssertionError("Had an update, but it didn't match any rows!") } @@ -929,7 +929,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da fun applyStorageSyncGroupV2Update(update: StorageRecordUpdate) { val values = getValuesForStorageGroupV2(update.new, false) - val updateCount = writableDatabase.update(TABLE_NAME, values, "$STORAGE_SERVICE_ID = ?", arrayOf(Base64.encodeBytes(update.old.id.raw))) + val updateCount = writableDatabase.update(TABLE_NAME, values, "$STORAGE_SERVICE_ID = ?", arrayOf(Base64.encodeWithPadding(update.old.id.raw))) if (updateCount < 1) { throw AssertionError("Had an update, but it didn't match any rows!") } @@ -951,7 +951,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da val profileName = ProfileName.fromParts(update.new.givenName.orElse(null), update.new.familyName.orElse(null)) val localKey = ProfileKeyUtil.profileKeyOptional(update.old.profileKey.orElse(null)) val remoteKey = ProfileKeyUtil.profileKeyOptional(update.new.profileKey.orElse(null)) - val profileKey: String? = remoteKey.or(localKey).map { obj: ProfileKey -> obj.serialize() }.map { source: ByteArray? -> Base64.encodeBytes(source!!) }.orElse(null) + val profileKey: String? = remoteKey.or(localKey).map { obj: ProfileKey -> obj.serialize() }.map { source: ByteArray? -> Base64.encodeWithPadding(source!!) }.orElse(null) if (!remoteKey.isPresent) { Log.w(TAG, "Got an empty profile key while applying an account record update! The parsed local key is ${if (localKey.isPresent) "present" else "not present"}. The raw local key is ${if (update.old.profileKey.isPresent) "present" else "not present"}. The resulting key is ${if (profileKey != null) "present" else "not present"}.") } @@ -968,10 +968,10 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da } put(USERNAME, update.new.username) - put(STORAGE_SERVICE_ID, Base64.encodeBytes(update.new.id.raw)) + put(STORAGE_SERVICE_ID, Base64.encodeWithPadding(update.new.id.raw)) if (update.new.hasUnknownFields()) { - put(STORAGE_SERVICE_PROTO, Base64.encodeBytes(Objects.requireNonNull(update.new.serializeUnknownFields()))) + put(STORAGE_SERVICE_PROTO, Base64.encodeWithPadding(Objects.requireNonNull(update.new.serializeUnknownFields()))) } else { putNull(STORAGE_SERVICE_PROTO) } @@ -985,7 +985,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da .run() } - val updateCount = writableDatabase.update(TABLE_NAME, values, "$STORAGE_SERVICE_ID = ?", arrayOf(Base64.encodeBytes(update.old.id.raw))) + val updateCount = writableDatabase.update(TABLE_NAME, values, "$STORAGE_SERVICE_ID = ?", arrayOf(Base64.encodeWithPadding(update.old.id.raw))) if (updateCount < 1) { throw AssertionError("Account update didn't match any rows!") } @@ -1019,7 +1019,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da val values = contentValuesOf(STORAGE_SERVICE_ID to null) var updated = 0 - SqlUtil.buildCollectionQuery(STORAGE_SERVICE_ID, storageIds.map { Base64.encodeBytes(it.raw) }, "$UNREGISTERED_TIMESTAMP > 0 AND") + SqlUtil.buildCollectionQuery(STORAGE_SERVICE_ID, storageIds.map { Base64.encodeWithPadding(it.raw) }, "$UNREGISTERED_TIMESTAMP > 0 AND") .forEach { updated += writableDatabase.update(TABLE_NAME, values, it.where, it.whereArgs) } @@ -1048,7 +1048,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da private fun getByStorageKeyOrThrow(storageKey: ByteArray): RecipientId { val query = "$STORAGE_SERVICE_ID = ?" - val args = arrayOf(Base64.encodeBytes(storageKey)) + val args = arrayOf(Base64.encodeWithPadding(storageKey)) readableDatabase.query(TABLE_NAME, ID_PROJECTION, query, args, null, null, null).use { cursor -> return if (cursor != null && cursor.moveToFirst()) { @@ -1500,7 +1500,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da fun setProfileKey(id: RecipientId, profileKey: ProfileKey): Boolean { val selection = "$ID = ?" val args = arrayOf(id.serialize()) - val encodedProfileKey = Base64.encodeBytes(profileKey.serialize()) + val encodedProfileKey = Base64.encodeWithPadding(profileKey.serialize()) val valuesToCompare = ContentValues(1).apply { put(PROFILE_KEY, encodedProfileKey) } @@ -1537,7 +1537,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da val selection = "$ID = ? AND $PROFILE_KEY is NULL" val args = arrayOf(id.serialize()) val valuesToSet = ContentValues(3).apply { - put(PROFILE_KEY, Base64.encodeBytes(profileKey.serialize())) + put(PROFILE_KEY, Base64.encodeWithPadding(profileKey.serialize())) putNull(EXPIRING_PROFILE_KEY_CREDENTIAL) put(SEALED_SENDER_MODE, UnidentifiedAccessMode.UNKNOWN.mode) } @@ -1560,13 +1560,13 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da expiringProfileKeyCredential: ExpiringProfileKeyCredential ): Boolean { val selection = "$ID = ? AND $PROFILE_KEY = ?" - val args = arrayOf(id.serialize(), Base64.encodeBytes(profileKey.serialize())) + val args = arrayOf(id.serialize(), Base64.encodeWithPadding(profileKey.serialize())) val columnData = ExpiringProfileKeyCredentialColumnData.Builder() .profileKey(profileKey.serialize().toByteString()) .expiringProfileKeyCredential(expiringProfileKeyCredential.serialize().toByteString()) .build() val values = ContentValues(1).apply { - put(EXPIRING_PROFILE_KEY_CREDENTIAL, Base64.encodeBytes(columnData.encode())) + put(EXPIRING_PROFILE_KEY_CREDENTIAL, Base64.encodeWithPadding(columnData.encode())) } val updateQuery = SqlUtil.buildTrueUpdateQuery(selection, args, values) @@ -3492,7 +3492,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da try { for ((key, value) in ids) { val values = ContentValues().apply { - put(STORAGE_SERVICE_ID, Base64.encodeBytes(value!!)) + put(STORAGE_SERVICE_ID, Base64.encodeWithPadding(value!!)) } db.update(TABLE_NAME, values, ID_WHERE, arrayOf(key.serialize())) } @@ -3639,7 +3639,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da */ fun rotateStorageId(recipientId: RecipientId) { val values = ContentValues(1).apply { - put(STORAGE_SERVICE_ID, Base64.encodeBytes(StorageSyncHelper.generateKey())) + put(STORAGE_SERVICE_ID, Base64.encodeWithPadding(StorageSyncHelper.generateKey())) } val query = "$ID = ? AND ($TYPE IN (?, ?, ?) OR $REGISTERED = ?)" @@ -3652,7 +3652,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da */ fun setStorageIdIfNotSet(recipientId: RecipientId) { val values = ContentValues(1).apply { - put(STORAGE_SERVICE_ID, Base64.encodeBytes(StorageSyncHelper.generateKey())) + put(STORAGE_SERVICE_ID, Base64.encodeWithPadding(StorageSyncHelper.generateKey())) } val query = "$ID = ? AND $STORAGE_SERVICE_ID IS NULL" @@ -3840,7 +3840,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da E164 to e164, ACI_COLUMN to aci?.toString(), PNI_COLUMN to pni?.toString(), - STORAGE_SERVICE_ID to Base64.encodeBytes(StorageSyncHelper.generateKey()), + STORAGE_SERVICE_ID to Base64.encodeWithPadding(StorageSyncHelper.generateKey()), AVATAR_COLOR to AvatarColorHash.forAddress((aci ?: pni)?.toString(), e164).serialize() ) @@ -3868,16 +3868,16 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da put(SYSTEM_FAMILY_NAME, systemName.familyName) put(SYSTEM_JOINED_NAME, systemName.toString()) put(SYSTEM_NICKNAME, contact.systemNickname.orElse(null)) - put(PROFILE_KEY, contact.profileKey.map { source -> Base64.encodeBytes(source) }.orElse(null)) + put(PROFILE_KEY, contact.profileKey.map { source -> Base64.encodeWithPadding(source) }.orElse(null)) put(USERNAME, if (TextUtils.isEmpty(username)) null else username) put(PROFILE_SHARING, if (contact.isProfileSharingEnabled) "1" else "0") put(BLOCKED, if (contact.isBlocked) "1" else "0") put(MUTE_UNTIL, contact.muteUntil) - put(STORAGE_SERVICE_ID, Base64.encodeBytes(contact.id.raw)) + put(STORAGE_SERVICE_ID, Base64.encodeWithPadding(contact.id.raw)) put(HIDDEN, contact.isHidden) if (contact.hasUnknownFields()) { - put(STORAGE_SERVICE_PROTO, Base64.encodeBytes(Objects.requireNonNull(contact.serializeUnknownFields()))) + put(STORAGE_SERVICE_PROTO, Base64.encodeWithPadding(Objects.requireNonNull(contact.serializeUnknownFields()))) } else { putNull(STORAGE_SERVICE_PROTO) } @@ -3906,10 +3906,10 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da put(PROFILE_SHARING, if (groupV1.isProfileSharingEnabled) "1" else "0") put(BLOCKED, if (groupV1.isBlocked) "1" else "0") put(MUTE_UNTIL, groupV1.muteUntil) - put(STORAGE_SERVICE_ID, Base64.encodeBytes(groupV1.id.raw)) + put(STORAGE_SERVICE_ID, Base64.encodeWithPadding(groupV1.id.raw)) if (groupV1.hasUnknownFields()) { - put(STORAGE_SERVICE_PROTO, Base64.encodeBytes(groupV1.serializeUnknownFields())) + put(STORAGE_SERVICE_PROTO, Base64.encodeWithPadding(groupV1.serializeUnknownFields())) } else { putNull(STORAGE_SERVICE_PROTO) } @@ -3929,11 +3929,11 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da put(PROFILE_SHARING, if (groupV2.isProfileSharingEnabled) "1" else "0") put(BLOCKED, if (groupV2.isBlocked) "1" else "0") put(MUTE_UNTIL, groupV2.muteUntil) - put(STORAGE_SERVICE_ID, Base64.encodeBytes(groupV2.id.raw)) + put(STORAGE_SERVICE_ID, Base64.encodeWithPadding(groupV2.id.raw)) put(MENTION_SETTING, if (groupV2.notifyForMentionsWhenMuted()) MentionSetting.ALWAYS_NOTIFY.id else MentionSetting.DO_NOT_NOTIFY.id) if (groupV2.hasUnknownFields()) { - put(STORAGE_SERVICE_PROTO, Base64.encodeBytes(groupV2.serializeUnknownFields())) + put(STORAGE_SERVICE_PROTO, Base64.encodeWithPadding(groupV2.serializeUnknownFields())) } else { putNull(STORAGE_SERVICE_PROTO) } @@ -4250,7 +4250,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da private fun updateProfileValuesForMerge(values: ContentValues, record: RecipientRecord) { values.apply { - put(PROFILE_KEY, if (record.profileKey != null) Base64.encodeBytes(record.profileKey) else null) + put(PROFILE_KEY, if (record.profileKey != null) Base64.encodeWithPadding(record.profileKey) else null) putNull(EXPIRING_PROFILE_KEY_CREDENTIAL) put(PROFILE_AVATAR, record.signalProfileAvatar) put(PROFILE_GIVEN_NAME, record.signalProfileName.givenName) diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/SignedPreKeyTable.kt b/app/src/main/java/org/thoughtcrime/securesms/database/SignedPreKeyTable.kt index bfa4404957..01d64f2b9d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/SignedPreKeyTable.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/SignedPreKeyTable.kt @@ -2,6 +2,7 @@ package org.thoughtcrime.securesms.database import android.content.Context import androidx.core.content.contentValuesOf +import org.signal.core.util.Base64 import org.signal.core.util.SqlUtil import org.signal.core.util.logging.Log import org.signal.core.util.requireInt @@ -11,7 +12,6 @@ import org.signal.libsignal.protocol.InvalidKeyException import org.signal.libsignal.protocol.ecc.Curve import org.signal.libsignal.protocol.ecc.ECKeyPair import org.signal.libsignal.protocol.state.SignedPreKeyRecord -import org.thoughtcrime.securesms.util.Base64 import org.whispersystems.signalservice.api.push.ServiceId import java.io.IOException import java.util.LinkedList @@ -88,9 +88,9 @@ class SignedPreKeyTable(context: Context, databaseHelper: SignalDatabase) : Data val contentValues = contentValuesOf( ACCOUNT_ID to serviceId.toString(), KEY_ID to keyId, - PUBLIC_KEY to Base64.encodeBytes(record.keyPair.publicKey.serialize()), - PRIVATE_KEY to Base64.encodeBytes(record.keyPair.privateKey.serialize()), - SIGNATURE to Base64.encodeBytes(record.signature), + PUBLIC_KEY to Base64.encodeWithPadding(record.keyPair.publicKey.serialize()), + PRIVATE_KEY to Base64.encodeWithPadding(record.keyPair.privateKey.serialize()), + SIGNATURE to Base64.encodeWithPadding(record.signature), TIMESTAMP to record.timestamp ) writableDatabase.replace(TABLE_NAME, null, contentValues) diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/UnknownStorageIdTable.java b/app/src/main/java/org/thoughtcrime/securesms/database/UnknownStorageIdTable.java index 03124661e7..a5098dc091 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/UnknownStorageIdTable.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/UnknownStorageIdTable.java @@ -8,7 +8,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import org.signal.core.util.CursorUtil; -import org.thoughtcrime.securesms.util.Base64; +import org.signal.core.util.Base64; import org.signal.core.util.SqlUtil; import org.whispersystems.signalservice.api.storage.SignalStorageRecord; import org.whispersystems.signalservice.api.storage.StorageId; @@ -84,7 +84,7 @@ public class UnknownStorageIdTable extends DatabaseTable { public @Nullable SignalStorageRecord getById(@NonNull byte[] rawId) { String query = STORAGE_ID + " = ?"; - String[] args = new String[] { Base64.encodeBytes(rawId) }; + String[] args = new String[] { Base64.encodeWithPadding(rawId) }; try (Cursor cursor = databaseHelper.getSignalReadableDatabase().query(TABLE_NAME, null, query, args, null, null, null)) { if (cursor != null && cursor.moveToFirst()) { @@ -104,7 +104,7 @@ public class UnknownStorageIdTable extends DatabaseTable { for (SignalStorageRecord insert : inserts) { ContentValues values = new ContentValues(); values.put(TYPE, insert.getType()); - values.put(STORAGE_ID, Base64.encodeBytes(insert.getId().getRaw())); + values.put(STORAGE_ID, Base64.encodeWithPadding(insert.getId().getRaw())); db.insert(TABLE_NAME, null, values); } @@ -117,7 +117,7 @@ public class UnknownStorageIdTable extends DatabaseTable { Preconditions.checkArgument(db.inTransaction(), "Must be in a transaction!"); for (StorageId id : deletes) { - String[] args = SqlUtil.buildArgs(Base64.encodeBytes(id.getRaw())); + String[] args = SqlUtil.buildArgs(Base64.encodeWithPadding(id.getRaw())); db.delete(TABLE_NAME, deleteQuery, args); } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/documents/IdentityKeyMismatch.java b/app/src/main/java/org/thoughtcrime/securesms/database/documents/IdentityKeyMismatch.java index ba05bece8c..e9b1157787 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/documents/IdentityKeyMismatch.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/documents/IdentityKeyMismatch.java @@ -21,7 +21,7 @@ import org.signal.libsignal.protocol.IdentityKey; import org.signal.libsignal.protocol.InvalidKeyException; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; -import org.thoughtcrime.securesms.util.Base64; +import org.signal.core.util.Base64; import java.io.IOException; import java.util.Objects; @@ -83,7 +83,7 @@ public class IdentityKeyMismatch { public void serialize(IdentityKey value, JsonGenerator jsonGenerator, SerializerProvider serializers) throws IOException { - jsonGenerator.writeString(Base64.encodeBytes(value.serialize())); + jsonGenerator.writeString(Base64.encodeWithPadding(value.serialize())); } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/ClassicOpenHelper.java b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/ClassicOpenHelper.java index 9ddecdc9ad..b74a574e9f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/ClassicOpenHelper.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/ClassicOpenHelper.java @@ -44,7 +44,7 @@ import org.thoughtcrime.securesms.groups.GroupId; import org.thoughtcrime.securesms.migrations.LegacyMigrationJob; import org.thoughtcrime.securesms.permissions.Permissions; import org.thoughtcrime.securesms.phonenumbers.NumberUtil; -import org.thoughtcrime.securesms.util.Base64; +import org.signal.core.util.Base64; import org.thoughtcrime.securesms.util.DelimiterUtil; import org.thoughtcrime.securesms.util.JsonUtils; import org.thoughtcrime.securesms.util.MediaUtil; @@ -379,8 +379,8 @@ public class ClassicOpenHelper extends SQLiteOpenHelper { if (identityKey != null) { MasterCipher masterCipher = new MasterCipher(masterSecret); - String identityKeyString = Base64.encodeBytes(identityKey.serialize()); - String macString = Base64.encodeBytes(masterCipher.getMacFor(recipientId + + String identityKeyString = Base64.encodeWithPadding(identityKey.serialize()); + String macString = Base64.encodeWithPadding(masterCipher.getMacFor(recipientId + identityKeyString)); db.execSQL("REPLACE INTO identities (recipient, key, mac) VALUES (?, ?, ?)", diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/PreKeyMigrationHelper.java b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/PreKeyMigrationHelper.java index ad97b7088b..1e8f532ac4 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/PreKeyMigrationHelper.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/PreKeyMigrationHelper.java @@ -19,7 +19,7 @@ import org.signal.libsignal.protocol.state.SignedPreKeyRecord; import org.thoughtcrime.securesms.database.OneTimePreKeyTable; import org.thoughtcrime.securesms.database.SignedPreKeyTable; import org.thoughtcrime.securesms.keyvalue.SignalStore; -import org.thoughtcrime.securesms.util.Base64; +import org.signal.core.util.Base64; import org.thoughtcrime.securesms.util.JsonUtils; import java.io.File; @@ -49,8 +49,8 @@ public final class PreKeyMigrationHelper { ContentValues contentValues = new ContentValues(); contentValues.put(OneTimePreKeyTable.KEY_ID, preKey.getId()); - contentValues.put(OneTimePreKeyTable.PUBLIC_KEY, Base64.encodeBytes(preKey.getKeyPair().getPublicKey().serialize())); - contentValues.put(OneTimePreKeyTable.PRIVATE_KEY, Base64.encodeBytes(preKey.getKeyPair().getPrivateKey().serialize())); + contentValues.put(OneTimePreKeyTable.PUBLIC_KEY, Base64.encodeWithPadding(preKey.getKeyPair().getPublicKey().serialize())); + contentValues.put(OneTimePreKeyTable.PRIVATE_KEY, Base64.encodeWithPadding(preKey.getKeyPair().getPrivateKey().serialize())); database.insert(OneTimePreKeyTable.TABLE_NAME, null, contentValues); Log.i(TAG, "Migrated one-time prekey: " + preKey.getId()); } catch (IOException | InvalidMessageException | InvalidKeyException e) { @@ -71,9 +71,9 @@ public final class PreKeyMigrationHelper { ContentValues contentValues = new ContentValues(); contentValues.put(SignedPreKeyTable.KEY_ID, signedPreKey.getId()); - contentValues.put(SignedPreKeyTable.PUBLIC_KEY, Base64.encodeBytes(signedPreKey.getKeyPair().getPublicKey().serialize())); - contentValues.put(SignedPreKeyTable.PRIVATE_KEY, Base64.encodeBytes(signedPreKey.getKeyPair().getPrivateKey().serialize())); - contentValues.put(SignedPreKeyTable.SIGNATURE, Base64.encodeBytes(signedPreKey.getSignature())); + contentValues.put(SignedPreKeyTable.PUBLIC_KEY, Base64.encodeWithPadding(signedPreKey.getKeyPair().getPublicKey().serialize())); + contentValues.put(SignedPreKeyTable.PRIVATE_KEY, Base64.encodeWithPadding(signedPreKey.getKeyPair().getPrivateKey().serialize())); + contentValues.put(SignedPreKeyTable.SIGNATURE, Base64.encodeWithPadding(signedPreKey.getSignature())); contentValues.put(SignedPreKeyTable.TIMESTAMP, signedPreKey.getTimestamp()); database.insert(SignedPreKeyTable.TABLE_NAME, null, contentValues); Log.i(TAG, "Migrated signed prekey: " + signedPreKey.getId()); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherMigrationHelper.java b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherMigrationHelper.java index 3a457ccbe1..3c47272b3d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherMigrationHelper.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherMigrationHelper.java @@ -26,7 +26,7 @@ import org.thoughtcrime.securesms.jobs.UnableToStartException; import org.thoughtcrime.securesms.migrations.LegacyMigrationJob; import org.thoughtcrime.securesms.service.GenericForegroundService; import org.thoughtcrime.securesms.service.NotificationController; -import org.thoughtcrime.securesms.util.Base64; +import org.signal.core.util.Base64; import org.thoughtcrime.securesms.util.TextSecurePreferences; import java.io.IOException; @@ -125,7 +125,7 @@ public class SQLCipherMigrationHelper { plaintext = legacyCipher.decryptBytes(Base64.decode(mediaKey)); } - row.put("cd", Base64.encodeBytes(plaintext)); + row.put("cd", Base64.encodeWithPadding(plaintext)); } } catch (IOException | InvalidMessageException e) { Log.w(TAG, e); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/migration/V149_LegacyMigrations.kt b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/migration/V149_LegacyMigrations.kt index 35e6607b4f..586de5f086 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/migration/V149_LegacyMigrations.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/migration/V149_LegacyMigrations.kt @@ -15,6 +15,7 @@ import android.text.TextUtils import androidx.core.content.contentValuesOf import com.annimon.stream.Stream import net.zetetic.database.sqlcipher.SQLiteDatabase +import org.signal.core.util.Base64 import org.signal.core.util.CursorUtil import org.signal.core.util.Hex import org.signal.core.util.SqlUtil @@ -41,7 +42,6 @@ import org.thoughtcrime.securesms.notifications.NotificationChannels import org.thoughtcrime.securesms.phonenumbers.PhoneNumberFormatter import org.thoughtcrime.securesms.profiles.ProfileName import org.thoughtcrime.securesms.storage.StorageSyncHelper -import org.thoughtcrime.securesms.util.Base64 import org.thoughtcrime.securesms.util.FileUtils import org.thoughtcrime.securesms.util.ServiceUtil import org.thoughtcrime.securesms.util.Triple @@ -825,7 +825,7 @@ object V149_LegacyMigrations : SignalDatabaseMigration { val encodedProfileKey = PreferenceManager.getDefaultSharedPreferences(context).getString("pref_profile_key", null) val profileKey = if (encodedProfileKey != null) Base64.decodeOrThrow(encodedProfileKey) else Util.getSecretBytes(32) val values = ContentValues(1).apply { - put("profile_key", Base64.encodeBytes(profileKey)) + put("profile_key", Base64.encodeWithPadding(profileKey)) } if (db.update("recipient", values, "phone = ?", arrayOf(localNumber)) == 0) { throw AssertionError("No rows updated!") @@ -851,7 +851,7 @@ object V149_LegacyMigrations : SignalDatabaseMigration { val id: String = cursor.getString(cursor.getColumnIndexOrThrow("_id")) val values = ContentValues(2).apply { put("dirty", 2) - put("storage_service_key", Base64.encodeBytes(StorageSyncHelper.generateKey())) + put("storage_service_key", Base64.encodeWithPadding(StorageSyncHelper.generateKey())) } db.update("recipient", values, "_id = ?", arrayOf(id)) } @@ -1434,7 +1434,7 @@ object V149_LegacyMigrations : SignalDatabaseMigration { insertCount = cursor.count while (cursor.moveToNext()) { val insertValues = ContentValues().apply { - put("storage_service_key", Base64.encodeBytes(StorageSyncHelper.generateKey())) + put("storage_service_key", Base64.encodeWithPadding(StorageSyncHelper.generateKey())) } val id: Long = cursor.getLong(cursor.getColumnIndexOrThrow("_id")) db.update("recipient", insertValues, "_id = ?", SqlUtil.buildArgs(id)) @@ -1445,7 +1445,7 @@ object V149_LegacyMigrations : SignalDatabaseMigration { updateCount = cursor.count while (cursor.moveToNext()) { val updateValues = ContentValues().apply { - put("storage_service_key", Base64.encodeBytes(StorageSyncHelper.generateKey())) + put("storage_service_key", Base64.encodeWithPadding(StorageSyncHelper.generateKey())) } val id: Long = cursor.getLong(cursor.getColumnIndexOrThrow("_id")) db.update("recipient", updateValues, "_id = ?", SqlUtil.buildArgs(id)) @@ -2445,7 +2445,7 @@ object V149_LegacyMigrations : SignalDatabaseMigration { null, contentValuesOf( "distribution_list_id" to 1L, - "storage_service_key" to Base64.encodeBytes(StorageSyncHelper.generateKey()), + "storage_service_key" to Base64.encodeWithPadding(StorageSyncHelper.generateKey()), "profile_sharing" to 1 ) ) diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/migration/V151_MyStoryMigration.kt b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/migration/V151_MyStoryMigration.kt index c0392866b8..ab2b83114b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/migration/V151_MyStoryMigration.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/migration/V151_MyStoryMigration.kt @@ -4,11 +4,11 @@ import android.app.Application import android.database.Cursor import androidx.core.content.contentValuesOf import net.zetetic.database.sqlcipher.SQLiteDatabase +import org.signal.core.util.Base64 import org.signal.core.util.CursorUtil import org.signal.core.util.SqlUtil import org.signal.core.util.logging.Log import org.thoughtcrime.securesms.storage.StorageSyncHelper -import org.thoughtcrime.securesms.util.Base64 /** * Performs a check and ensures that MyStory exists at the correct distribution list id and correct distribution id. @@ -87,7 +87,7 @@ object V151_MyStoryMigration : SignalDatabaseMigration { contentValuesOf( "group_type" to 4, "distribution_list_id" to MY_STORY_DISTRIBUTION_LIST_ID, - "storage_service_key" to Base64.encodeBytes(StorageSyncHelper.generateKey()), + "storage_service_key" to Base64.encodeWithPadding(StorageSyncHelper.generateKey()), "profile_sharing" to 1 ) ) diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/migration/V153_MyStoryMigration.kt b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/migration/V153_MyStoryMigration.kt index 93b5be18ea..59de4a9e5e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/migration/V153_MyStoryMigration.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/migration/V153_MyStoryMigration.kt @@ -4,11 +4,11 @@ import android.app.Application import android.database.Cursor import androidx.core.content.contentValuesOf import net.zetetic.database.sqlcipher.SQLiteDatabase +import org.signal.core.util.Base64 import org.signal.core.util.CursorUtil import org.signal.core.util.SqlUtil import org.signal.core.util.logging.Log import org.thoughtcrime.securesms.storage.StorageSyncHelper -import org.thoughtcrime.securesms.util.Base64 /** * Performs a check and ensures that MyStory exists at the correct distribution list id and correct distribution id. @@ -87,7 +87,7 @@ object V153_MyStoryMigration : SignalDatabaseMigration { contentValuesOf( "group_type" to 4, "distribution_list_id" to MY_STORY_DISTRIBUTION_LIST_ID, - "storage_service_key" to Base64.encodeBytes(StorageSyncHelper.generateKey()), + "storage_service_key" to Base64.encodeWithPadding(StorageSyncHelper.generateKey()), "profile_sharing" to 1 ) ) diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/loaders/DeviceListLoader.java b/app/src/main/java/org/thoughtcrime/securesms/database/loaders/DeviceListLoader.java index 5a7c3656a1..9d3da9efb4 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/loaders/DeviceListLoader.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/loaders/DeviceListLoader.java @@ -18,7 +18,7 @@ import org.signal.libsignal.protocol.util.ByteUtil; import org.thoughtcrime.securesms.devicelist.Device; import org.thoughtcrime.securesms.keyvalue.SignalStore; import org.thoughtcrime.securesms.util.AsyncLoader; -import org.thoughtcrime.securesms.util.Base64; +import org.signal.core.util.Base64; import org.whispersystems.signalservice.api.SignalServiceAccountManager; import org.whispersystems.signalservice.api.messages.multidevice.DeviceInfo; import org.whispersystems.signalservice.api.push.SignalServiceAddress; diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/model/BodyRangeListSerializer.kt b/app/src/main/java/org/thoughtcrime/securesms/database/model/BodyRangeListSerializer.kt index 69b4cb0f24..5f0ee2a43f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/model/BodyRangeListSerializer.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/model/BodyRangeListSerializer.kt @@ -1,11 +1,11 @@ package org.thoughtcrime.securesms.database.model +import org.signal.core.util.Base64 import org.signal.core.util.StringSerializer import org.thoughtcrime.securesms.database.model.databaseprotos.BodyRangeList -import org.thoughtcrime.securesms.util.Base64 object BodyRangeListSerializer : StringSerializer { - override fun serialize(data: BodyRangeList): String = Base64.encodeBytes(data.encode()) + override fun serialize(data: BodyRangeList): String = Base64.encodeWithPadding(data.encode()) override fun deserialize(data: String): BodyRangeList = BodyRangeList.ADAPTER.decode(Base64.decode(data)) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/model/GroupCallUpdateDetailsUtil.java b/app/src/main/java/org/thoughtcrime/securesms/database/model/GroupCallUpdateDetailsUtil.java index 361f468f79..d549cc2eb3 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/model/GroupCallUpdateDetailsUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/model/GroupCallUpdateDetailsUtil.java @@ -5,7 +5,7 @@ import androidx.annotation.Nullable; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.database.model.databaseprotos.GroupCallUpdateDetails; -import org.thoughtcrime.securesms.util.Base64; +import org.signal.core.util.Base64; import java.io.IOException; import java.util.List; @@ -38,6 +38,6 @@ public final class GroupCallUpdateDetailsUtil { .isCallFull(isCallFull) .inCallUuids(inCallUuids); - return Base64.encodeBytes(builder.build().encode()); + return Base64.encodeWithPadding(builder.build().encode()); } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java b/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java index 7810aaee8a..b2f417d090 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java @@ -56,7 +56,7 @@ import org.thoughtcrime.securesms.phonenumbers.PhoneNumberFormatter; import org.thoughtcrime.securesms.profiles.ProfileName; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; -import org.thoughtcrime.securesms.util.Base64; +import org.signal.core.util.Base64; import org.thoughtcrime.securesms.util.DateUtils; import org.thoughtcrime.securesms.util.ExpirationUtil; import org.thoughtcrime.securesms.util.GroupUtil; @@ -508,7 +508,7 @@ public abstract class MessageRecord extends DisplayRecord { List deleteRequestingMembers = new ArrayList<>(change.deleteRequestingMembers); deleteRequestingMembers.add(id); - return Base64.encodeBytes(decryptedGroupV2Context.newBuilder() + return Base64.encodeWithPadding(decryptedGroupV2Context.newBuilder() .change(change.newBuilder() .revision(revision) .deleteRequestingMembers(deleteRequestingMembers) diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/v2/GroupInviteLinkUrl.java b/app/src/main/java/org/thoughtcrime/securesms/groups/v2/GroupInviteLinkUrl.java index 325239f176..0a773f84ef 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/v2/GroupInviteLinkUrl.java +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/v2/GroupInviteLinkUrl.java @@ -3,11 +3,11 @@ package org.thoughtcrime.securesms.groups.v2; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import org.signal.core.util.Base64; import org.signal.libsignal.zkgroup.InvalidInputException; import org.signal.libsignal.zkgroup.groups.GroupMasterKey; import org.signal.storageservice.protos.groups.GroupInviteLink; import org.signal.storageservice.protos.groups.local.DecryptedGroup; -import org.whispersystems.util.Base64UrlSafe; import java.io.IOException; import java.net.URI; @@ -58,7 +58,7 @@ public final class GroupInviteLinkUrl { throw new InvalidGroupLinkException("No reference was in the uri"); } - byte[] bytes = Base64UrlSafe.decodePaddingAgnostic(encoding); + byte[] bytes = Base64.decode(encoding); GroupInviteLink groupInviteLink = GroupInviteLink.ADAPTER.decode(bytes); //noinspection SwitchStatementWithTooFewBranches @@ -112,7 +112,7 @@ public final class GroupInviteLinkUrl { .build()) .build(); - String encoding = Base64UrlSafe.encodeBytesWithoutPadding(groupInviteLink.encode()); + String encoding = Base64.encodeUrlSafeWithoutPadding(groupInviteLink.encode()); return GROUP_URL_PREFIX + encoding; } diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JsonJobData.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JsonJobData.java index 1a5dd4ad09..159e0722f6 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JsonJobData.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JsonJobData.java @@ -6,7 +6,7 @@ import androidx.annotation.Nullable; import com.fasterxml.jackson.annotation.JsonProperty; import org.signal.core.util.logging.Log; -import org.thoughtcrime.securesms.util.Base64; +import org.signal.core.util.Base64; import org.thoughtcrime.securesms.util.JsonUtils; import java.io.IOException; @@ -427,7 +427,7 @@ public class JsonJobData { } public Builder putBlobAsString(@NonNull String key, @Nullable byte[] value) { - String serialized = value != null ? Base64.encodeBytes(value) : null; + String serialized = value != null ? Base64.encodeWithPadding(value) : null; strings.put(key, serialized); return this; } diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/migrations/PushProcessMessageJobMigration.kt b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/migrations/PushProcessMessageJobMigration.kt index 4818056256..b5413368ea 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/migrations/PushProcessMessageJobMigration.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/migrations/PushProcessMessageJobMigration.kt @@ -1,13 +1,13 @@ package org.thoughtcrime.securesms.jobmanager.migrations import okio.ByteString.Companion.toByteString +import org.signal.core.util.Base64 import org.signal.core.util.logging.Log import org.thoughtcrime.securesms.jobmanager.JobMigration import org.thoughtcrime.securesms.jobmanager.JsonJobData import org.thoughtcrime.securesms.jobs.FailingJob import org.thoughtcrime.securesms.jobs.PushProcessMessageErrorJob import org.thoughtcrime.securesms.messages.MessageState -import org.thoughtcrime.securesms.util.Base64 import org.whispersystems.signalservice.api.crypto.protos.CompleteMessage import org.whispersystems.signalservice.api.crypto.protos.EnvelopeMetadata import org.whispersystems.signalservice.api.push.ServiceId diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/migrations/PushProcessMessageQueueJobMigration.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/migrations/PushProcessMessageQueueJobMigration.java index b5a0b432fc..154f3dc8e7 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/migrations/PushProcessMessageQueueJobMigration.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/migrations/PushProcessMessageQueueJobMigration.java @@ -12,7 +12,7 @@ import org.thoughtcrime.securesms.jobmanager.JobMigration; import org.thoughtcrime.securesms.jobmanager.JsonJobData; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; -import org.thoughtcrime.securesms.util.Base64; +import org.signal.core.util.Base64; import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.internal.serialize.protos.SignalServiceContentProto; diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/AccountConsistencyWorkerJob.kt b/app/src/main/java/org/thoughtcrime/securesms/jobs/AccountConsistencyWorkerJob.kt index 9b231ddfe7..2e68d7b3e9 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/AccountConsistencyWorkerJob.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/AccountConsistencyWorkerJob.kt @@ -1,12 +1,12 @@ package org.thoughtcrime.securesms.jobs +import org.signal.core.util.Base64 import org.signal.core.util.logging.Log import org.thoughtcrime.securesms.dependencies.ApplicationDependencies import org.thoughtcrime.securesms.jobmanager.Job import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint import org.thoughtcrime.securesms.keyvalue.SignalStore import org.thoughtcrime.securesms.recipients.Recipient -import org.thoughtcrime.securesms.util.Base64 import org.thoughtcrime.securesms.util.ProfileUtil import org.whispersystems.signalservice.api.profiles.SignalServiceProfile import java.io.IOException @@ -57,7 +57,7 @@ class AccountConsistencyWorkerJob private constructor(parameters: Parameters) : } val profile: SignalServiceProfile = ProfileUtil.retrieveProfileSync(context, Recipient.self(), SignalServiceProfile.RequestType.PROFILE, false).profile - val encodedPublicKey = Base64.encodeBytes(SignalStore.account().aciIdentityKey.publicKey.serialize()) + val encodedPublicKey = Base64.encodeWithPadding(SignalStore.account().aciIdentityKey.publicKey.serialize()) if (profile.identityKey != encodedPublicKey) { Log.w(TAG, "Identity key on profile differed from the one we have locally! Marking ourselves unregistered.") diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/AttachmentDownloadJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/AttachmentDownloadJob.java index 4cdcb78a8b..c4414daee5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/AttachmentDownloadJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/AttachmentDownloadJob.java @@ -34,7 +34,7 @@ import org.thoughtcrime.securesms.releasechannel.ReleaseChannel; import org.thoughtcrime.securesms.s3.S3; import org.thoughtcrime.securesms.transport.RetryLaterException; import org.thoughtcrime.securesms.util.AttachmentUtil; -import org.thoughtcrime.securesms.util.Base64; +import org.signal.core.util.Base64; import org.thoughtcrime.securesms.util.FeatureFlags; import org.thoughtcrime.securesms.util.Util; import org.whispersystems.signalservice.api.SignalServiceMessageReceiver; diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/MmsReceiveJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/MmsReceiveJob.java index d60f8b9bd2..827467cdda 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/MmsReceiveJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/MmsReceiveJob.java @@ -16,7 +16,7 @@ import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.jobmanager.JsonJobData; import org.thoughtcrime.securesms.jobmanager.Job; import org.thoughtcrime.securesms.recipients.Recipient; -import org.thoughtcrime.securesms.util.Base64; +import org.signal.core.util.Base64; import org.thoughtcrime.securesms.util.Util; import java.io.IOException; @@ -46,7 +46,7 @@ public class MmsReceiveJob extends BaseJob { @Override public @Nullable byte[] serialize() { - return new JsonJobData.Builder().putString(KEY_DATA, Base64.encodeBytes(data)) + return new JsonJobData.Builder().putString(KEY_DATA, Base64.encodeWithPadding(data)) .putInt(KEY_SUBSCRIPTION_ID, subscriptionId) .serialize(); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceVerifiedUpdateJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceVerifiedUpdateJob.java index 181ad3195b..687c09dad9 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceVerifiedUpdateJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceVerifiedUpdateJob.java @@ -17,7 +17,7 @@ import org.thoughtcrime.securesms.net.NotPushRegisteredException; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.recipients.RecipientUtil; -import org.thoughtcrime.securesms.util.Base64; +import org.signal.core.util.Base64; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.whispersystems.signalservice.api.SignalServiceMessageSender; import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException; @@ -76,7 +76,7 @@ public class MultiDeviceVerifiedUpdateJob extends BaseJob { @Override public @Nullable byte[] serialize() { return new JsonJobData.Builder().putString(KEY_DESTINATION, destination.serialize()) - .putString(KEY_IDENTITY_KEY, Base64.encodeBytes(identityKey)) + .putString(KEY_IDENTITY_KEY, Base64.encodeWithPadding(identityKey)) .putInt(KEY_VERIFIED_STATUS, verifiedStatus.toInt()) .putLong(KEY_TIMESTAMP, timestamp) .serialize(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushGroupSilentUpdateSendJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushGroupSilentUpdateSendJob.java index 7b52271188..e68647cc66 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushGroupSilentUpdateSendJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushGroupSilentUpdateSendJob.java @@ -24,7 +24,7 @@ import org.thoughtcrime.securesms.net.NotPushRegisteredException; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.transport.RetryLaterException; -import org.thoughtcrime.securesms.util.Base64; +import org.signal.core.util.Base64; import org.thoughtcrime.securesms.util.GroupUtil; import org.whispersystems.signalservice.api.crypto.ContentHint; import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException; @@ -120,7 +120,7 @@ public final class PushGroupSilentUpdateSendJob extends BaseJob { return new JsonJobData.Builder().putString(KEY_RECIPIENTS, RecipientId.toSerializedList(recipients)) .putInt(KEY_INITIAL_RECIPIENT_COUNT, initialRecipientCount) .putLong(KEY_TIMESTAMP, timestamp) - .putString(KEY_GROUP_CONTEXT_V2, Base64.encodeBytes(groupContextV2.encode())) + .putString(KEY_GROUP_CONTEXT_V2, Base64.encodeWithPadding(groupContextV2.encode())) .serialize(); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushSendJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushSendJob.java index 21329ad2fa..43c23b6025 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushSendJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushSendJob.java @@ -60,7 +60,7 @@ import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.recipients.RecipientUtil; import org.thoughtcrime.securesms.transport.RetryLaterException; import org.thoughtcrime.securesms.transport.UndeliverableMessageException; -import org.thoughtcrime.securesms.util.Base64; +import org.signal.core.util.Base64; import org.thoughtcrime.securesms.util.BitmapDecodingException; import org.thoughtcrime.securesms.util.FeatureFlags; import org.thoughtcrime.securesms.util.ImageCompressionUtil; diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/RefreshAttributesJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/RefreshAttributesJob.java index c224b7fd19..27ee6ad0ea 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/RefreshAttributesJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/RefreshAttributesJob.java @@ -20,7 +20,7 @@ import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.whispersystems.signalservice.api.account.AccountAttributes; import org.whispersystems.signalservice.api.crypto.UnidentifiedAccess; import org.whispersystems.signalservice.api.push.exceptions.NetworkFailureException; -import org.whispersystems.util.Base64; +import org.signal.core.util.Base64; import java.io.IOException; import java.nio.charset.StandardCharsets; @@ -118,7 +118,7 @@ public class RefreshAttributesJob extends BaseJob { universalUnidentifiedAccess, capabilities, phoneNumberDiscoverable, - (encryptedDeviceName == null) ? null : Base64.encodeBytes(encryptedDeviceName), + (encryptedDeviceName == null) ? null : Base64.encodeWithPadding(encryptedDeviceName), pniRegistrationId, recoveryPassword ); diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/RefreshOwnProfileJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/RefreshOwnProfileJob.java index b3d1e62c4c..ce9a437e25 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/RefreshOwnProfileJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/RefreshOwnProfileJob.java @@ -5,6 +5,7 @@ import android.text.TextUtils; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import org.signal.core.util.Base64; import org.signal.core.util.logging.Log; import org.signal.libsignal.usernames.BaseUsernameException; import org.signal.libsignal.usernames.Username; @@ -23,7 +24,6 @@ import org.thoughtcrime.securesms.keyvalue.SignalStore; import org.thoughtcrime.securesms.profiles.ProfileName; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.subscription.Subscriber; -import org.thoughtcrime.securesms.util.Base64; import org.thoughtcrime.securesms.util.FeatureFlags; import org.thoughtcrime.securesms.util.ProfileUtil; import org.thoughtcrime.securesms.util.TextSecurePreferences; @@ -38,7 +38,6 @@ import org.whispersystems.signalservice.api.util.ExpiringProfileCredentialUtil; import org.whispersystems.signalservice.internal.ServiceResponse; import org.whispersystems.signalservice.internal.push.ReserveUsernameResponse; import org.whispersystems.signalservice.internal.push.WhoAmIResponse; -import org.whispersystems.util.Base64UrlSafe; import java.io.IOException; import java.util.Collections; @@ -273,7 +272,7 @@ public class RefreshOwnProfileJob extends BaseJob { WhoAmIResponse whoAmIResponse = ApplicationDependencies.getSignalServiceAccountManager().getWhoAmI(); boolean hasServerUsername = !TextUtils.isEmpty(whoAmIResponse.getUsernameHash()); String serverUsernameHash = whoAmIResponse.getUsernameHash(); - String localUsernameHash = Base64UrlSafe.encodeBytesWithoutPadding(Username.hash(localUsername)); + String localUsernameHash = Base64.encodeUrlSafeWithoutPadding(Username.hash(localUsername)); if (!hasServerUsername) { Log.w(TAG, "No remote username is set."); diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/ReportSpamJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/ReportSpamJob.java index 35a6372e31..0c6b059507 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/ReportSpamJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/ReportSpamJob.java @@ -13,7 +13,7 @@ import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint; import org.thoughtcrime.securesms.keyvalue.SignalStore; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; -import org.thoughtcrime.securesms.util.Base64; +import org.signal.core.util.Base64; import org.whispersystems.signalservice.api.SignalServiceAccountManager; import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException; @@ -86,7 +86,7 @@ public class ReportSpamJob extends BaseJob { byte[] reportingTokenBytes = SignalDatabase.recipients().getReportingToken(recipientId); if (reportingTokenBytes != null) { - reportingTokenEncoded = Base64.encodeBytes(reportingTokenBytes); + reportingTokenEncoded = Base64.encodeWithPadding(reportingTokenBytes); } signalServiceAccountManager.reportSpam(serviceId.get(), data.getServerGuid(), reportingTokenEncoded); diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/RetrieveProfileJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/RetrieveProfileJob.java index 057fffe3fd..7dd60b3a15 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/RetrieveProfileJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/RetrieveProfileJob.java @@ -40,7 +40,7 @@ import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.recipients.RecipientUtil; import org.thoughtcrime.securesms.transport.RetryLaterException; -import org.thoughtcrime.securesms.util.Base64; +import org.signal.core.util.Base64; import org.thoughtcrime.securesms.util.IdentityUtil; import org.thoughtcrime.securesms.util.ProfileUtil; import org.thoughtcrime.securesms.util.Util; diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/SmsReceiveJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/SmsReceiveJob.java index ac5dc2c73a..863c4a3d83 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/SmsReceiveJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/SmsReceiveJob.java @@ -31,7 +31,7 @@ import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.service.VerificationCodeParser; import org.thoughtcrime.securesms.sms.IncomingTextMessage; import org.thoughtcrime.securesms.transport.RetryLaterException; -import org.thoughtcrime.securesms.util.Base64; +import org.signal.core.util.Base64; import org.thoughtcrime.securesms.util.ServiceUtil; import org.thoughtcrime.securesms.util.TextSecurePreferences; @@ -74,7 +74,7 @@ public class SmsReceiveJob extends BaseJob { public @Nullable byte[] serialize() { String[] encoded = new String[pdus.length]; for (int i = 0; i < pdus.length; i++) { - encoded[i] = Base64.encodeBytes((byte[]) pdus[i]); + encoded[i] = Base64.encodeWithPadding((byte[]) pdus[i]); } return new JsonJobData.Builder().putStringArray(KEY_PDUS, encoded) diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/SubscriptionReceiptRequestResponseJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/SubscriptionReceiptRequestResponseJob.java index 4bc8d252d5..17e19fca2d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/SubscriptionReceiptRequestResponseJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/SubscriptionReceiptRequestResponseJob.java @@ -26,7 +26,7 @@ import org.thoughtcrime.securesms.jobmanager.JobManager; import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint; import org.thoughtcrime.securesms.keyvalue.SignalStore; import org.thoughtcrime.securesms.subscription.Subscriber; -import org.thoughtcrime.securesms.util.Base64; +import org.signal.core.util.Base64; import org.whispersystems.signalservice.api.subscriptions.ActiveSubscription; import org.whispersystems.signalservice.api.subscriptions.SubscriberId; import org.whispersystems.signalservice.internal.ServiceResponse; diff --git a/app/src/main/java/org/thoughtcrime/securesms/keyvalue/AccountValues.kt b/app/src/main/java/org/thoughtcrime/securesms/keyvalue/AccountValues.kt index 9020f22fac..82e5a90d3e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/keyvalue/AccountValues.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/keyvalue/AccountValues.kt @@ -5,6 +5,7 @@ import android.content.Context import android.content.SharedPreferences import android.preference.PreferenceManager import androidx.annotation.VisibleForTesting +import org.signal.core.util.Base64 import org.signal.core.util.logging.Log import org.signal.libsignal.protocol.IdentityKey import org.signal.libsignal.protocol.IdentityKeyPair @@ -19,7 +20,6 @@ import org.thoughtcrime.securesms.dependencies.ApplicationDependencies import org.thoughtcrime.securesms.jobs.PreKeysSyncJob import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.service.KeyCachingService -import org.thoughtcrime.securesms.util.Base64 import org.thoughtcrime.securesms.util.TextSecurePreferences import org.thoughtcrime.securesms.util.Util import org.whispersystems.signalservice.api.push.ServiceId.ACI diff --git a/app/src/main/java/org/thoughtcrime/securesms/logging/LogSecretProvider.java b/app/src/main/java/org/thoughtcrime/securesms/logging/LogSecretProvider.java index 5da3440686..57ac3ee714 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/logging/LogSecretProvider.java +++ b/app/src/main/java/org/thoughtcrime/securesms/logging/LogSecretProvider.java @@ -6,7 +6,7 @@ import android.os.Build; import androidx.annotation.NonNull; import org.thoughtcrime.securesms.crypto.KeyStoreHelper; -import org.thoughtcrime.securesms.util.Base64; +import org.signal.core.util.Base64; import org.thoughtcrime.securesms.util.TextSecurePreferences; import java.io.IOException; @@ -49,7 +49,7 @@ public class LogSecretProvider { KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(secret); TextSecurePreferences.setLogEncryptedSecret(context, encryptedSecret.serialize()); } else { - TextSecurePreferences.setLogUnencryptedSecret(context, Base64.encodeBytes(secret)); + TextSecurePreferences.setLogUnencryptedSecret(context, Base64.encodeWithPadding(secret)); } return secret; diff --git a/app/src/main/java/org/thoughtcrime/securesms/mediasend/v2/text/send/TextStoryPostSendRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/mediasend/v2/text/send/TextStoryPostSendRepository.kt index 8ffa1f3cdb..d627eb6a66 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/mediasend/v2/text/send/TextStoryPostSendRepository.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/mediasend/v2/text/send/TextStoryPostSendRepository.kt @@ -4,6 +4,7 @@ import android.graphics.Bitmap import android.net.Uri import io.reactivex.rxjava3.core.Single import io.reactivex.rxjava3.schedulers.Schedulers +import org.signal.core.util.Base64 import org.signal.core.util.ThreadUtil import org.signal.core.util.logging.Log import org.thoughtcrime.securesms.contacts.paged.ContactSearchKey @@ -20,7 +21,6 @@ import org.thoughtcrime.securesms.mms.OutgoingMessage import org.thoughtcrime.securesms.providers.BlobProvider import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.stories.Stories -import org.thoughtcrime.securesms.util.Base64 import java.io.ByteArrayOutputStream private val TAG = Log.tag(TextStoryPostSendRepository::class.java) @@ -110,6 +110,6 @@ class TextStoryPostSendRepository { builder.textBackgroundColor = textStoryPostCreationState.textBackgroundColor builder.textForegroundColor = textStoryPostCreationState.textForegroundColor - return Base64.encodeBytes(builder.build().encode()) + return Base64.encodeWithPadding(builder.build().encode()) } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/messages/DataMessageProcessor.kt b/app/src/main/java/org/thoughtcrime/securesms/messages/DataMessageProcessor.kt index f51536bb4f..c571b35c0b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/messages/DataMessageProcessor.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/messages/DataMessageProcessor.kt @@ -5,6 +5,7 @@ import android.content.Context import android.text.TextUtils import com.mobilecoin.lib.exceptions.SerializationException import okio.ByteString.Companion.toByteString +import org.signal.core.util.Base64 import org.signal.core.util.Hex import org.signal.core.util.concurrent.SignalExecutors import org.signal.core.util.logging.Log @@ -88,7 +89,6 @@ import org.thoughtcrime.securesms.sms.IncomingEndSessionMessage import org.thoughtcrime.securesms.sms.IncomingTextMessage import org.thoughtcrime.securesms.stickers.StickerLocator import org.thoughtcrime.securesms.storage.StorageSyncHelper -import org.thoughtcrime.securesms.util.Base64 import org.thoughtcrime.securesms.util.EarlyMessageCacheEntry import org.thoughtcrime.securesms.util.LinkUtil import org.thoughtcrime.securesms.util.MediaUtil @@ -825,7 +825,7 @@ object DataMessageProcessor { receivedTimeMillis = receivedTime, expiresIn = message.expireTimerDuration.inWholeMilliseconds, isUnidentified = metadata.sealedSender, - body = Base64.encodeBytes(dbGiftBadge.encode()), + body = Base64.encodeWithPadding(dbGiftBadge.encode()), serverGuid = envelope.serverGuid, giftBadge = dbGiftBadge ) diff --git a/app/src/main/java/org/thoughtcrime/securesms/messages/StoryMessageProcessor.kt b/app/src/main/java/org/thoughtcrime/securesms/messages/StoryMessageProcessor.kt index 98a1c4df3b..8873be1e91 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/messages/StoryMessageProcessor.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/messages/StoryMessageProcessor.kt @@ -1,6 +1,7 @@ package org.thoughtcrime.securesms.messages import android.graphics.Color +import org.signal.core.util.Base64 import org.signal.core.util.orNull import org.thoughtcrime.securesms.database.MessageTable.InsertResult import org.thoughtcrime.securesms.database.SignalDatabase @@ -17,7 +18,6 @@ import org.thoughtcrime.securesms.mms.IncomingMediaMessage import org.thoughtcrime.securesms.mms.MmsException import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.stories.Stories -import org.thoughtcrime.securesms.util.Base64 import org.thoughtcrime.securesms.util.FeatureFlags import org.whispersystems.signalservice.api.crypto.EnvelopeMetadata import org.whispersystems.signalservice.internal.push.Content @@ -147,6 +147,6 @@ object StoryMessageProcessor { } builder.background(chatColorBuilder.build()) - return Base64.encodeBytes(builder.build().encode()) + return Base64.encodeWithPadding(builder.build().encode()) } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/messages/StorySendUtil.kt b/app/src/main/java/org/thoughtcrime/securesms/messages/StorySendUtil.kt index c168e6dfce..691bd3b9c2 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/messages/StorySendUtil.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/messages/StorySendUtil.kt @@ -1,8 +1,8 @@ package org.thoughtcrime.securesms.messages +import org.signal.core.util.Base64 import org.thoughtcrime.securesms.database.model.databaseprotos.StoryTextPost import org.thoughtcrime.securesms.mms.OutgoingMessage -import org.thoughtcrime.securesms.util.Base64 import org.whispersystems.signalservice.api.messages.SignalServicePreview import org.whispersystems.signalservice.api.messages.SignalServiceTextAttachment import java.io.IOException diff --git a/app/src/main/java/org/thoughtcrime/securesms/mms/MessageGroupContext.java b/app/src/main/java/org/thoughtcrime/securesms/mms/MessageGroupContext.java index c94ce73ce6..3d0dfd34c5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/mms/MessageGroupContext.java +++ b/app/src/main/java/org/thoughtcrime/securesms/mms/MessageGroupContext.java @@ -14,7 +14,7 @@ import org.thoughtcrime.securesms.database.model.databaseprotos.DecryptedGroupV2 import org.thoughtcrime.securesms.messages.SignalServiceProtoUtil; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; -import org.thoughtcrime.securesms.util.Base64; +import org.signal.core.util.Base64; import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil; import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.api.push.ServiceId.ACI; @@ -51,14 +51,14 @@ public final class MessageGroupContext { } public MessageGroupContext(@NonNull GroupContext group) { - this.encodedGroupContext = Base64.encodeBytes(group.encode()); + this.encodedGroupContext = Base64.encodeWithPadding(group.encode()); this.groupV1 = new GroupV1Properties(group); this.groupV2 = null; this.group = groupV1; } public MessageGroupContext(@NonNull DecryptedGroupV2Context group) { - this.encodedGroupContext = Base64.encodeBytes(group.encode()); + this.encodedGroupContext = Base64.encodeWithPadding(group.encode()); this.groupV1 = null; this.groupV2 = new GroupV2Properties(group); this.group = groupV2; diff --git a/app/src/main/java/org/thoughtcrime/securesms/payments/MobileCoinMainNetConfig.java b/app/src/main/java/org/thoughtcrime/securesms/payments/MobileCoinMainNetConfig.java index 254511b63c..75b9f73005 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/payments/MobileCoinMainNetConfig.java +++ b/app/src/main/java/org/thoughtcrime/securesms/payments/MobileCoinMainNetConfig.java @@ -9,7 +9,7 @@ import com.mobilecoin.lib.Verifier; import com.mobilecoin.lib.exceptions.AttestationException; import org.thoughtcrime.securesms.R; -import org.thoughtcrime.securesms.util.Base64; +import org.signal.core.util.Base64; import org.whispersystems.signalservice.api.SignalServiceAccountManager; import org.whispersystems.signalservice.internal.push.AuthCredentials; diff --git a/app/src/main/java/org/thoughtcrime/securesms/payments/MobileCoinTestNetConfig.java b/app/src/main/java/org/thoughtcrime/securesms/payments/MobileCoinTestNetConfig.java index ad156cc618..f17256d577 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/payments/MobileCoinTestNetConfig.java +++ b/app/src/main/java/org/thoughtcrime/securesms/payments/MobileCoinTestNetConfig.java @@ -8,7 +8,7 @@ import com.mobilecoin.lib.ClientConfig; import com.mobilecoin.lib.exceptions.AttestationException; import org.thoughtcrime.securesms.R; -import org.thoughtcrime.securesms.util.Base64; +import org.signal.core.util.Base64; import org.whispersystems.signalservice.api.SignalServiceAccountManager; import org.whispersystems.signalservice.internal.push.AuthCredentials; diff --git a/app/src/main/java/org/thoughtcrime/securesms/profiles/manage/UsernameRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/profiles/manage/UsernameRepository.kt index c81c00710c..6df328a6d2 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/profiles/manage/UsernameRepository.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/profiles/manage/UsernameRepository.kt @@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.profiles.manage import androidx.annotation.WorkerThread import io.reactivex.rxjava3.core.Single import io.reactivex.rxjava3.schedulers.Schedulers +import org.signal.core.util.Base64 import org.signal.core.util.Result import org.signal.core.util.Result.Companion.failure import org.signal.core.util.Result.Companion.success @@ -24,7 +25,6 @@ import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulRespons import org.whispersystems.signalservice.api.push.exceptions.UsernameIsNotReservedException import org.whispersystems.signalservice.api.push.exceptions.UsernameMalformedException import org.whispersystems.signalservice.api.push.exceptions.UsernameTakenException -import org.whispersystems.util.Base64UrlSafe import java.io.IOException /** @@ -153,7 +153,7 @@ class UsernameRepository { val candidates: List = Username.candidatesFrom(nickname, UsernameUtil.MIN_LENGTH, UsernameUtil.MAX_LENGTH) val hashes: List = candidates - .map { Base64UrlSafe.encodeBytesWithoutPadding(it.hash) } + .map { Base64.encodeUrlSafeWithoutPadding(it.hash) } val response = accountManager.reserveUsername(hashes) diff --git a/app/src/main/java/org/thoughtcrime/securesms/profiles/manage/UsernameShareBottomSheet.kt b/app/src/main/java/org/thoughtcrime/securesms/profiles/manage/UsernameShareBottomSheet.kt index f40b3c4580..ab9a9e2bbd 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/profiles/manage/UsernameShareBottomSheet.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/profiles/manage/UsernameShareBottomSheet.kt @@ -8,6 +8,7 @@ import androidx.core.app.ShareCompat import androidx.core.content.ContextCompat import androidx.fragment.app.setFragmentResult import androidx.navigation.fragment.findNavController +import org.signal.core.util.Base64 import org.signal.core.util.DimensionUnit import org.signal.core.util.concurrent.LifecycleDisposable import org.signal.libsignal.usernames.Username @@ -20,7 +21,6 @@ import org.thoughtcrime.securesms.components.settings.configure import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.util.FragmentResultContract import org.thoughtcrime.securesms.util.Util -import org.whispersystems.util.Base64UrlSafe /** * Allows the user to either share their username directly or to copy it to their clipboard. @@ -71,7 +71,7 @@ class UsernameShareBottomSheet : DSLSettingsBottomSheetFragment() { customPref( CopyButton.Model( - text = getString(R.string.signal_me_username_url, Base64UrlSafe.encodeBytesWithoutPadding(Username.hash(username))), + text = getString(R.string.signal_me_username_url, Base64.encodeUrlSafeWithoutPadding(Username.hash(username))), onClick = { copyToClipboard(it) } @@ -82,7 +82,7 @@ class UsernameShareBottomSheet : DSLSettingsBottomSheetFragment() { customPref( ShareButton.Model( - text = getString(R.string.signal_me_username_url, Base64UrlSafe.encodeBytesWithoutPadding(Username.hash(username))), + text = getString(R.string.signal_me_username_url, Base64.encodeUrlSafeWithoutPadding(Username.hash(username))), onClick = { openShareSheet(it.text) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/profiles/spoofing/ReviewUtil.java b/app/src/main/java/org/thoughtcrime/securesms/profiles/spoofing/ReviewUtil.java index 9be140aaf5..2926140d98 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/profiles/spoofing/ReviewUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/profiles/spoofing/ReviewUtil.java @@ -16,7 +16,7 @@ import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.groups.GroupId; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; -import org.thoughtcrime.securesms.util.Base64; +import org.signal.core.util.Base64; import java.io.IOException; import java.util.Collections; diff --git a/app/src/main/java/org/thoughtcrime/securesms/push/SignalServiceNetworkAccess.kt b/app/src/main/java/org/thoughtcrime/securesms/push/SignalServiceNetworkAccess.kt index 6e72845e9f..4ee13d52e4 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/push/SignalServiceNetworkAccess.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/push/SignalServiceNetworkAccess.kt @@ -7,6 +7,7 @@ import okhttp3.ConnectionSpec import okhttp3.Dns import okhttp3.Interceptor import okhttp3.TlsVersion +import org.signal.core.util.Base64 import org.signal.core.util.logging.Log import org.thoughtcrime.securesms.BuildConfig import org.thoughtcrime.securesms.keyvalue.SettingsValues @@ -18,7 +19,6 @@ import org.thoughtcrime.securesms.net.RemoteDeprecationDetectorInterceptor import org.thoughtcrime.securesms.net.SequentialDns import org.thoughtcrime.securesms.net.StandardUserAgentInterceptor import org.thoughtcrime.securesms.net.StaticDns -import org.thoughtcrime.securesms.util.Base64 import org.whispersystems.signalservice.api.push.TrustStore import org.whispersystems.signalservice.internal.configuration.SignalCdnUrl import org.whispersystems.signalservice.internal.configuration.SignalCdsiUrl diff --git a/app/src/main/java/org/thoughtcrime/securesms/registration/viewmodel/RegistrationViewModel.java b/app/src/main/java/org/thoughtcrime/securesms/registration/viewmodel/RegistrationViewModel.java index b026cb534d..6d20ccc9b3 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/registration/viewmodel/RegistrationViewModel.java +++ b/app/src/main/java/org/thoughtcrime/securesms/registration/viewmodel/RegistrationViewModel.java @@ -35,7 +35,7 @@ import org.whispersystems.signalservice.api.push.exceptions.IncorrectCodeExcepti import org.whispersystems.signalservice.api.push.exceptions.IncorrectRegistrationRecoveryPasswordException; import org.whispersystems.signalservice.internal.ServiceResponse; import org.whispersystems.signalservice.internal.push.RegistrationSessionMetadataResponse; -import org.whispersystems.util.Base64; +import org.signal.core.util.Base64; import java.io.IOException; import java.nio.charset.StandardCharsets; diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/links/CallLinkRoomId.kt b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/links/CallLinkRoomId.kt index 9e55ded332..ca2fcd3624 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/links/CallLinkRoomId.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/links/CallLinkRoomId.kt @@ -9,9 +9,9 @@ import android.os.Parcelable import kotlinx.parcelize.Parcelize import okio.ByteString import okio.ByteString.Companion.toByteString +import org.signal.core.util.Base64 import org.signal.core.util.Serializer import org.signal.ringrtc.CallLinkRootKey -import org.thoughtcrime.securesms.util.Base64 @Parcelize class CallLinkRoomId private constructor(private val roomId: ByteArray) : Parcelable { @@ -40,7 +40,7 @@ class CallLinkRoomId private constructor(private val roomId: ByteArray) : Parcel object DatabaseSerializer : Serializer { override fun serialize(data: CallLinkRoomId): String { - return Base64.encodeBytes(data.roomId) + return Base64.encodeWithPadding(data.roomId) } override fun deserialize(data: String): CallLinkRoomId { diff --git a/app/src/main/java/org/thoughtcrime/securesms/sharing/MultiShareSender.java b/app/src/main/java/org/thoughtcrime/securesms/sharing/MultiShareSender.java index 5d432f8f7f..0ec58a4376 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/sharing/MultiShareSender.java +++ b/app/src/main/java/org/thoughtcrime/securesms/sharing/MultiShareSender.java @@ -46,7 +46,7 @@ import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.sms.MessageSender; import org.thoughtcrime.securesms.sms.MessageSender.SendType; import org.thoughtcrime.securesms.stories.Stories; -import org.thoughtcrime.securesms.util.Base64; +import org.signal.core.util.Base64; import org.thoughtcrime.securesms.util.MediaUtil; import org.thoughtcrime.securesms.util.MessageUtil; import org.thoughtcrime.securesms.util.Util; @@ -390,7 +390,7 @@ public final class MultiShareSender { { return OutgoingMessage.textStoryMessage( recipient, - Base64.encodeBytes(new StoryTextPost.Builder() + Base64.encodeWithPadding(new StoryTextPost.Builder() .body(getBodyForTextStory(multiShareArgs.getDraftText(), multiShareArgs.getLinkPreview())) .style(StoryTextPost.Style.DEFAULT) .background(background.serialize()) diff --git a/app/src/main/java/org/thoughtcrime/securesms/storage/StorageSyncHelper.java b/app/src/main/java/org/thoughtcrime/securesms/storage/StorageSyncHelper.java index d408c5c478..5964bda3ef 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/storage/StorageSyncHelper.java +++ b/app/src/main/java/org/thoughtcrime/securesms/storage/StorageSyncHelper.java @@ -22,7 +22,7 @@ import org.thoughtcrime.securesms.keyvalue.SignalStore; import org.thoughtcrime.securesms.payments.Entropy; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.subscription.Subscriber; -import org.thoughtcrime.securesms.util.Base64; +import org.signal.core.util.Base64; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.Util; import org.whispersystems.signalservice.api.push.UsernameLinkComponents; @@ -69,8 +69,8 @@ public final class StorageSyncHelper { public static @NonNull IdDifferenceResult findIdDifference(@NonNull Collection remoteIds, @NonNull Collection localIds) { - Map remoteByRawId = Stream.of(remoteIds).collect(Collectors.toMap(id -> Base64.encodeBytes(id.getRaw()), id -> id)); - Map localByRawId = Stream.of(localIds).collect(Collectors.toMap(id -> Base64.encodeBytes(id.getRaw()), id -> id)); + Map remoteByRawId = Stream.of(remoteIds).collect(Collectors.toMap(id -> Base64.encodeWithPadding(id.getRaw()), id -> id)); + Map localByRawId = Stream.of(localIds).collect(Collectors.toMap(id -> Base64.encodeWithPadding(id.getRaw()), id -> id)); boolean hasTypeMismatch = remoteByRawId.size() != remoteIds.size() || localByRawId.size() != localIds.size(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/storage/StorageSyncValidations.java b/app/src/main/java/org/thoughtcrime/securesms/storage/StorageSyncValidations.java index 2a22af49af..b9deaf52c2 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/storage/StorageSyncValidations.java +++ b/app/src/main/java/org/thoughtcrime/securesms/storage/StorageSyncValidations.java @@ -7,7 +7,7 @@ import com.annimon.stream.Stream; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.recipients.Recipient; -import org.thoughtcrime.securesms.util.Base64; +import org.signal.core.util.Base64; import org.signal.core.util.SetUtil; import org.whispersystems.signalservice.api.storage.SignalContactRecord; import org.whispersystems.signalservice.api.storage.SignalStorageManifest; @@ -34,10 +34,10 @@ public final class StorageSyncValidations { validateManifestAndInserts(result.getManifest(), result.getInserts(), self); if (result.getDeletes().size() > 0) { - Set allSetEncoded = Stream.of(result.getManifest().getStorageIds()).map(StorageId::getRaw).map(Base64::encodeBytes).collect(Collectors.toSet()); + Set allSetEncoded = Stream.of(result.getManifest().getStorageIds()).map(StorageId::getRaw).map(Base64::encodeWithPadding).collect(Collectors.toSet()); for (byte[] delete : result.getDeletes()) { - String encoded = Base64.encodeBytes(delete); + String encoded = Base64.encodeWithPadding(delete); if (allSetEncoded.contains(encoded)) { throw new DeletePresentInFullIdSetError(); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/stories/StoryTextPostModel.kt b/app/src/main/java/org/thoughtcrime/securesms/stories/StoryTextPostModel.kt index 436f551853..49d086b33b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/stories/StoryTextPostModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/stories/StoryTextPostModel.kt @@ -15,6 +15,7 @@ import com.bumptech.glide.load.Options import com.bumptech.glide.load.ResourceDecoder import com.bumptech.glide.load.engine.Resource import com.bumptech.glide.load.resource.SimpleResource +import org.signal.core.util.Base64 import org.signal.core.util.concurrent.safeBlockingGet import org.signal.core.util.readParcelableCompat import org.thoughtcrime.securesms.R @@ -32,7 +33,6 @@ import org.thoughtcrime.securesms.fonts.TypefaceCache import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader import org.thoughtcrime.securesms.mms.GlideApp import org.thoughtcrime.securesms.recipients.RecipientId -import org.thoughtcrime.securesms.util.Base64 import org.thoughtcrime.securesms.util.ParcelUtil import java.io.IOException import java.security.MessageDigest diff --git a/app/src/main/java/org/thoughtcrime/securesms/stories/dialogs/StoryContextMenu.kt b/app/src/main/java/org/thoughtcrime/securesms/stories/dialogs/StoryContextMenu.kt index 27d52b9cfe..82b2a3db73 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/stories/dialogs/StoryContextMenu.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/stories/dialogs/StoryContextMenu.kt @@ -12,6 +12,7 @@ import androidx.core.app.ShareCompat import androidx.fragment.app.Fragment import com.bumptech.glide.load.Options import io.reactivex.rxjava3.core.Single +import org.signal.core.util.Base64 import org.signal.core.util.DimensionUnit import org.signal.core.util.concurrent.SimpleTask import org.signal.core.util.logging.Log @@ -27,7 +28,6 @@ import org.thoughtcrime.securesms.stories.StoryTextPostModel import org.thoughtcrime.securesms.stories.landing.StoriesLandingItem import org.thoughtcrime.securesms.stories.viewer.page.StoryPost import org.thoughtcrime.securesms.stories.viewer.page.StoryViewerPageState -import org.thoughtcrime.securesms.util.Base64 import org.thoughtcrime.securesms.util.BitmapUtil import org.thoughtcrime.securesms.util.DeleteDialog import org.thoughtcrime.securesms.util.MediaUtil diff --git a/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/page/StoryViewerPageRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/page/StoryViewerPageRepository.kt index de597e4909..f81170bc0b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/page/StoryViewerPageRepository.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/page/StoryViewerPageRepository.kt @@ -6,6 +6,7 @@ import androidx.annotation.CheckResult import io.reactivex.rxjava3.core.Completable import io.reactivex.rxjava3.core.Observable import io.reactivex.rxjava3.schedulers.Schedulers +import org.signal.core.util.Base64 import org.signal.core.util.BreakIteratorCompat import org.signal.core.util.concurrent.SignalExecutors import org.signal.core.util.logging.Log @@ -26,7 +27,6 @@ import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.recipients.RecipientId import org.thoughtcrime.securesms.sms.MessageSender import org.thoughtcrime.securesms.stories.Stories -import org.thoughtcrime.securesms.util.Base64 /** * Open for testing. diff --git a/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/post/StoryPostViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/post/StoryPostViewModel.kt index 8b902d2da7..da2887ba5a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/post/StoryPostViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/post/StoryPostViewModel.kt @@ -8,10 +8,10 @@ import io.reactivex.rxjava3.core.Single import io.reactivex.rxjava3.disposables.CompositeDisposable import io.reactivex.rxjava3.kotlin.plusAssign import io.reactivex.rxjava3.kotlin.subscribeBy +import org.signal.core.util.Base64 import org.signal.core.util.logging.Log import org.thoughtcrime.securesms.database.model.databaseprotos.StoryTextPost import org.thoughtcrime.securesms.stories.viewer.page.StoryPost -import org.thoughtcrime.securesms.util.Base64 import org.thoughtcrime.securesms.util.rx.RxStore import kotlin.time.Duration import kotlin.time.Duration.Companion.microseconds diff --git a/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/post/StoryTextPostRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/post/StoryTextPostRepository.kt index 88e5225f4b..5ba196fa04 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/post/StoryTextPostRepository.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/post/StoryTextPostRepository.kt @@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.stories.viewer.post import android.graphics.Typeface import io.reactivex.rxjava3.core.Single import io.reactivex.rxjava3.schedulers.Schedulers +import org.signal.core.util.Base64 import org.thoughtcrime.securesms.database.SignalDatabase import org.thoughtcrime.securesms.database.model.MmsMessageRecord import org.thoughtcrime.securesms.database.model.databaseprotos.StoryTextPost @@ -10,7 +11,6 @@ import org.thoughtcrime.securesms.dependencies.ApplicationDependencies import org.thoughtcrime.securesms.fonts.TextFont import org.thoughtcrime.securesms.fonts.TextToScript import org.thoughtcrime.securesms.fonts.TypefaceCache -import org.thoughtcrime.securesms.util.Base64 class StoryTextPostRepository { fun getRecord(recordId: Long): Single { diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/AppSignatureUtil.java b/app/src/main/java/org/thoughtcrime/securesms/util/AppSignatureUtil.java index 2c0b949ccc..15d4e43f99 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/AppSignatureUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/AppSignatureUtil.java @@ -8,6 +8,7 @@ import android.content.pm.Signature; import androidx.annotation.NonNull; +import org.signal.core.util.Base64; import org.signal.core.util.logging.Log; import java.nio.charset.StandardCharsets; @@ -56,7 +57,7 @@ public final class AppSignatureUtil { byte[] hashSignature = messageDigest.digest(); hashSignature = Arrays.copyOfRange(hashSignature, 0, HASH_LENGTH_BYTES); - String base64Hash = Base64.encodeBytes(hashSignature); + String base64Hash = Base64.encodeWithPadding(hashSignature); base64Hash = base64Hash.substring(0, HASH_LENGTH_CHARS); return base64Hash; diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/Base64.java b/app/src/main/java/org/thoughtcrime/securesms/util/Base64.java deleted file mode 100644 index 99f545734a..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/util/Base64.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.thoughtcrime.securesms.util; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import java.io.IOException; - -public final class Base64 { - - private Base64() { - } - - public static @NonNull byte[] decode(@NonNull String s) throws IOException { - return org.whispersystems.util.Base64.decode(s); - } - - public static @NonNull byte[] decodeWithoutPadding(@NonNull String s) throws IOException { - return org.whispersystems.util.Base64.decodeWithoutPadding(s); - } - - public static @NonNull String encodeBytes(@NonNull byte[] source) { - return org.whispersystems.util.Base64.encodeBytes(source); - } - - public static @NonNull String encodeBytesWithoutPadding(@NonNull byte[] source) { - return org.whispersystems.util.Base64.encodeBytesWithoutPadding(source); - } - - public static @NonNull byte[] decodeOrThrow(@NonNull String s) { - try { - return org.whispersystems.util.Base64.decode(s); - } catch (IOException e) { - throw new AssertionError(); - } - } - - public static @Nullable byte[] decodeNullableOrThrow(@Nullable String s) { - if (s == null) { - return null; - } - - try { - return org.whispersystems.util.Base64.decode(s); - } catch (IOException e) { - throw new AssertionError(); - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/ProfileUtil.java b/app/src/main/java/org/thoughtcrime/securesms/util/ProfileUtil.java index ef75122599..32f9a7f395 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/ProfileUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/ProfileUtil.java @@ -6,6 +6,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.WorkerThread; +import org.signal.core.util.Base64; import org.signal.core.util.logging.Log; import org.signal.libsignal.protocol.IdentityKey; import org.signal.libsignal.protocol.IdentityKeyPair; diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/UsernameUtil.kt b/app/src/main/java/org/thoughtcrime/securesms/util/UsernameUtil.kt index 0f5ec2bfea..7400a20444 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/UsernameUtil.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/util/UsernameUtil.kt @@ -1,6 +1,7 @@ package org.thoughtcrime.securesms.util import androidx.annotation.WorkerThread +import org.signal.core.util.Base64 import org.signal.core.util.logging.Log import org.signal.libsignal.usernames.BaseUsernameException import org.signal.libsignal.usernames.Username @@ -11,7 +12,6 @@ import org.whispersystems.signalservice.api.push.ServiceId import org.whispersystems.signalservice.api.push.UsernameLinkComponents import org.whispersystems.signalservice.api.util.UuidUtil import org.whispersystems.signalservice.api.util.toByteArray -import org.whispersystems.util.Base64UrlSafe import java.io.IOException import java.util.Locale import java.util.Optional @@ -85,7 +85,7 @@ object UsernameUtil { Log.d(TAG, "No local user with this username. Searching remotely.") return try { - fetchAciForUsernameHash(Base64UrlSafe.encodeBytesWithoutPadding(Username.hash(username))) + fetchAciForUsernameHash(Base64.encodeUrlSafeWithoutPadding(Username.hash(username))) } catch (e: BaseUsernameException) { Optional.empty() } @@ -97,7 +97,7 @@ object UsernameUtil { */ @Throws(BaseUsernameException::class) fun hashUsernameToBase64(username: String?): String { - return Base64UrlSafe.encodeBytesWithoutPadding(Username.hash(username)) + return Base64.encodeUrlSafeWithoutPadding(Username.hash(username)) } @JvmStatic @@ -117,7 +117,7 @@ object UsernameUtil { */ fun generateLink(components: UsernameLinkComponents): String { val combined: ByteArray = components.entropy + components.serverId.toByteArray() - val base64 = Base64UrlSafe.encodeBytesWithoutPadding(combined) + val base64 = Base64.encodeUrlSafeWithoutPadding(combined) return BASE_URL + base64 } @@ -128,7 +128,7 @@ object UsernameUtil { fun parseLink(url: String): UsernameLinkComponents? { val match: MatchResult = URL_PATTERN.find(url) ?: return null val path: String = match.groups[2]?.value ?: return null - val allBytes: ByteArray = Base64UrlSafe.decodePaddingAgnostic(path) + val allBytes: ByteArray = Base64.decode(path) if (allBytes.size != 48) { return null diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/Util.java b/app/src/main/java/org/thoughtcrime/securesms/util/Util.java index acc8ede8f1..f8a6e9c126 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/Util.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/Util.java @@ -44,6 +44,7 @@ import com.google.i18n.phonenumbers.NumberParseException; import com.google.i18n.phonenumbers.PhoneNumberUtil; import com.google.i18n.phonenumbers.Phonenumber; +import org.signal.core.util.Base64; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.BuildConfig; import org.thoughtcrime.securesms.R; @@ -359,7 +360,7 @@ public class Util { public static String getSecret(int size) { byte[] secret = getSecretBytes(size); - return Base64.encodeBytes(secret); + return Base64.encodeWithPadding(secret); } public static byte[] getSecretBytes(int size) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/video/exo/PartDataSource.java b/app/src/main/java/org/thoughtcrime/securesms/video/exo/PartDataSource.java index b8d75745fc..2fe498c6db 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/video/exo/PartDataSource.java +++ b/app/src/main/java/org/thoughtcrime/securesms/video/exo/PartDataSource.java @@ -17,7 +17,7 @@ import org.thoughtcrime.securesms.attachments.DatabaseAttachment; import org.thoughtcrime.securesms.database.AttachmentTable; import org.thoughtcrime.securesms.database.SignalDatabase; import org.thoughtcrime.securesms.mms.PartUriParser; -import org.thoughtcrime.securesms.util.Base64; +import org.signal.core.util.Base64; import org.thoughtcrime.securesms.util.FeatureFlags; import org.whispersystems.signalservice.api.crypto.AttachmentCipherInputStream; diff --git a/app/src/spinner/java/org/thoughtcrime/securesms/database/GV2UpdateTransformer.kt b/app/src/spinner/java/org/thoughtcrime/securesms/database/GV2UpdateTransformer.kt index 870d74e0a9..7547a341b1 100644 --- a/app/src/spinner/java/org/thoughtcrime/securesms/database/GV2UpdateTransformer.kt +++ b/app/src/spinner/java/org/thoughtcrime/securesms/database/GV2UpdateTransformer.kt @@ -1,6 +1,7 @@ package org.thoughtcrime.securesms.database import android.database.Cursor +import org.signal.core.util.Base64 import org.signal.core.util.CursorUtil import org.signal.core.util.requireLong import org.signal.spinner.ColumnTransformer @@ -9,7 +10,6 @@ import org.thoughtcrime.securesms.database.model.MessageRecord import org.thoughtcrime.securesms.database.model.UpdateDescription import org.thoughtcrime.securesms.database.model.databaseprotos.DecryptedGroupV2Context import org.thoughtcrime.securesms.dependencies.ApplicationDependencies -import org.thoughtcrime.securesms.util.Base64 object GV2UpdateTransformer : ColumnTransformer { override fun matches(tableName: String?, columnName: String): Boolean { diff --git a/app/src/spinner/java/org/thoughtcrime/securesms/database/KyberKeyTransformer.kt b/app/src/spinner/java/org/thoughtcrime/securesms/database/KyberKeyTransformer.kt index ab877a7a90..4563f5f641 100644 --- a/app/src/spinner/java/org/thoughtcrime/securesms/database/KyberKeyTransformer.kt +++ b/app/src/spinner/java/org/thoughtcrime/securesms/database/KyberKeyTransformer.kt @@ -6,10 +6,10 @@ package org.thoughtcrime.securesms.database import android.database.Cursor +import org.signal.core.util.Base64 import org.signal.core.util.requireBlob import org.signal.libsignal.protocol.state.KyberPreKeyRecord import org.signal.spinner.ColumnTransformer -import org.thoughtcrime.securesms.util.Base64 object KyberKeyTransformer : ColumnTransformer { override fun matches(tableName: String?, columnName: String): Boolean { @@ -18,6 +18,6 @@ object KyberKeyTransformer : ColumnTransformer { override fun transform(tableName: String?, columnName: String, cursor: Cursor): String? { val record = KyberPreKeyRecord(cursor.requireBlob(columnName)) - return "ID: ${record.id}\nTimestamp: ${record.timestamp}\nPublicKey: ${Base64.encodeBytesWithoutPadding(record.keyPair.publicKey.serialize())}\nPrivateKey: ${Base64.encodeBytesWithoutPadding(record.keyPair.secretKey.serialize())}\nSignature: ${Base64.encodeBytesWithoutPadding(record.signature)}" + return "ID: ${record.id}\nTimestamp: ${record.timestamp}\nPublicKey: ${Base64.encodeWithoutPadding(record.keyPair.publicKey.serialize())}\nPrivateKey: ${Base64.encodeWithoutPadding(record.keyPair.secretKey.serialize())}\nSignature: ${Base64.encodeWithoutPadding(record.signature)}" } } diff --git a/app/src/spinner/java/org/thoughtcrime/securesms/database/ProfileKeyCredentialTransformer.kt b/app/src/spinner/java/org/thoughtcrime/securesms/database/ProfileKeyCredentialTransformer.kt index 982e8814ba..45ecf44e41 100644 --- a/app/src/spinner/java/org/thoughtcrime/securesms/database/ProfileKeyCredentialTransformer.kt +++ b/app/src/spinner/java/org/thoughtcrime/securesms/database/ProfileKeyCredentialTransformer.kt @@ -1,13 +1,13 @@ package org.thoughtcrime.securesms.database import android.database.Cursor +import org.signal.core.util.Base64 import org.signal.core.util.Hex import org.signal.core.util.requireString import org.signal.libsignal.zkgroup.profiles.ExpiringProfileKeyCredential import org.signal.spinner.ColumnTransformer import org.signal.spinner.DefaultColumnTransformer import org.thoughtcrime.securesms.database.model.databaseprotos.ExpiringProfileKeyCredentialColumnData -import org.thoughtcrime.securesms.util.Base64 import org.thoughtcrime.securesms.util.toLocalDateTime import java.security.MessageDigest @@ -27,7 +27,7 @@ object ProfileKeyCredentialTransformer : ColumnTransformer { Expires: ${credential.expirationTime.toLocalDateTime()} Matching Profile Key: - ${Base64.encodeBytes(columnData.profileKey.toByteArray())} + ${Base64.encodeWithPadding(columnData.profileKey.toByteArray())} """.trimIndent().replace("\n", "
") } } diff --git a/app/src/test/java/org/thoughtcrime/securesms/database/model/MessageRecordTest_createNewContextWithAppendedDeleteJoinRequest.kt b/app/src/test/java/org/thoughtcrime/securesms/database/model/MessageRecordTest_createNewContextWithAppendedDeleteJoinRequest.kt index d0d9a17eb8..08c2e52b51 100644 --- a/app/src/test/java/org/thoughtcrime/securesms/database/model/MessageRecordTest_createNewContextWithAppendedDeleteJoinRequest.kt +++ b/app/src/test/java/org/thoughtcrime/securesms/database/model/MessageRecordTest_createNewContextWithAppendedDeleteJoinRequest.kt @@ -7,9 +7,9 @@ import org.hamcrest.Matchers.`is` import org.junit.Test import org.mockito.kotlin.doReturn import org.mockito.kotlin.mock +import org.signal.core.util.Base64 import org.thoughtcrime.securesms.database.model.databaseprotos.DecryptedGroupV2Context import org.thoughtcrime.securesms.groups.v2.ChangeBuilder -import org.thoughtcrime.securesms.util.Base64 import org.whispersystems.signalservice.api.push.ServiceId.ACI import org.whispersystems.signalservice.internal.push.GroupContextV2 import java.util.Random diff --git a/app/src/test/java/org/thoughtcrime/securesms/groups/v2/GroupInviteLinkUrl_InvalidGroupLinkException_Test.java b/app/src/test/java/org/thoughtcrime/securesms/groups/v2/GroupInviteLinkUrl_InvalidGroupLinkException_Test.java index 040ee88c02..c647af55cd 100644 --- a/app/src/test/java/org/thoughtcrime/securesms/groups/v2/GroupInviteLinkUrl_InvalidGroupLinkException_Test.java +++ b/app/src/test/java/org/thoughtcrime/securesms/groups/v2/GroupInviteLinkUrl_InvalidGroupLinkException_Test.java @@ -3,10 +3,10 @@ package org.thoughtcrime.securesms.groups.v2; import androidx.annotation.NonNull; import org.junit.Test; +import org.signal.core.util.Base64; import org.signal.libsignal.zkgroup.InvalidInputException; import org.signal.storageservice.protos.groups.GroupInviteLink; import org.thoughtcrime.securesms.util.Util; -import org.whispersystems.util.Base64UrlSafe; import java.io.IOException; @@ -98,13 +98,13 @@ public final class GroupInviteLinkUrl_InvalidGroupLinkException_Test { private static String createEncodedProtobuf(@NonNull byte[] groupMasterKey, @NonNull byte[] passwordBytes) { - return Base64UrlSafe.encodeBytesWithoutPadding(new GroupInviteLink.Builder() - .v1Contents(new GroupInviteLink.GroupInviteLinkContentsV1.Builder() - .groupMasterKey(ByteString.of(groupMasterKey)) - .inviteLinkPassword(ByteString.of(passwordBytes)) - .build()) - .build() - .encode()); + return Base64.encodeUrlSafeWithoutPadding(new GroupInviteLink.Builder() + .v1Contents(new GroupInviteLink.GroupInviteLinkContentsV1.Builder() + .groupMasterKey(ByteString.of(groupMasterKey)) + .inviteLinkPassword(ByteString.of(passwordBytes)) + .build()) + .build() + .encode()); } } \ No newline at end of file diff --git a/app/src/test/java/org/thoughtcrime/securesms/stories/dialogs/StoryContextMenuTest.kt b/app/src/test/java/org/thoughtcrime/securesms/stories/dialogs/StoryContextMenuTest.kt index 43484de257..d74edc94d7 100644 --- a/app/src/test/java/org/thoughtcrime/securesms/stories/dialogs/StoryContextMenuTest.kt +++ b/app/src/test/java/org/thoughtcrime/securesms/stories/dialogs/StoryContextMenuTest.kt @@ -16,6 +16,7 @@ import org.mockito.kotlin.mock import org.mockito.kotlin.verify import org.robolectric.RobolectricTestRunner import org.robolectric.annotation.Config +import org.signal.core.util.Base64 import org.signal.core.util.getParcelableExtraCompat import org.thoughtcrime.securesms.attachments.AttachmentId import org.thoughtcrime.securesms.database.FakeMessageRecords @@ -26,7 +27,6 @@ import org.thoughtcrime.securesms.mms.ImageSlide import org.thoughtcrime.securesms.mms.PartAuthority import org.thoughtcrime.securesms.mms.SlideDeck import org.thoughtcrime.securesms.util.MediaUtil -import org.whispersystems.util.Base64 import java.util.Optional @RunWith(RobolectricTestRunner::class) @@ -74,7 +74,7 @@ class StoryContextMenuTest { val expected = "Hello" val storyRecord = FakeMessageRecords.buildMediaMmsMessageRecord( storyType = StoryType.TEXT_STORY_WITH_REPLIES, - body = Base64.encodeBytes(StoryTextPost.Builder().body(expected).build().encode()) + body = Base64.encodeWithPadding(StoryTextPost.Builder().body(expected).build().encode()) ) // WHEN @@ -93,7 +93,7 @@ class StoryContextMenuTest { val expected = "https://www.signal.org" val storyRecord = FakeMessageRecords.buildMediaMmsMessageRecord( storyType = StoryType.TEXT_STORY_WITH_REPLIES, - body = Base64.encodeBytes(StoryTextPost.Builder().build().encode()), + body = Base64.encodeWithPadding(StoryTextPost.Builder().build().encode()), linkPreviews = listOf(LinkPreview(expected, "", "", 0L, Optional.empty())) ) @@ -115,7 +115,7 @@ class StoryContextMenuTest { val expected = "$text $url" val storyRecord = FakeMessageRecords.buildMediaMmsMessageRecord( storyType = StoryType.TEXT_STORY_WITH_REPLIES, - body = Base64.encodeBytes(StoryTextPost.Builder().body(text).build().encode()), + body = Base64.encodeWithPadding(StoryTextPost.Builder().body(text).build().encode()), linkPreviews = listOf(LinkPreview(url, "", "", 0L, Optional.empty())) ) diff --git a/core-util-jvm/src/main/java/org/signal/core/util/Base64.kt b/core-util-jvm/src/main/java/org/signal/core/util/Base64.kt new file mode 100644 index 0000000000..7e81ad0082 --- /dev/null +++ b/core-util-jvm/src/main/java/org/signal/core/util/Base64.kt @@ -0,0 +1,116 @@ +/* + * Copyright 2023 Signal Messenger, LLC + * SPDX-License-Identifier: AGPL-3.0-only + */ + +package org.signal.core.util + +import java.io.IOException +import java.io.UnsupportedEncodingException + +object Base64 { + + /** + * Encodes the bytes as a normal Base64 string with padding. Not URL safe. For url-safe, use [encodeUrlSafe]. + * + * Note: the [offset] and [length] are there to support a legacy usecase, which is why they're not present on + * the other encode* methods. + */ + @JvmOverloads + @JvmStatic + fun encodeWithPadding(bytes: ByteArray, offset: Int = 0, length: Int = bytes.size): String { + return Base64Tools.encodeBytes(bytes, offset, length) + } + + /** + * Encodes the bytes as a normal Base64 string without padding. Not URL safe. For url-safe, use [encodeUrlSafe]. + */ + @JvmStatic + fun encodeWithoutPadding(bytes: ByteArray): String { + return Base64Tools.encodeBytes(bytes).stripPadding() + } + + /** + * Encodes the bytes as a url-safe Base64 string with padding. It basically replaces the '+' and '/' characters in the + * normal encoding scheme with '-' and '_'. + */ + @JvmStatic + fun encodeUrlSafeWithPadding(bytes: ByteArray): String { + return Base64Tools.encodeBytes(bytes, Base64Tools.URL_SAFE or Base64Tools.DONT_GUNZIP) + } + + /** + * Encodes the bytes as a url-safe Base64 string without padding. It basically replaces the '+' and '/' characters in the + * normal encoding scheme with '-' and '_'. + */ + @JvmStatic + fun encodeUrlSafeWithoutPadding(bytes: ByteArray): String { + return Base64Tools.encodeBytes(bytes, Base64Tools.URL_SAFE or Base64Tools.DONT_GUNZIP).stripPadding() + } + + /** + * A very lenient decoder. Does not care about the presence of padding or whether it's url-safe or not. It'll just decode it. + */ + @Throws(IOException::class) + @JvmStatic + fun decode(value: String): ByteArray { + return if (value.contains('-') || value.contains('_')) { + Base64Tools.decode(value.withPaddingIfNeeded(), Base64Tools.URL_SAFE or Base64Tools.DONT_GUNZIP) + } else { + Base64Tools.decode(value.withPaddingIfNeeded()) + } + } + + @JvmStatic + fun decode(value: ByteArray): ByteArray { + // This pattern of trying US_ASCII first mimics how Base64Tools handles strings + return try { + decode(String(value, Charsets.US_ASCII)) + } catch (e: UnsupportedEncodingException) { + decode(String(value, Charsets.UTF_8)) + } + } + + /** + * The same as [decode], except that instead of requiring you to handle an exception, this will just crash on invalid base64 strings. + * Should only be used if the value is definitely a valid base64 string. + */ + @JvmStatic + fun decodeOrThrow(value: String): ByteArray { + return try { + decode(value) + } catch (e: IOException) { + throw AssertionError(e) + } + } + + /** + * The same as [decode], except that instead of requiring you to handle an exception, this will just crash on invalid base64 strings. + * It also allows null inputs. If the input is null, the outpul will be null. + * Should only be used if the value is definitely a valid base64 string. + */ + @JvmStatic + fun decodeNullableOrThrow(value: String?): ByteArray? { + if (value == null) { + return null + } + + return try { + decode(value) + } catch (e: IOException) { + throw AssertionError(e) + } + } + + private fun String.withPaddingIfNeeded(): String { + return when (this.length % 4) { + 2 -> "$this==" + 3 -> "$this=" + else -> this + } + } + + private fun String.stripPadding(): String { + return this.replace("=", "") + } +} diff --git a/libsignal-service/src/main/java/org/whispersystems/util/Base64.java b/core-util-jvm/src/main/java/org/signal/core/util/Base64Tools.java similarity index 95% rename from libsignal-service/src/main/java/org/whispersystems/util/Base64.java rename to core-util-jvm/src/main/java/org/signal/core/util/Base64Tools.java index 70daaaeb5d..fb858ed1d2 100644 --- a/libsignal-service/src/main/java/org/whispersystems/util/Base64.java +++ b/core-util-jvm/src/main/java/org/signal/core/util/Base64Tools.java @@ -1,4 +1,4 @@ -package org.whispersystems.util; +package org.signal.core.util; /** *

Encodes and decodes to and from Base64 notation.

@@ -6,9 +6,9 @@ package org.whispersystems.util; * *

Example:

* - * String encoded = Base64.encode( myByteArray ); + * String encoded = Base64Tools.encode( myByteArray ); *
- * byte[] myByteArray = Base64.decode( encoded ); + * byte[] myByteArray = Base64Tools.decode( encoded ); * *

The options parameter, which appears in a few places, is used to pass * several pieces of information to the encoder. In the "higher level" methods such as @@ -24,10 +24,10 @@ package org.whispersystems.util; *

The constants defined in Base64 can be OR-ed together to combine options, so you * might make a call like this:

* - * String encoded = Base64.encodeBytes( mybytes, Base64.GZIP | Base64.DO_BREAK_LINES ); + * String encoded = Base64Tools.encodeBytes( mybytes, Base64Tools.GZIP | Base64Tools.DO_BREAK_LINES ); *

to compress the data before encoding it and then making the output have newline characters.

*

Also...

- * String encoded = Base64.encodeBytes( crazyString.getBytes() ); + * String encoded = Base64Tools.encodeBytes( crazyString.getBytes() ); * * * @@ -36,11 +36,11 @@ package org.whispersystems.util; *

*
    *
  • v2.3.4 - Fixed bug when working with gzipped streams whereby flushing - * the Base64.OutputStream closed the Base64 encoding (by padding with equals + * the Base64Tools.OutputStream closed the Base64 encoding (by padding with equals * signs) too soon. Also added an option to suppress the automatic decoding * of gzipped streams. Also added experimental support for specifying a * class loader when using the - * {@link #decodeToObject(java.lang.String, int, java.lang.ClassLoader)} + * {@link #decodeToObject(String, int, ClassLoader)} * method.
  • *
  • v2.3.3 - Changed default char encoding to US-ASCII which reduces the internal Java * footprint with its CharEncoders and so forth. Fixed some javadocs that were @@ -85,10 +85,10 @@ package org.whispersystems.util; * encoding/decoding from one file to the next. Also added these Base64 dialects: *
      *
    1. The default is RFC3548 format.
    2. - *
    3. Calling Base64.setFormat(Base64.BASE64_FORMAT.URLSAFE_FORMAT) generates + *
    4. Calling Base64Tools.setFormat(Base64Tools.BASE64_FORMAT.URLSAFE_FORMAT) generates * URL and file name friendly format as described in Section 4 of RFC3548. * http://www.faqs.org/rfcs/rfc3548.html
    5. - *
    6. Calling Base64.setFormat(Base64.BASE64_FORMAT.ORDERED_FORMAT) generates + *
    7. Calling Base64Tools.setFormat(Base64Tools.BASE64_FORMAT.ORDERED_FORMAT) generates * URL and file name friendly format that preserves lexical ordering as described * in http://www.faqs.org/qa/rfcc-1940.html
    8. *
    @@ -136,38 +136,38 @@ package org.whispersystems.util; * @author rob@iharder.net * @version 2.3.3 */ -public class Base64 +class Base64Tools { - -/* ******** P U B L I C F I E L D S ******** */ - - + +/* ******** P U B L I C F I E L D S ******** */ + + /** No options specified. Value is zero. */ public final static int NO_OPTIONS = 0; - + /** Specify encoding in first bit. Value is one. */ public final static int ENCODE = 1; - - + + /** Specify decoding in first bit. Value is zero. */ public final static int DECODE = 0; - + /** Specify that data should be gzip-compressed in second bit. Value is two. */ public final static int GZIP = 2; /** Specify that gzipped data should not be automatically gunzipped. */ public final static int DONT_GUNZIP = 4; - - + + /** Do break lines when encoding. Value is 8. */ public final static int DO_BREAK_LINES = 8; - - /** + + /** * Encode using Base64-like encoding that is URL- and Filename-safe as described - * in Section 4 of RFC3548: + * in Section 4 of RFC3548: * http://www.faqs.org/rfcs/rfc3548.html. - * It is important to note that data encoded this way is not officially valid Base64, + * It is important to note that data encoded this way is not officially valid Base64, * or at the very least should not be called Base64 without also specifying that is * was encoded using the URL- and Filename-safe dialect. */ @@ -179,50 +179,50 @@ public class Base64 * http://www.faqs.org/qa/rfcc-1940.html. */ public final static int ORDERED = 32; - - -/* ******** P R I V A T E F I E L D S ******** */ - - + + +/* ******** P R I V A T E F I E L D S ******** */ + + /** Maximum line length (76) of Base64 output. */ private final static int MAX_LINE_LENGTH = 76; - - + + /** The equals sign (=) as a byte. */ private final static byte EQUALS_SIGN = (byte)'='; - - + + /** The new line character (\n) as a byte. */ private final static byte NEW_LINE = (byte)'\n'; - - + + /** Preferred encoding. */ private final static String PREFERRED_ENCODING = "US-ASCII"; - - + + private final static byte WHITE_SPACE_ENC = -5; // Indicates white space in encoding private final static byte EQUALS_SIGN_ENC = -1; // Indicates equals sign in encoding - - -/* ******** S T A N D A R D B A S E 6 4 A L P H A B E T ******** */ - + + +/* ******** S T A N D A R D B A S E 6 4 A L P H A B E T ******** */ + /** The 64 valid Base64 values. */ /* Host platform me be something funny like EBCDIC, so we hardcode these values. */ private final static byte[] _STANDARD_ALPHABET = { (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G', (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N', - (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U', + (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U', (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z', (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g', (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n', - (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u', + (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u', (byte)'v', (byte)'w', (byte)'x', (byte)'y', (byte)'z', - (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', + (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7', (byte)'8', (byte)'9', (byte)'+', (byte)'/' }; - - - /** + + + /** * Translates a Base64 value to either its 6-bit reconstruction value * or a negative number indicating some other meaning. **/ @@ -259,30 +259,30 @@ public class Base64 -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243 -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */ }; - - + + /* ******** U R L S A F E B A S E 6 4 A L P H A B E T ******** */ - + /** - * Used in the URL- and Filename-safe dialect described in Section 4 of RFC3548: + * Used in the URL- and Filename-safe dialect described in Section 4 of RFC3548: * http://www.faqs.org/rfcs/rfc3548.html. * Notice that the last two bytes become "hyphen" and "underscore" instead of "plus" and "slash." */ private final static byte[] _URL_SAFE_ALPHABET = { (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G', (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N', - (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U', + (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U', (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z', (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g', (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n', - (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u', + (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u', (byte)'v', (byte)'w', (byte)'x', (byte)'y', (byte)'z', - (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', + (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7', (byte)'8', (byte)'9', (byte)'-', (byte)'_' }; - + /** - * Used in decoding URL- and Filename-safe dialects of Base64. + * Used in decoding URL- and Filename-safe dialects of Base64Tools. */ private final static byte[] _URL_SAFE_DECODABET = { -9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 0 - 8 @@ -345,9 +345,9 @@ public class Base64 (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u', (byte)'v', (byte)'w', (byte)'x', (byte)'y', (byte)'z' }; - + /** - * Used in decoding the "ordered" dialect of Base64. + * Used in decoding the "ordered" dialect of Base64Tools. */ private final static byte[] _ORDERED_DECODABET = { -9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 0 - 8 @@ -387,7 +387,7 @@ public class Base64 -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */ }; - + /* ******** D E T E R M I N E W H I C H A L H A B E T ******** */ @@ -427,9 +427,9 @@ public class Base64 } // end getAlphabet - + /** Defeats instantiation. */ - private Base64(){} + private Base64Tools(){} @@ -564,7 +564,7 @@ public class Base64 while( raw.hasRemaining() ){ int rem = Math.min(3,raw.remaining()); raw.get(raw3,0,rem); - Base64.encode3to4(enc4, raw3, rem, Base64.NO_OPTIONS ); + Base64Tools.encode3to4(enc4, raw3, rem, Base64Tools.NO_OPTIONS ); encoded.put(enc4); } // end input remaining } @@ -588,7 +588,7 @@ public class Base64 while( raw.hasRemaining() ){ int rem = Math.min(3,raw.remaining()); raw.get(raw3,0,rem); - Base64.encode3to4(enc4, raw3, rem, Base64.NO_OPTIONS ); + Base64Tools.encode3to4(enc4, raw3, rem, Base64Tools.NO_OPTIONS ); for( int i = 0; i < 4; i++ ){ encoded.put( (char)(enc4[i] & 0xFF) ); } @@ -640,9 +640,9 @@ public class Base64 * DO_BREAK_LINES: break lines at 76 characters * *

    - * Example: encodeObject( myObj, Base64.GZIP ) or + * Example: encodeObject( myObj, Base64Tools.GZIP ) or *

    - * Example: encodeObject( myObj, Base64.GZIP | Base64.DO_BREAK_LINES ) + * Example: encodeObject( myObj, Base64Tools.GZIP | Base64Tools.DO_BREAK_LINES ) * * @param serializableObject The object to encode * @param options Specified options @@ -669,7 +669,7 @@ public class Base64 try { // ObjectOutputStream -> (GZIP) -> Base64 -> ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream(); - b64os = new Base64.OutputStream( baos, ENCODE | options ); + b64os = new Base64Tools.OutputStream( baos, ENCODE | options ); if( (options & GZIP) != 0 ){ // Gzip gzos = new java.util.zip.GZIPOutputStream(b64os); @@ -760,9 +760,9 @@ public class Base64 * Note: Technically, this makes your encoding non-compliant. * *

    - * Example: encodeBytes( myData, Base64.GZIP ) or + * Example: encodeBytes( myData, Base64Tools.GZIP ) or *

    - * Example: encodeBytes( myData, Base64.GZIP | Base64.DO_BREAK_LINES ) + * Example: encodeBytes( myData, Base64Tools.GZIP | Base64Tools.DO_BREAK_LINES ) * * *

    As of v 2.3, if there is an error with the GZIP stream, @@ -828,9 +828,9 @@ public class Base64 * Note: Technically, this makes your encoding non-compliant. * *

    - * Example: encodeBytes( myData, Base64.GZIP ) or + * Example: encodeBytes( myData, Base64Tools.GZIP ) or *

    - * Example: encodeBytes( myData, Base64.GZIP | Base64.DO_BREAK_LINES ) + * Example: encodeBytes( myData, Base64Tools.GZIP | Base64Tools.DO_BREAK_LINES ) * * *

    As of v 2.3, if there is an error with the GZIP stream, @@ -881,7 +881,7 @@ public class Base64 public static byte[] encodeBytesToBytes( byte[] source ) { byte[] encoded = null; try { - encoded = encodeBytesToBytes( source, 0, source.length, Base64.NO_OPTIONS ); + encoded = encodeBytesToBytes( source, 0, source.length, Base64Tools.NO_OPTIONS ); } catch( java.io.IOException ex ) { assert false : "IOExceptions only come from GZipping, which is turned off: " + ex.getMessage(); } @@ -932,12 +932,12 @@ public class Base64 if( (options & GZIP) != 0 ) { java.io.ByteArrayOutputStream baos = null; java.util.zip.GZIPOutputStream gzos = null; - Base64.OutputStream b64os = null; + Base64Tools.OutputStream b64os = null; try { // GZip -> Base64 -> ByteArray baos = new java.io.ByteArrayOutputStream(); - b64os = new Base64.OutputStream( baos, ENCODE | options ); + b64os = new Base64Tools.OutputStream( baos, ENCODE | options ); gzos = new java.util.zip.GZIPOutputStream( b64os ); gzos.write( source, off, len ); @@ -1138,7 +1138,7 @@ public class Base64 public static byte[] decode( byte[] source ){ byte[] decoded = null; try { - decoded = decode( source, 0, source.length, Base64.NO_OPTIONS ); + decoded = decode( source, 0, source.length, Base64Tools.NO_OPTIONS ); } catch( java.io.IOException ex ) { assert false : "IOExceptions only come from GZipping, which is turned off: " + ex.getMessage(); } @@ -1345,7 +1345,7 @@ public class Base64 * @since 1.5 */ public static Object decodeToObject( String encodedObject ) - throws java.io.IOException, java.lang.ClassNotFoundException { + throws java.io.IOException, ClassNotFoundException { return decodeToObject(encodedObject,NO_OPTIONS,null); } @@ -1368,7 +1368,7 @@ public class Base64 */ public static Object decodeToObject( String encodedObject, int options, final ClassLoader loader ) - throws java.io.IOException, java.lang.ClassNotFoundException { + throws java.io.IOException, ClassNotFoundException { // Decode and gunzip if necessary byte[] objBytes = decode( encodedObject, options ); @@ -1407,7 +1407,7 @@ public class Base64 catch( java.io.IOException e ) { throw e; // Catch and throw in order to execute finally{} } // end catch - catch( java.lang.ClassNotFoundException e ) { + catch( ClassNotFoundException e ) { throw e; // Catch and throw in order to execute finally{} } // end catch finally { @@ -1441,10 +1441,10 @@ public class Base64 throw new NullPointerException( "Data to encode was null." ); } // end iff - Base64.OutputStream bos = null; + Base64Tools.OutputStream bos = null; try { - bos = new Base64.OutputStream( - new java.io.FileOutputStream( filename ), Base64.ENCODE ); + bos = new Base64Tools.OutputStream( + new java.io.FileOutputStream( filename ), Base64Tools.ENCODE ); bos.write( dataToEncode ); } // end try catch( java.io.IOException e ) { @@ -1473,10 +1473,10 @@ public class Base64 public static void decodeToFile( String dataToDecode, String filename ) throws java.io.IOException { - Base64.OutputStream bos = null; + Base64Tools.OutputStream bos = null; try{ - bos = new Base64.OutputStream( - new java.io.FileOutputStream( filename ), Base64.DECODE ); + bos = new Base64Tools.OutputStream( + new java.io.FileOutputStream( filename ), Base64Tools.DECODE ); bos.write( dataToDecode.getBytes( PREFERRED_ENCODING ) ); } // end try catch( java.io.IOException e ) { @@ -1509,7 +1509,7 @@ public class Base64 throws java.io.IOException { byte[] decodedData = null; - Base64.InputStream bis = null; + Base64Tools.InputStream bis = null; try { // Set up some useful variables @@ -1526,9 +1526,9 @@ public class Base64 buffer = new byte[ (int)file.length() ]; // Open a stream - bis = new Base64.InputStream( + bis = new Base64Tools.InputStream( new java.io.BufferedInputStream( - new java.io.FileInputStream( file ) ), Base64.DECODE ); + new java.io.FileInputStream( file ) ), Base64Tools.DECODE ); // Read until done while( ( numBytes = bis.read( buffer, length, 4096 ) ) >= 0 ) { @@ -1570,7 +1570,7 @@ public class Base64 throws java.io.IOException { String encodedData = null; - Base64.InputStream bis = null; + Base64Tools.InputStream bis = null; try { // Set up some useful variables @@ -1580,9 +1580,9 @@ public class Base64 int numBytes = 0; // Open a stream - bis = new Base64.InputStream( + bis = new Base64Tools.InputStream( new java.io.BufferedInputStream( - new java.io.FileInputStream( file ) ), Base64.ENCODE ); + new java.io.FileInputStream( file ) ), Base64Tools.ENCODE ); // Read until done while( ( numBytes = bis.read( buffer, length, 4096 ) ) >= 0 ) { @@ -1590,7 +1590,7 @@ public class Base64 } // end while // Save in a variable to return - encodedData = new String( buffer, 0, length, Base64.PREFERRED_ENCODING ); + encodedData = new String( buffer, 0, length, Base64Tools.PREFERRED_ENCODING ); } // end try catch( java.io.IOException e ) { @@ -1614,7 +1614,7 @@ public class Base64 public static void encodeFileToFile( String infile, String outfile ) throws java.io.IOException { - String encoded = Base64.encodeFromFile( infile ); + String encoded = Base64Tools.encodeFromFile( infile ); java.io.OutputStream out = null; try{ out = new java.io.BufferedOutputStream( @@ -1642,7 +1642,7 @@ public class Base64 public static void decodeFileToFile( String infile, String outfile ) throws java.io.IOException { - byte[] decoded = Base64.decodeFromFile( infile ); + byte[] decoded = Base64Tools.decodeFromFile( infile ); java.io.OutputStream out = null; try{ out = new java.io.BufferedOutputStream( @@ -1664,7 +1664,7 @@ public class Base64 /** - * A {@link Base64.InputStream} will read data from another + * A {@link Base64Tools.InputStream} will read data from another * java.io.InputStream, given in the constructor, * and encode/decode to/from Base64 notation on the fly. * @@ -1685,7 +1685,7 @@ public class Base64 /** - * Constructs a {@link Base64.InputStream} in DECODE mode. + * Constructs a {@link Base64Tools.InputStream} in DECODE mode. * * @param in the java.io.InputStream from which to read data. * @since 1.3 @@ -1696,7 +1696,7 @@ public class Base64 /** - * Constructs a {@link Base64.InputStream} in + * Constructs a {@link Base64Tools.InputStream} in * either ENCODE or DECODE mode. *

    * Valid options:

    @@ -1705,7 +1705,7 @@ public class Base64
              *     (only meaningful when encoding)
              * 
    *

    - * Example: new Base64.InputStream( in, Base64.DECODE ) + * Example: new Base64Tools.InputStream( in, Base64Tools.DECODE ) * * * @param in the java.io.InputStream from which to read data. @@ -1877,7 +1877,7 @@ public class Base64 /** - * A {@link Base64.OutputStream} will write data to another + * A {@link Base64Tools.OutputStream} will write data to another * java.io.OutputStream, given in the constructor, * and encode/decode to/from Base64 notation on the fly. * @@ -1898,7 +1898,7 @@ public class Base64 private byte[] decodabet; // Local copies to avoid extra method calls /** - * Constructs a {@link Base64.OutputStream} in ENCODE mode. + * Constructs a {@link Base64Tools.OutputStream} in ENCODE mode. * * @param out the java.io.OutputStream to which data will be written. * @since 1.3 @@ -1909,7 +1909,7 @@ public class Base64 /** - * Constructs a {@link Base64.OutputStream} in + * Constructs a {@link Base64Tools.OutputStream} in * either ENCODE or DECODE mode. *

    * Valid options:

    @@ -1918,7 +1918,7 @@ public class Base64
              *     (only meaningful when encoding)
              * 
    *

    - * Example: new Base64.OutputStream( out, Base64.ENCODE ) + * Example: new Base64Tools.OutputStream( out, Base64Tools.ENCODE ) * * @param out the java.io.OutputStream to which data will be written. * @param options Specified options. @@ -1987,7 +1987,7 @@ public class Base64 buffer[ position++ ] = (byte)theByte; if( position >= bufferLength ) { // Enough to output. - int len = Base64.decode4to3( buffer, 0, b4, 0, options ); + int len = Base64Tools.decode4to3( buffer, 0, b4, 0, options ); out.write( b4, 0, len ); position = 0; } // end if: enough to output diff --git a/core-util-jvm/src/test/java/org/signal/core/util/Base64Test.kt b/core-util-jvm/src/test/java/org/signal/core/util/Base64Test.kt new file mode 100644 index 0000000000..54a2507d0d --- /dev/null +++ b/core-util-jvm/src/test/java/org/signal/core/util/Base64Test.kt @@ -0,0 +1,36 @@ +/* + * Copyright 2023 Signal Messenger, LLC + * SPDX-License-Identifier: AGPL-3.0-only + */ + +package org.signal.core.util + +import org.junit.Assert.assertArrayEquals +import org.junit.Test +import kotlin.random.Random + +class Base64Test { + + @Test + fun `decode - correctly decode all strings regardless of url safety or padding`() { + val stopwatch = Stopwatch("time", 2) + + for (len in 0 until 256) { + for (i in 0..2_000) { + val bytes = Random.nextBytes(len) + + val padded = Base64.encodeWithPadding(bytes) + val unpadded = Base64.encodeWithoutPadding(bytes) + val urlSafePadded = Base64.encodeUrlSafeWithPadding(bytes) + val urlSafeUnpadded = Base64.encodeUrlSafeWithoutPadding(bytes) + + assertArrayEquals(bytes, Base64.decode(padded)) + assertArrayEquals(bytes, Base64.decode(unpadded)) + assertArrayEquals(bytes, Base64.decode(urlSafePadded)) + assertArrayEquals(bytes, Base64.decode(urlSafeUnpadded)) + } + } + + println(stopwatch.stopAndGetLogString()) + } +} diff --git a/libsignal-service/build.gradle b/libsignal-service/build.gradle index eb476cdd0a..4e342943bc 100644 --- a/libsignal-service/build.gradle +++ b/libsignal-service/build.gradle @@ -65,6 +65,8 @@ dependencies { implementation libs.kotlin.stdlib.jdk8 + implementation project(":core-util-jvm") + testImplementation testLibs.junit.junit testImplementation testLibs.assertj.core testImplementation testLibs.conscrypt.openjdk.uber diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/SignalServiceAccountManager.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/SignalServiceAccountManager.java index c4ae426bf5..fbaf774da9 100644 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/SignalServiceAccountManager.java +++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/SignalServiceAccountManager.java @@ -81,8 +81,7 @@ import org.whispersystems.signalservice.internal.storage.protos.WriteOperation; import org.whispersystems.signalservice.internal.util.StaticCredentialsProvider; import org.whispersystems.signalservice.internal.util.Util; import org.whispersystems.signalservice.internal.websocket.DefaultResponseMapper; -import org.whispersystems.util.Base64; -import org.whispersystems.util.Base64UrlSafe; +import org.signal.core.util.Base64; import java.io.IOException; import java.security.KeyStore; @@ -801,7 +800,7 @@ public class SignalServiceAccountManager { public UsernameLinkComponents createUsernameLink(Username username) throws IOException { try { UsernameLink link = username.generateLink(); - UUID serverId = this.pushServiceSocket.createUsernameLink(Base64UrlSafe.encodeBytes(link.getEncryptedUsername())); + UUID serverId = this.pushServiceSocket.createUsernameLink(Base64.encodeUrlSafeWithPadding(link.getEncryptedUsername())); return new UsernameLinkComponents(link.getEntropy(), serverId); } catch (BaseUsernameException e) { @@ -841,7 +840,7 @@ public class SignalServiceAccountManager { try { MessageDigest digest = MessageDigest.getInstance("SHA1"); byte[] token = Util.trim(digest.digest(e164number.getBytes()), 10); - String encoded = Base64.encodeBytesWithoutPadding(token); + String encoded = Base64.encodeWithoutPadding(token); if (urlSafe) return encoded.replace('+', '-').replace('/', '_'); else return encoded; diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java index 6e0df4b0aa..7cd3a3a7c9 100644 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java +++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java @@ -127,7 +127,7 @@ import org.whispersystems.signalservice.internal.push.http.PartialSendBatchCompl import org.whispersystems.signalservice.internal.push.http.PartialSendCompleteListener; import org.whispersystems.signalservice.internal.push.http.ResumableUploadSpec; import org.whispersystems.signalservice.internal.util.Util; -import org.whispersystems.util.Base64; +import org.signal.core.util.Base64; import org.whispersystems.util.ByteArrayUtil; import java.io.IOException; @@ -888,7 +888,7 @@ public class SignalServiceMessageSender { throws IOException, UntrustedIdentityException { byte[] nullMessageBody = new DataMessage.Builder() - .body(Base64.encodeBytes(Util.getRandomLengthBytes(140))) + .body(Base64.encodeWithPadding(Util.getRandomLengthBytes(140))) .build() .encode(); @@ -918,7 +918,7 @@ public class SignalServiceMessageSender { throws UntrustedIdentityException, IOException { byte[] nullMessageBody = new DataMessage.Builder() - .body(Base64.encodeBytes(Util.getRandomLengthBytes(140))) + .body(Base64.encodeWithPadding(Util.getRandomLengthBytes(140))) .build() .encode(); diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/SignalWebSocket.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/SignalWebSocket.java index 0c7dccce8f..d326dfe99f 100644 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/SignalWebSocket.java +++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/SignalWebSocket.java @@ -11,7 +11,7 @@ import org.whispersystems.signalservice.internal.websocket.WebSocketConnection; import org.whispersystems.signalservice.internal.websocket.WebSocketRequestMessage; import org.whispersystems.signalservice.internal.websocket.WebSocketResponseMessage; import org.whispersystems.signalservice.internal.websocket.WebsocketResponse; -import org.whispersystems.util.Base64; +import org.signal.core.util.Base64; import java.io.IOException; import java.util.ArrayList; @@ -201,7 +201,7 @@ public final class SignalWebSocket { public Single request(WebSocketRequestMessage requestMessage, Optional unidentifiedAccess) { if (unidentifiedAccess.isPresent()) { List headers = new ArrayList<>(requestMessage.headers); - headers.add("Unidentified-Access-Key:" + Base64.encodeBytes(unidentifiedAccess.get().getUnidentifiedAccessKey())); + headers.add("Unidentified-Access-Key:" + Base64.encodeWithPadding(unidentifiedAccess.get().getUnidentifiedAccessKey())); WebSocketRequestMessage message = requestMessage.newBuilder() .headers(headers) .build(); diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/crypto/EnvelopeContent.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/crypto/EnvelopeContent.java index aeea9fb0a2..1d87bb3916 100644 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/crypto/EnvelopeContent.java +++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/crypto/EnvelopeContent.java @@ -13,7 +13,7 @@ import org.whispersystems.signalservice.internal.push.Content; import org.whispersystems.signalservice.internal.push.Envelope.Type; import org.whispersystems.signalservice.internal.push.OutgoingPushMessage; import org.whispersystems.signalservice.internal.push.PushTransportDetails; -import org.whispersystems.util.Base64; +import org.signal.core.util.Base64; import java.util.Optional; @@ -88,7 +88,7 @@ public interface EnvelopeContent { groupId); byte[] ciphertext = sealedSessionCipher.encrypt(destination, messageContent); - String body = Base64.encodeBytes(ciphertext); + String body = Base64.encodeWithPadding(ciphertext); int remoteRegistrationId = sealedSessionCipher.getRemoteRegistrationId(destination); return new OutgoingPushMessage(Type.UNIDENTIFIED_SENDER.getValue(), destination.getDeviceId(), remoteRegistrationId, body); @@ -99,7 +99,7 @@ public interface EnvelopeContent { PushTransportDetails transportDetails = new PushTransportDetails(); CiphertextMessage message = sessionCipher.encrypt(transportDetails.getPaddedMessageBody(content.encode())); int remoteRegistrationId = sessionCipher.getRemoteRegistrationId(); - String body = Base64.encodeBytes(message.serialize()); + String body = Base64.encodeWithPadding(message.serialize()); int type; @@ -146,7 +146,7 @@ public interface EnvelopeContent { groupId); byte[] ciphertext = sealedSessionCipher.encrypt(destination, messageContent); - String body = Base64.encodeBytes(ciphertext); + String body = Base64.encodeWithPadding(ciphertext); int remoteRegistrationId = sealedSessionCipher.getRemoteRegistrationId(destination); return new OutgoingPushMessage(Type.UNIDENTIFIED_SENDER.getValue(), destination.getDeviceId(), remoteRegistrationId, body); @@ -154,7 +154,7 @@ public interface EnvelopeContent { @Override public OutgoingPushMessage processUnsealedSender(SignalSessionCipher sessionCipher, SignalProtocolAddress destination) { - String body = Base64.encodeBytes(plaintextContent.serialize()); + String body = Base64.encodeWithPadding(plaintextContent.serialize()); int remoteRegistrationId = sessionCipher.getRemoteRegistrationId(); return new OutgoingPushMessage(Type.PLAINTEXT_CONTENT.getValue(), destination.getDeviceId(), remoteRegistrationId, body); diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/kbs/MasterKey.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/kbs/MasterKey.java index 5e6f43354b..c4708c7b23 100644 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/kbs/MasterKey.java +++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/kbs/MasterKey.java @@ -2,7 +2,7 @@ package org.whispersystems.signalservice.api.kbs; import org.whispersystems.signalservice.api.storage.StorageKey; import org.whispersystems.signalservice.internal.util.Hex; -import org.whispersystems.util.Base64; +import org.signal.core.util.Base64; import org.whispersystems.util.StringUtil; import java.security.SecureRandom; @@ -33,7 +33,7 @@ public final class MasterKey { } public String deriveRegistrationRecoveryPassword() { - return Base64.encodeBytes(derive("Registration Recovery")); + return Base64.encodeWithPadding(derive("Registration Recovery")); } public StorageKey deriveStorageServiceKey() { diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/push/SignedPreKeyEntity.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/push/SignedPreKeyEntity.java index f5b108f118..2ae05785e3 100644 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/push/SignedPreKeyEntity.java +++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/push/SignedPreKeyEntity.java @@ -18,7 +18,7 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize; import org.signal.libsignal.protocol.ecc.ECPublicKey; import org.whispersystems.signalservice.internal.push.PreKeyEntity; -import org.whispersystems.util.Base64; +import org.signal.core.util.Base64; import java.io.IOException; @@ -43,7 +43,7 @@ public class SignedPreKeyEntity extends PreKeyEntity { private static class ByteArraySerializer extends JsonSerializer { @Override public void serialize(byte[] value, JsonGenerator gen, SerializerProvider serializers) throws IOException { - gen.writeString(Base64.encodeBytesWithoutPadding(value)); + gen.writeString(Base64.encodeWithoutPadding(value)); } } @@ -51,7 +51,7 @@ public class SignedPreKeyEntity extends PreKeyEntity { @Override public byte[] deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { - return Base64.decodeWithoutPadding(p.getValueAsString()); + return Base64.decode(p.getValueAsString()); } } } diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/services/CdsiSocket.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/services/CdsiSocket.java index 1fbd16a2da..f6f01aebba 100644 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/services/CdsiSocket.java +++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/services/CdsiSocket.java @@ -22,7 +22,7 @@ import org.whispersystems.signalservice.internal.util.BlacklistingTrustManager; import org.whispersystems.signalservice.internal.util.Hex; import org.whispersystems.signalservice.internal.util.JsonUtil; import org.whispersystems.signalservice.internal.util.Util; -import org.whispersystems.util.Base64; +import org.signal.core.util.Base64; import java.io.IOException; import java.nio.charset.StandardCharsets; @@ -214,7 +214,7 @@ final class CdsiSocket { } private static String basicAuth(String username, String password) { - return "Basic " + Base64.encodeBytes((username + ":" + password).getBytes(StandardCharsets.UTF_8)); + return "Basic " + Base64.encodeWithPadding((username + ":" + password).getBytes(StandardCharsets.UTF_8)); } private static Pair createTlsSocketFactory(TrustStore trustStore) { diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/services/MessagingService.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/services/MessagingService.java index 0abb0e4840..72712a88dd 100644 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/services/MessagingService.java +++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/services/MessagingService.java @@ -19,7 +19,7 @@ import org.whispersystems.signalservice.internal.util.Util; import org.whispersystems.signalservice.internal.websocket.DefaultResponseMapper; import org.whispersystems.signalservice.internal.websocket.ResponseMapper; import org.whispersystems.signalservice.internal.websocket.WebSocketRequestMessage; -import org.whispersystems.util.Base64; +import org.signal.core.util.Base64; import java.security.SecureRandom; import java.util.LinkedList; @@ -74,7 +74,7 @@ public class MessagingService { public Single> sendToGroup(byte[] body, byte[] joinedUnidentifiedAccess, long timestamp, boolean online, boolean urgent, boolean story) { List headers = new LinkedList() {{ add("content-type:application/vnd.signal-messenger.mrm"); - add("Unidentified-Access-Key:" + Base64.encodeBytes(joinedUnidentifiedAccess)); + add("Unidentified-Access-Key:" + Base64.encodeWithPadding(joinedUnidentifiedAccess)); }}; String path = String.format(Locale.US, "/v1/messages/multi_recipient?ts=%s&online=%s&urgent=%s&story=%s", timestamp, online, urgent, story); diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/storage/StorageKey.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/storage/StorageKey.java index 034b8c4f9b..9e3ea5df32 100644 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/storage/StorageKey.java +++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/storage/StorageKey.java @@ -1,7 +1,7 @@ package org.whispersystems.signalservice.api.storage; import org.whispersystems.signalservice.api.kbs.MasterKey; -import org.whispersystems.util.Base64; +import org.signal.core.util.Base64; import org.whispersystems.util.StringUtil; import java.util.Arrays; @@ -31,7 +31,7 @@ public final class StorageKey { } public StorageItemKey deriveItemKey(byte[] key) { - return new StorageItemKey(derive("Item_" + Base64.encodeBytes(key))); + return new StorageItemKey(derive("Item_" + Base64.encodeWithPadding(key))); } private byte[] derive(String keyName) { diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/subscriptions/IdempotencyKey.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/subscriptions/IdempotencyKey.java index 1f4c64d02c..1c6de11c05 100644 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/subscriptions/IdempotencyKey.java +++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/subscriptions/IdempotencyKey.java @@ -1,8 +1,8 @@ package org.whispersystems.signalservice.api.subscriptions; +import org.signal.core.util.Base64; import org.whispersystems.signalservice.api.util.Preconditions; -import org.whispersystems.util.Base64UrlSafe; import java.security.SecureRandom; import java.util.Arrays; @@ -25,7 +25,7 @@ public final class IdempotencyKey { } public String serialize() { - return Base64UrlSafe.encodeBytes(bytes); + return Base64.encodeUrlSafeWithPadding(bytes); } public static IdempotencyKey fromBytes(byte[] bytes) { diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/subscriptions/SubscriberId.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/subscriptions/SubscriberId.java index 082e86e778..856fbcf7de 100644 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/subscriptions/SubscriberId.java +++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/subscriptions/SubscriberId.java @@ -1,8 +1,8 @@ package org.whispersystems.signalservice.api.subscriptions; +import org.signal.core.util.Base64; import org.whispersystems.signalservice.api.util.Preconditions; -import org.whispersystems.util.Base64UrlSafe; import java.security.SecureRandom; import java.util.Arrays; @@ -27,7 +27,7 @@ public final class SubscriberId { } public @NonNull String serialize() { - return Base64UrlSafe.encodeBytes(bytes); + return Base64.encodeUrlSafeWithPadding(bytes); } public static SubscriberId fromBytes(byte[] bytes) { diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/contacts/crypto/SigningCertificate.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/contacts/crypto/SigningCertificate.java index c490ab62d2..48bd02f6d7 100644 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/contacts/crypto/SigningCertificate.java +++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/contacts/crypto/SigningCertificate.java @@ -1,6 +1,6 @@ package org.whispersystems.signalservice.internal.contacts.crypto; -import org.whispersystems.util.Base64; +import org.signal.core.util.Base64; import java.io.ByteArrayInputStream; import java.security.InvalidAlgorithmParameterException; diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/BoostReceiptCredentialRequestJson.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/BoostReceiptCredentialRequestJson.java index b065a21ad0..4df8eab03f 100644 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/BoostReceiptCredentialRequestJson.java +++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/BoostReceiptCredentialRequestJson.java @@ -3,7 +3,7 @@ package org.whispersystems.signalservice.internal.push; import com.fasterxml.jackson.annotation.JsonProperty; import org.signal.libsignal.zkgroup.receipts.ReceiptCredentialRequest; -import org.whispersystems.util.Base64; +import org.signal.core.util.Base64; class BoostReceiptCredentialRequestJson { @JsonProperty("paymentIntentId") @@ -17,7 +17,7 @@ class BoostReceiptCredentialRequestJson { BoostReceiptCredentialRequestJson(String paymentIntentId, ReceiptCredentialRequest receiptCredentialRequest, DonationProcessor processor) { this.paymentIntentId = paymentIntentId; - this.receiptCredentialRequest = Base64.encodeBytes(receiptCredentialRequest.serialize()); + this.receiptCredentialRequest = Base64.encodeWithPadding(receiptCredentialRequest.serialize()); this.processor = processor.getCode(); } } diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/CreateCallLinkAuthRequest.kt b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/CreateCallLinkAuthRequest.kt index a2f696d509..38f1f9edab 100644 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/CreateCallLinkAuthRequest.kt +++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/CreateCallLinkAuthRequest.kt @@ -6,8 +6,8 @@ package org.whispersystems.signalservice.internal.push import com.fasterxml.jackson.annotation.JsonCreator +import org.signal.core.util.Base64 import org.signal.libsignal.zkgroup.calllinks.CreateCallLinkCredentialRequest -import org.whispersystems.util.Base64 /** * Request body to create a call link credential response. @@ -19,7 +19,7 @@ data class CreateCallLinkAuthRequest @JsonCreator constructor( @JvmStatic fun create(createCallLinkCredentialRequest: CreateCallLinkCredentialRequest): CreateCallLinkAuthRequest { return CreateCallLinkAuthRequest( - Base64.encodeBytes(createCallLinkCredentialRequest.serialize()) + Base64.encodeWithPadding(createCallLinkCredentialRequest.serialize()) ) } } diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/CreateCallLinkAuthResponse.kt b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/CreateCallLinkAuthResponse.kt index 544f6d5184..63d1c289ec 100644 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/CreateCallLinkAuthResponse.kt +++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/CreateCallLinkAuthResponse.kt @@ -7,8 +7,8 @@ package org.whispersystems.signalservice.internal.push import com.fasterxml.jackson.annotation.JsonCreator import com.fasterxml.jackson.annotation.JsonProperty +import org.signal.core.util.Base64 import org.signal.libsignal.zkgroup.calllinks.CreateCallLinkCredentialResponse -import org.whispersystems.util.Base64 /** * Response body for CreateCallLinkAuthResponse diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/IdentityCheckRequest.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/IdentityCheckRequest.java index cb57ddae90..669f30bf51 100644 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/IdentityCheckRequest.java +++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/IdentityCheckRequest.java @@ -6,7 +6,7 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize; import org.signal.libsignal.protocol.IdentityKey; import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.internal.util.JsonUtil; -import org.whispersystems.util.Base64; +import org.signal.core.util.Base64; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; @@ -40,7 +40,7 @@ public class IdentityCheckRequest { try { MessageDigest messageDigest = MessageDigest.getInstance("SHA-256"); - this.fingerprint = Base64.encodeBytes(messageDigest.digest(identityKey.serialize()), 0, 4); + this.fingerprint = Base64.encodeWithPadding(messageDigest.digest(identityKey.serialize()), 0, 4); } catch (NoSuchAlgorithmException e) { throw new AssertionError(e); } diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/KyberPreKeyEntity.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/KyberPreKeyEntity.java index 7668d549a1..90520fc3f3 100644 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/KyberPreKeyEntity.java +++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/KyberPreKeyEntity.java @@ -18,7 +18,7 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize; import org.signal.libsignal.protocol.InvalidKeyException; import org.signal.libsignal.protocol.kem.KEMPublicKey; -import org.whispersystems.util.Base64; +import org.signal.core.util.Base64; import java.io.IOException; @@ -60,7 +60,7 @@ public class KyberPreKeyEntity { private static class KEMPublicKeySerializer extends JsonSerializer { @Override public void serialize(KEMPublicKey value, JsonGenerator gen, SerializerProvider serializers) throws IOException { - gen.writeString(Base64.encodeBytesWithoutPadding(value.serialize())); + gen.writeString(Base64.encodeWithoutPadding(value.serialize())); } } @@ -68,7 +68,7 @@ public class KyberPreKeyEntity { @Override public KEMPublicKey deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { try { - return new KEMPublicKey(Base64.decodeWithoutPadding(p.getValueAsString()), 0); + return new KEMPublicKey(Base64.decode(p.getValueAsString()), 0); } catch (InvalidKeyException e) { throw new IOException(e); } @@ -78,7 +78,7 @@ public class KyberPreKeyEntity { private static class ByteArraySerializer extends JsonSerializer { @Override public void serialize(byte[] value, JsonGenerator gen, SerializerProvider serializers) throws IOException { - gen.writeString(Base64.encodeBytesWithoutPadding(value)); + gen.writeString(Base64.encodeWithoutPadding(value)); } } @@ -86,7 +86,7 @@ public class KyberPreKeyEntity { @Override public byte[] deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { - return Base64.decodeWithoutPadding(p.getValueAsString()); + return Base64.decode(p.getValueAsString()); } } } diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/PreKeyEntity.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/PreKeyEntity.java index 37d771233b..488f62d119 100644 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/PreKeyEntity.java +++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/PreKeyEntity.java @@ -19,7 +19,7 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize; import org.signal.libsignal.protocol.InvalidKeyException; import org.signal.libsignal.protocol.ecc.Curve; import org.signal.libsignal.protocol.ecc.ECPublicKey; -import org.whispersystems.util.Base64; +import org.signal.core.util.Base64; import java.io.IOException; @@ -51,7 +51,7 @@ public class PreKeyEntity { private static class ECPublicKeySerializer extends JsonSerializer { @Override public void serialize(ECPublicKey value, JsonGenerator gen, SerializerProvider serializers) throws IOException { - gen.writeString(Base64.encodeBytesWithoutPadding(value.serialize())); + gen.writeString(Base64.encodeWithoutPadding(value.serialize())); } } @@ -59,7 +59,7 @@ public class PreKeyEntity { @Override public ECPublicKey deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { try { - return Curve.decodePoint(Base64.decodeWithoutPadding(p.getValueAsString()), 0); + return Curve.decodePoint(Base64.decode(p.getValueAsString()), 0); } catch (InvalidKeyException e) { throw new IOException(e); } diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/PushServiceSocket.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/PushServiceSocket.java index b894218aa2..074b8bd0b5 100644 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/PushServiceSocket.java +++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/PushServiceSocket.java @@ -142,8 +142,7 @@ import org.whispersystems.signalservice.internal.util.concurrent.FutureTransform import org.whispersystems.signalservice.internal.util.concurrent.ListenableFuture; import org.whispersystems.signalservice.internal.util.concurrent.SettableFuture; import org.whispersystems.signalservice.internal.websocket.ResponseMapper; -import org.whispersystems.util.Base64; -import org.whispersystems.util.Base64UrlSafe; +import org.signal.core.util.Base64; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -429,8 +428,8 @@ public class PushServiceSocket { RegistrationSessionRequestBody body = new RegistrationSessionRequestBody(sessionId, recoveryPassword, attributes, - Base64.encodeBytesWithoutPadding(aciPreKeys.getIdentityKey().serialize()), - Base64.encodeBytesWithoutPadding(pniPreKeys.getIdentityKey().serialize()), + Base64.encodeWithoutPadding(aciPreKeys.getIdentityKey().serialize()), + Base64.encodeWithoutPadding(pniPreKeys.getIdentityKey().serialize()), aciSignedPreKey, pniSignedPreKey, aciLastResortKyberPreKey, @@ -510,7 +509,7 @@ public class PushServiceSocket { public void sendProvisioningMessage(String destination, byte[] body) throws IOException { makeServiceRequest(String.format(PROVISIONING_MESSAGE_PATH, destination), "PUT", - JsonUtil.toJson(new ProvisioningMessage(Base64.encodeBytes(body)))); + JsonUtil.toJson(new ProvisioningMessage(Base64.encodeWithPadding(body)))); } public void registerGcmId(@Nonnull String gcmRegistrationId) throws IOException { @@ -560,7 +559,7 @@ public class PushServiceSocket { Request.Builder requestBuilder = new Request.Builder(); requestBuilder.url(String.format("%s%s", connectionHolder.getUrl(), path)); requestBuilder.put(RequestBody.create(MediaType.get("application/vnd.signal-messenger.mrm"), body)); - requestBuilder.addHeader("Unidentified-Access-Key", Base64.encodeBytes(joinedUnidentifiedAccess)); + requestBuilder.addHeader("Unidentified-Access-Key", Base64.encodeWithPadding(joinedUnidentifiedAccess)); if (signalAgent != null) { requestBuilder.addHeader("X-Signal-Agent", signalAgent); @@ -1071,7 +1070,7 @@ public class PushServiceSocket { byte[] proof = Username.generateProof(username, randomness); ConfirmUsernameRequest confirmUsernameRequest = new ConfirmUsernameRequest(reserveUsernameResponse.getUsernameHash(), - Base64UrlSafe.encodeBytesWithoutPadding(proof)); + Base64.encodeUrlSafeWithoutPadding(proof)); makeServiceRequest(CONFIRM_USERNAME_PATH, "PUT", JsonUtil.toJson(confirmUsernameRequest), NO_HEADERS, (responseCode, body) -> { switch (responseCode) { @@ -1115,7 +1114,7 @@ public class PushServiceSocket { String response = makeServiceRequestWithoutAuthentication(String.format(USERNAME_FROM_LINK_PATH, serverId.toString()), "GET", null); GetUsernameFromLinkResponseBody parsed = JsonUtil.fromJson(response, GetUsernameFromLinkResponseBody.class); - return Base64UrlSafe.decodePaddingAgnostic(parsed.getUsernameLinkEncryptedValue()); + return Base64.decode(parsed.getUsernameLinkEncryptedValue()); } public void deleteAccount() throws IOException { @@ -1137,7 +1136,7 @@ public class PushServiceSocket { } public void redeemDonationReceipt(ReceiptCredentialPresentation receiptCredentialPresentation, boolean visible, boolean primary) throws IOException { - String payload = JsonUtil.toJson(new RedeemReceiptRequest(Base64.encodeBytes(receiptCredentialPresentation.serialize()), visible, primary)); + String payload = JsonUtil.toJson(new RedeemReceiptRequest(Base64.encodeWithPadding(receiptCredentialPresentation.serialize()), visible, primary)); makeServiceRequest(DONATION_REDEEM_RECEIPT, "POST", payload); } @@ -2097,7 +2096,7 @@ public class PushServiceSocket { if (!headers.containsKey("Authorization") && !doNotAddAuthenticationOrUnidentifiedAccessKey) { if (unidentifiedAccess.isPresent()) { - request.addHeader("Unidentified-Access-Key", Base64.encodeBytes(unidentifiedAccess.get().getUnidentifiedAccessKey())); + request.addHeader("Unidentified-Access-Key", Base64.encodeWithPadding(unidentifiedAccess.get().getUnidentifiedAccessKey())); } else if (credentialsProvider.getPassword() != null) { request.addHeader("Authorization", getAuthorizationHeader(credentialsProvider)); } @@ -2395,7 +2394,7 @@ public class PushServiceSocket { if (credentialsProvider.getDeviceId() != SignalServiceAddress.DEFAULT_DEVICE_ID) { identifier += "." + credentialsProvider.getDeviceId(); } - return "Basic " + Base64.encodeBytes((identifier + ":" + credentialsProvider.getPassword()).getBytes("UTF-8")); + return "Basic " + Base64.encodeWithPadding((identifier + ":" + credentialsProvider.getPassword()).getBytes("UTF-8")); } catch (UnsupportedEncodingException e) { throw new AssertionError(e); } @@ -2663,7 +2662,7 @@ public class PushServiceSocket { String path; if (groupLinkPassword.isPresent()) { - path = String.format(GROUPSV2_GROUP_PASSWORD, Base64UrlSafe.encodeBytesWithoutPadding(groupLinkPassword.get())); + path = String.format(GROUPSV2_GROUP_PASSWORD, Base64.encodeUrlSafeWithoutPadding(groupLinkPassword.get())); } else { path = GROUPSV2_GROUP; } @@ -2719,7 +2718,7 @@ public class PushServiceSocket { public GroupJoinInfo getGroupJoinInfo(Optional groupLinkPassword, GroupsV2AuthorizationString authorization) throws NonSuccessfulResponseCodeException, PushNetworkException, IOException, MalformedResponseException { - String passwordParam = groupLinkPassword.map(Base64UrlSafe::encodeBytesWithoutPadding).orElse(""); + String passwordParam = groupLinkPassword.map(org.signal.core.util.Base64::encodeUrlSafeWithoutPadding).orElse(""); try (Response response = makeStorageRequest(authorization.toString(), String.format(GROUPSV2_GROUP_JOIN, passwordParam), "GET", diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/ReceiptCredentialRequestJson.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/ReceiptCredentialRequestJson.java index cd5037ce94..9d33692998 100644 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/ReceiptCredentialRequestJson.java +++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/ReceiptCredentialRequestJson.java @@ -3,13 +3,13 @@ package org.whispersystems.signalservice.internal.push; import com.fasterxml.jackson.annotation.JsonProperty; import org.signal.libsignal.zkgroup.receipts.ReceiptCredentialRequest; -import org.whispersystems.util.Base64; +import org.signal.core.util.Base64; class ReceiptCredentialRequestJson { @JsonProperty("receiptCredentialRequest") private final String receiptCredentialRequest; ReceiptCredentialRequestJson(ReceiptCredentialRequest receiptCredentialRequest) { - this.receiptCredentialRequest = Base64.encodeBytes(receiptCredentialRequest.serialize()); + this.receiptCredentialRequest = Base64.encodeWithPadding(receiptCredentialRequest.serialize()); } } diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/ReceiptCredentialResponseJson.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/ReceiptCredentialResponseJson.java index 97cc722c75..e3f839b647 100644 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/ReceiptCredentialResponseJson.java +++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/ReceiptCredentialResponseJson.java @@ -4,7 +4,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import org.signal.libsignal.zkgroup.InvalidInputException; import org.signal.libsignal.zkgroup.receipts.ReceiptCredentialResponse; -import org.whispersystems.util.Base64; +import org.signal.core.util.Base64; import java.io.IOException; diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/SenderCertificate.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/SenderCertificate.java index 255282c226..1bda288c91 100644 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/SenderCertificate.java +++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/SenderCertificate.java @@ -11,7 +11,7 @@ import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import org.whispersystems.util.Base64; +import org.signal.core.util.Base64; import java.io.IOException; @@ -31,7 +31,7 @@ public class SenderCertificate { public static class ByteArraySerializer extends JsonSerializer { @Override public void serialize(byte[] value, JsonGenerator gen, SerializerProvider serializers) throws IOException { - gen.writeString(Base64.encodeBytes(value)); + gen.writeString(Base64.encodeWithPadding(value)); } } diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/http/ResumableUploadSpec.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/http/ResumableUploadSpec.java index 69c2a20472..c1f28c4edf 100644 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/http/ResumableUploadSpec.java +++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/http/ResumableUploadSpec.java @@ -2,7 +2,7 @@ package org.whispersystems.signalservice.internal.push.http; import org.signal.protos.resumableuploads.ResumableUpload; import org.whispersystems.signalservice.api.push.exceptions.ResumeLocationInvalidException; -import org.whispersystems.util.Base64; +import org.signal.core.util.Base64; import java.io.IOException; import java.util.HashMap; @@ -85,7 +85,7 @@ public final class ResumableUploadSpec { .collect(Collectors.toList()) ); - return Base64.encodeBytes(builder.build().encode()); + return Base64.encodeWithPadding(builder.build().encode()); } public static ResumableUploadSpec deserialize(String serializedSpec) throws ResumeLocationInvalidException { diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/util/JsonUtil.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/util/JsonUtil.java index 05fd09ed60..052d5eb3fc 100644 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/util/JsonUtil.java +++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/util/JsonUtil.java @@ -27,7 +27,7 @@ import org.whispersystems.signalservice.api.push.ServiceId.ACI; import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.api.push.exceptions.MalformedResponseException; import org.whispersystems.signalservice.api.util.UuidUtil; -import org.whispersystems.util.Base64; +import org.signal.core.util.Base64; import java.io.IOException; import java.util.UUID; @@ -98,7 +98,7 @@ public class JsonUtil { public void serialize(IdentityKey value, JsonGenerator gen, SerializerProvider serializers) throws IOException { - gen.writeString(Base64.encodeBytesWithoutPadding(value.serialize())); + gen.writeString(Base64.encodeWithoutPadding(value.serialize())); } } @@ -106,7 +106,7 @@ public class JsonUtil { @Override public IdentityKey deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { try { - return new IdentityKey(Base64.decodeWithoutPadding(p.getValueAsString()), 0); + return new IdentityKey(Base64.decode(p.getValueAsString()), 0); } catch (InvalidKeyException e) { throw new IOException(e); } @@ -164,7 +164,7 @@ public class JsonUtil { public static class MasterKeySerializer extends JsonSerializer { @Override public void serialize(MasterKey value, JsonGenerator gen, SerializerProvider serializers) throws IOException { - gen.writeString(Base64.encodeBytes(value.serialize())); + gen.writeString(Base64.encodeWithPadding(value.serialize())); } } diff --git a/libsignal-service/src/main/java/org/whispersystems/util/Base64UrlSafe.java b/libsignal-service/src/main/java/org/whispersystems/util/Base64UrlSafe.java deleted file mode 100644 index 5c42b7569e..0000000000 --- a/libsignal-service/src/main/java/org/whispersystems/util/Base64UrlSafe.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.whispersystems.util; - -import java.io.IOException; - -public final class Base64UrlSafe { - - private Base64UrlSafe() { - } - - public static byte[] decode(String s) throws IOException { - return Base64.decode(s, Base64.URL_SAFE); - } - - public static byte[] decodePaddingAgnostic(String s) throws IOException { - switch (s.length() % 4) { - case 1: - case 3: s = s + "="; break; - case 2: s = s + "=="; break; - } - return decode(s); - } - - public static String encodeBytes(byte[] source) { - try { - return Base64.encodeBytes(source, Base64.URL_SAFE); - } catch (IOException e) { - throw new AssertionError(e); - } - } - - public static String encodeBytesWithoutPadding(byte[] source) { - return encodeBytes(source).replace("=", ""); - } -} diff --git a/libsignal-service/src/test/java/org/whispersystems/signalservice/api/crypto/ProfileCipherTest.java b/libsignal-service/src/test/java/org/whispersystems/signalservice/api/crypto/ProfileCipherTest.java index 638b4b87b7..6c823ac8a3 100644 --- a/libsignal-service/src/test/java/org/whispersystems/signalservice/api/crypto/ProfileCipherTest.java +++ b/libsignal-service/src/test/java/org/whispersystems/signalservice/api/crypto/ProfileCipherTest.java @@ -6,7 +6,7 @@ import org.junit.Test; import org.signal.libsignal.zkgroup.InvalidInputException; import org.signal.libsignal.zkgroup.profiles.ProfileKey; import org.whispersystems.signalservice.internal.util.Util; -import org.whispersystems.util.Base64; +import org.signal.core.util.Base64; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -120,7 +120,7 @@ public class ProfileCipherTest { ProfileCipher cipher = new ProfileCipher(key); byte[] name = cipher.encrypt("Peter\0Parker".getBytes(), 53); - String encoded = Base64.encodeBytes(name); + String encoded = Base64.encodeWithPadding(name); assertEquals(108, encoded.length()); } @@ -131,7 +131,7 @@ public class ProfileCipherTest { ProfileCipher cipher = new ProfileCipher(key); byte[] name = cipher.encrypt("Peter\0Parker".getBytes(), 257); - String encoded = Base64.encodeBytes(name); + String encoded = Base64.encodeWithPadding(name); assertEquals(380, encoded.length()); } diff --git a/libsignal-service/src/test/java/org/whispersystems/signalservice/api/crypto/SigningCertificateTest.java b/libsignal-service/src/test/java/org/whispersystems/signalservice/api/crypto/SigningCertificateTest.java index d5efbcebbd..de5cf5bdda 100644 --- a/libsignal-service/src/test/java/org/whispersystems/signalservice/api/crypto/SigningCertificateTest.java +++ b/libsignal-service/src/test/java/org/whispersystems/signalservice/api/crypto/SigningCertificateTest.java @@ -4,7 +4,7 @@ import junit.framework.TestCase; import org.conscrypt.Conscrypt; import org.whispersystems.signalservice.internal.contacts.crypto.SigningCertificate; -import org.whispersystems.util.Base64; +import org.signal.core.util.Base64; import java.io.IOException; import java.net.URLDecoder; @@ -54,7 +54,7 @@ public class SigningCertificateTest extends TestCase { malformedSignature[i] ^= (0x01 << j); try { - certificate.verifySignature(signatureBody, Base64.encodeBytes(malformedSignature)); + certificate.verifySignature(signatureBody, Base64.encodeWithPadding(malformedSignature)); throw new AssertionError("Signature verification should fail!"); } catch (SignatureException e) { // good diff --git a/libsignal-service/src/test/java/org/whispersystems/util/Base64UrlSafeTest.java b/libsignal-service/src/test/java/org/whispersystems/util/Base64UrlSafeTest.java deleted file mode 100644 index be61b61971..0000000000 --- a/libsignal-service/src/test/java/org/whispersystems/util/Base64UrlSafeTest.java +++ /dev/null @@ -1,67 +0,0 @@ -package org.whispersystems.util; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.whispersystems.signalservice.internal.util.Hex; - -import java.io.IOException; -import java.util.Arrays; -import java.util.Collection; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; - -@RunWith(Parameterized.class) -public final class Base64UrlSafeTest { - - private final byte[] data; - private final String encoded; - private final String encodedWithoutPadding; - - @Parameterized.Parameters - public static Collection data() { - return Arrays.asList(new Object[][]{ - { "", "", "" }, - { "01", "AQ==", "AQ" }, - { "0102", "AQI=", "AQI" }, - { "010203", "AQID", "AQID" }, - { "030405", "AwQF", "AwQF" }, - { "03040506", "AwQFBg==", "AwQFBg" }, - { "0304050708", "AwQFBwg=", "AwQFBwg" }, - { "af4d6cff", "r01s_w==", "r01s_w" }, - { "ffefde", "_-_e", "_-_e" }, - }); - } - - public Base64UrlSafeTest(String hexData, String encoded, String encodedWithoutPadding) throws IOException { - this.data = Hex.fromStringCondensed(hexData); - this.encoded = encoded; - this.encodedWithoutPadding = encodedWithoutPadding; - } - - @Test - public void encodes_as_expected() { - assertEquals(encoded, Base64UrlSafe.encodeBytes(data)); - } - - @Test - public void encodes_as_expected_without_padding() { - assertEquals(encodedWithoutPadding, Base64UrlSafe.encodeBytesWithoutPadding(data)); - } - - @Test - public void decodes_as_expected() throws IOException { - assertArrayEquals(data, Base64UrlSafe.decode(encoded)); - } - - @Test - public void decodes_padding_agnostic_as_expected() throws IOException { - assertArrayEquals(data, Base64UrlSafe.decodePaddingAgnostic(encoded)); - } - - @Test - public void decodes_as_expected_without_padding() throws IOException { - assertArrayEquals(data, Base64UrlSafe.decodePaddingAgnostic(encodedWithoutPadding)); - } -} \ No newline at end of file diff --git a/microbenchmark/build.gradle.kts b/microbenchmark/build.gradle.kts index e3793ef731..763a353619 100644 --- a/microbenchmark/build.gradle.kts +++ b/microbenchmark/build.gradle.kts @@ -51,6 +51,8 @@ android { dependencies { lintChecks(project(":lintchecks")) + implementation(project(":core-util")) + // Base dependencies androidTestImplementation(testLibs.junit.junit) androidTestImplementation(benchmarkLibs.androidx.test.ext.junit) diff --git a/microbenchmark/src/androidTest/java/org/signal/util/SignalClient.kt b/microbenchmark/src/androidTest/java/org/signal/util/SignalClient.kt index a2b7d46665..e299844222 100644 --- a/microbenchmark/src/androidTest/java/org/signal/util/SignalClient.kt +++ b/microbenchmark/src/androidTest/java/org/signal/util/SignalClient.kt @@ -1,6 +1,7 @@ package org.signal.util import okio.ByteString.Companion.toByteString +import org.signal.core.util.Base64 import org.signal.libsignal.internal.Native import org.signal.libsignal.internal.NativeHandleGuard import org.signal.libsignal.metadata.certificate.CertificateValidator @@ -27,7 +28,6 @@ import org.whispersystems.signalservice.internal.push.DataMessage import org.whispersystems.signalservice.internal.push.Envelope import org.whispersystems.signalservice.internal.push.OutgoingPushMessage import org.whispersystems.signalservice.internal.util.Util -import org.whispersystems.util.Base64 import java.util.Optional import java.util.UUID import java.util.concurrent.locks.ReentrantLock