Prevent invalid profile keys from being processed for storage service.

This commit is contained in:
Cody Henthorne
2025-10-16 10:18:03 -04:00
parent 55916f31aa
commit 08eca9ac27
2 changed files with 11 additions and 11 deletions

View File

@@ -22,10 +22,12 @@ import org.signal.core.util.requireLong
import org.signal.core.util.requireString
import org.signal.libsignal.zkgroup.InvalidInputException
import org.signal.libsignal.zkgroup.profiles.ExpiringProfileKeyCredential
import org.signal.libsignal.zkgroup.profiles.ProfileKey
import org.thoughtcrime.securesms.badges.Badges
import org.thoughtcrime.securesms.badges.models.Badge
import org.thoughtcrime.securesms.conversation.colors.AvatarColor
import org.thoughtcrime.securesms.conversation.colors.ChatColors
import org.thoughtcrime.securesms.crypto.ProfileKeyUtil
import org.thoughtcrime.securesms.database.IdentityTable.VerifiedStatus
import org.thoughtcrime.securesms.database.RecipientTable.RegisteredState
import org.thoughtcrime.securesms.database.model.DistributionListId
@@ -47,7 +49,6 @@ import org.thoughtcrime.securesms.wallpaper.ChatWallpaper
import org.thoughtcrime.securesms.wallpaper.ChatWallpaperFactory
import org.whispersystems.signalservice.api.push.ServiceId
import java.io.IOException
import java.util.Arrays
object RecipientTableCursorUtil {
@@ -60,21 +61,19 @@ object RecipientTableCursorUtil {
fun getRecord(context: Context, cursor: Cursor, idColumnName: String): RecipientRecord {
val profileKeyString = cursor.requireString(RecipientTable.PROFILE_KEY)
val expiringProfileKeyCredentialString = cursor.requireString(RecipientTable.EXPIRING_PROFILE_KEY_CREDENTIAL)
var profileKey: ByteArray? = null
var profileKey: ProfileKey? = null
var expiringProfileKeyCredential: ExpiringProfileKeyCredential? = null
if (profileKeyString != null) {
try {
profileKey = Base64.decode(profileKeyString)
} catch (e: IOException) {
Log.w(TAG, e)
}
profileKey = ProfileKeyUtil.profileKeyOrNull(profileKeyString)
if (expiringProfileKeyCredentialString != null) {
if (profileKey == null) {
Log.w(TAG, "Profile key present in db but is invalid, ignoring on read")
} else if (expiringProfileKeyCredentialString != null) {
try {
val columnDataBytes = Base64.decode(expiringProfileKeyCredentialString)
val columnData = ExpiringProfileKeyCredentialColumnData.ADAPTER.decode(columnDataBytes)
if (Arrays.equals(columnData.profileKey.toByteArray(), profileKey)) {
if (columnData.profileKey.toByteArray().contentEquals(profileKey.serialize())) {
expiringProfileKeyCredential = ExpiringProfileKeyCredential(columnData.expiringProfileKeyCredential.toByteArray())
} else {
Log.i(TAG, "Out of date profile key credential data ignored on read")
@@ -135,7 +134,7 @@ object RecipientTableCursorUtil {
expireMessages = cursor.requireInt(RecipientTable.MESSAGE_EXPIRATION_TIME),
expireTimerVersion = cursor.requireInt(RecipientTable.MESSAGE_EXPIRATION_TIME_VERSION),
registered = RegisteredState.fromId(cursor.requireInt(RecipientTable.REGISTERED)),
profileKey = profileKey,
profileKey = profileKey?.serialize(),
expiringProfileKeyCredential = expiringProfileKeyCredential,
systemProfileName = ProfileName.fromParts(cursor.requireString(RecipientTable.SYSTEM_GIVEN_NAME), cursor.requireString(RecipientTable.SYSTEM_FAMILY_NAME)),
systemDisplayName = cursor.requireString(RecipientTable.SYSTEM_JOINED_NAME),

View File

@@ -7,6 +7,7 @@ import org.signal.core.util.isNotEmpty
import org.signal.core.util.logging.Log
import org.signal.core.util.nullIfBlank
import org.signal.core.util.nullIfEmpty
import org.thoughtcrime.securesms.crypto.ProfileKeyUtil
import org.thoughtcrime.securesms.database.RecipientTable
import org.thoughtcrime.securesms.database.SignalDatabase
import org.thoughtcrime.securesms.database.model.RecipientRecord
@@ -215,7 +216,7 @@ class ContactRecordProcessor(
pni = mergedPni?.toStringWithoutPrefix() ?: ""
givenName = mergedProfileGivenName
familyName = mergedProfileFamilyName
profileKey = remote.proto.profileKey.nullIfEmpty() ?: local.proto.profileKey
profileKey = remote.proto.profileKey.nullIfEmpty()?.takeIf { ProfileKeyUtil.profileKeyOrNull(it.toByteArray()) != null } ?: local.proto.profileKey
username = remote.proto.username.nullIfBlank() ?: local.proto.username
identityState = mergedIdentityState
identityKey = mergedIdentityKey?.toByteString() ?: ByteString.EMPTY