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.core.util.requireString
import org.signal.libsignal.zkgroup.InvalidInputException import org.signal.libsignal.zkgroup.InvalidInputException
import org.signal.libsignal.zkgroup.profiles.ExpiringProfileKeyCredential 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.Badges
import org.thoughtcrime.securesms.badges.models.Badge import org.thoughtcrime.securesms.badges.models.Badge
import org.thoughtcrime.securesms.conversation.colors.AvatarColor import org.thoughtcrime.securesms.conversation.colors.AvatarColor
import org.thoughtcrime.securesms.conversation.colors.ChatColors 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.IdentityTable.VerifiedStatus
import org.thoughtcrime.securesms.database.RecipientTable.RegisteredState import org.thoughtcrime.securesms.database.RecipientTable.RegisteredState
import org.thoughtcrime.securesms.database.model.DistributionListId 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.thoughtcrime.securesms.wallpaper.ChatWallpaperFactory
import org.whispersystems.signalservice.api.push.ServiceId import org.whispersystems.signalservice.api.push.ServiceId
import java.io.IOException import java.io.IOException
import java.util.Arrays
object RecipientTableCursorUtil { object RecipientTableCursorUtil {
@@ -60,21 +61,19 @@ object RecipientTableCursorUtil {
fun getRecord(context: Context, cursor: Cursor, idColumnName: String): RecipientRecord { fun getRecord(context: Context, cursor: Cursor, idColumnName: String): RecipientRecord {
val profileKeyString = cursor.requireString(RecipientTable.PROFILE_KEY) val profileKeyString = cursor.requireString(RecipientTable.PROFILE_KEY)
val expiringProfileKeyCredentialString = cursor.requireString(RecipientTable.EXPIRING_PROFILE_KEY_CREDENTIAL) val expiringProfileKeyCredentialString = cursor.requireString(RecipientTable.EXPIRING_PROFILE_KEY_CREDENTIAL)
var profileKey: ByteArray? = null var profileKey: ProfileKey? = null
var expiringProfileKeyCredential: ExpiringProfileKeyCredential? = null var expiringProfileKeyCredential: ExpiringProfileKeyCredential? = null
if (profileKeyString != null) { if (profileKeyString != null) {
try { profileKey = ProfileKeyUtil.profileKeyOrNull(profileKeyString)
profileKey = Base64.decode(profileKeyString)
} catch (e: IOException) {
Log.w(TAG, e)
}
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 { try {
val columnDataBytes = Base64.decode(expiringProfileKeyCredentialString) val columnDataBytes = Base64.decode(expiringProfileKeyCredentialString)
val columnData = ExpiringProfileKeyCredentialColumnData.ADAPTER.decode(columnDataBytes) 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()) expiringProfileKeyCredential = ExpiringProfileKeyCredential(columnData.expiringProfileKeyCredential.toByteArray())
} else { } else {
Log.i(TAG, "Out of date profile key credential data ignored on read") 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), expireMessages = cursor.requireInt(RecipientTable.MESSAGE_EXPIRATION_TIME),
expireTimerVersion = cursor.requireInt(RecipientTable.MESSAGE_EXPIRATION_TIME_VERSION), expireTimerVersion = cursor.requireInt(RecipientTable.MESSAGE_EXPIRATION_TIME_VERSION),
registered = RegisteredState.fromId(cursor.requireInt(RecipientTable.REGISTERED)), registered = RegisteredState.fromId(cursor.requireInt(RecipientTable.REGISTERED)),
profileKey = profileKey, profileKey = profileKey?.serialize(),
expiringProfileKeyCredential = expiringProfileKeyCredential, expiringProfileKeyCredential = expiringProfileKeyCredential,
systemProfileName = ProfileName.fromParts(cursor.requireString(RecipientTable.SYSTEM_GIVEN_NAME), cursor.requireString(RecipientTable.SYSTEM_FAMILY_NAME)), systemProfileName = ProfileName.fromParts(cursor.requireString(RecipientTable.SYSTEM_GIVEN_NAME), cursor.requireString(RecipientTable.SYSTEM_FAMILY_NAME)),
systemDisplayName = cursor.requireString(RecipientTable.SYSTEM_JOINED_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.logging.Log
import org.signal.core.util.nullIfBlank import org.signal.core.util.nullIfBlank
import org.signal.core.util.nullIfEmpty import org.signal.core.util.nullIfEmpty
import org.thoughtcrime.securesms.crypto.ProfileKeyUtil
import org.thoughtcrime.securesms.database.RecipientTable import org.thoughtcrime.securesms.database.RecipientTable
import org.thoughtcrime.securesms.database.SignalDatabase import org.thoughtcrime.securesms.database.SignalDatabase
import org.thoughtcrime.securesms.database.model.RecipientRecord import org.thoughtcrime.securesms.database.model.RecipientRecord
@@ -215,7 +216,7 @@ class ContactRecordProcessor(
pni = mergedPni?.toStringWithoutPrefix() ?: "" pni = mergedPni?.toStringWithoutPrefix() ?: ""
givenName = mergedProfileGivenName givenName = mergedProfileGivenName
familyName = mergedProfileFamilyName 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 username = remote.proto.username.nullIfBlank() ?: local.proto.username
identityState = mergedIdentityState identityState = mergedIdentityState
identityKey = mergedIdentityKey?.toByteString() ?: ByteString.EMPTY identityKey = mergedIdentityKey?.toByteString() ?: ByteString.EMPTY