Swiftify OWSOutgoingSenderKeyDistributionMessage

This commit is contained in:
Max Radermacher 2026-01-15 15:14:20 -06:00 committed by GitHub
parent af378990bb
commit c83a181b00
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 139 additions and 225 deletions

View File

@ -806,6 +806,7 @@
50D9CD8D2C52D78000273D6C /* StoryRecipientManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50D9CD8C2C52D78000273D6C /* StoryRecipientManager.swift */; };
50DCCBFA2F1817280024D124 /* DisappearingMessagesConfigurationMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50DCCBF92F1817280024D124 /* DisappearingMessagesConfigurationMessage.swift */; };
50DCCBFC2F181A790024D124 /* ProfileKeyMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50DCCBFB2F181A790024D124 /* ProfileKeyMessage.swift */; };
50DCCBFE2F1820600024D124 /* OutgoingSenderKeyDistributionMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50DCCBFD2F1820600024D124 /* OutgoingSenderKeyDistributionMessage.swift */; };
50E42FEA2C1BA3B900554BD6 /* CallHTTPClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50E42FE92C1BA3B900554BD6 /* CallHTTPClient.swift */; };
50E51A3B2AE989C4004F9069 /* AccountAttributesTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50E51A3A2AE989C4004F9069 /* AccountAttributesTest.swift */; };
50E5E4B129932D9B00E15A1C /* DeviceMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50E5E4B029932D9B00E15A1C /* DeviceMessage.swift */; };
@ -3635,7 +3636,6 @@
F9C5CC3F289453B300548EEE /* MessageReceiver.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C94F289453B100548EEE /* MessageReceiver.swift */; };
F9C5CC40289453B300548EEE /* OWSAddToProfileWhitelistOfferMessage+SDS.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C950289453B100548EEE /* OWSAddToProfileWhitelistOfferMessage+SDS.swift */; };
F9C5CC42289453B300548EEE /* OWSUnknownProtocolVersionMessage.h in Headers */ = {isa = PBXBuildFile; fileRef = F9C5C952289453B100548EEE /* OWSUnknownProtocolVersionMessage.h */; settings = {ATTRIBUTES = (Public, ); }; };
F9C5CC43289453B300548EEE /* OWSOutgoingSenderKeyDistributionMessage.h in Headers */ = {isa = PBXBuildFile; fileRef = F9C5C953289453B100548EEE /* OWSOutgoingSenderKeyDistributionMessage.h */; settings = {ATTRIBUTES = (Public, ); }; };
F9C5CC44289453B300548EEE /* MessageSender+SenderKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C954289453B100548EEE /* MessageSender+SenderKey.swift */; };
F9C5CC46289453B300548EEE /* OWSGroupCallMessage+SDS.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C956289453B100548EEE /* OWSGroupCallMessage+SDS.swift */; };
F9C5CC47289453B300548EEE /* OWSRecoverableDecryptionPlaceholder.h in Headers */ = {isa = PBXBuildFile; fileRef = F9C5C957289453B100548EEE /* OWSRecoverableDecryptionPlaceholder.h */; settings = {ATTRIBUTES = (Public, ); }; };
@ -3674,7 +3674,6 @@
F9C5CC84289453B300548EEE /* OWSAddToProfileWhitelistOfferMessage.h in Headers */ = {isa = PBXBuildFile; fileRef = F9C5C997289453B100548EEE /* OWSAddToProfileWhitelistOfferMessage.h */; settings = {ATTRIBUTES = (Public, ); }; };
F9C5CC85289453B300548EEE /* OWSRecoverableDecryptionPlaceholder.m in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C998289453B100548EEE /* OWSRecoverableDecryptionPlaceholder.m */; };
F9C5CC88289453B300548EEE /* MessageSender+Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C99B289453B100548EEE /* MessageSender+Errors.swift */; };
F9C5CC89289453B300548EEE /* OWSOutgoingSenderKeyDistributionMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C99C289453B100548EEE /* OWSOutgoingSenderKeyDistributionMessage.m */; };
F9C5CC8A289453B300548EEE /* EarlyMessageManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C99D289453B100548EEE /* EarlyMessageManager.swift */; };
F9C5CC8B289453B300548EEE /* OWSUnknownProtocolVersionMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C99E289453B100548EEE /* OWSUnknownProtocolVersionMessage.m */; };
F9C5CC8E289453B300548EEE /* SSKProtos.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C9A3289453B100548EEE /* SSKProtos.swift */; };
@ -4977,6 +4976,7 @@
50D9CD8C2C52D78000273D6C /* StoryRecipientManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoryRecipientManager.swift; sourceTree = "<group>"; };
50DCCBF92F1817280024D124 /* DisappearingMessagesConfigurationMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisappearingMessagesConfigurationMessage.swift; sourceTree = "<group>"; };
50DCCBFB2F181A790024D124 /* ProfileKeyMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileKeyMessage.swift; sourceTree = "<group>"; };
50DCCBFD2F1820600024D124 /* OutgoingSenderKeyDistributionMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OutgoingSenderKeyDistributionMessage.swift; sourceTree = "<group>"; };
50E42FE52C1B9EB900554BD6 /* CallLinkState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallLinkState.swift; sourceTree = "<group>"; };
50E42FE92C1BA3B900554BD6 /* CallHTTPClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallHTTPClient.swift; sourceTree = "<group>"; };
50E51A3A2AE989C4004F9069 /* AccountAttributesTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountAttributesTest.swift; sourceTree = "<group>"; };
@ -7857,7 +7857,6 @@
F9C5C94F289453B100548EEE /* MessageReceiver.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageReceiver.swift; sourceTree = "<group>"; };
F9C5C950289453B100548EEE /* OWSAddToProfileWhitelistOfferMessage+SDS.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "OWSAddToProfileWhitelistOfferMessage+SDS.swift"; sourceTree = "<group>"; };
F9C5C952289453B100548EEE /* OWSUnknownProtocolVersionMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSUnknownProtocolVersionMessage.h; sourceTree = "<group>"; };
F9C5C953289453B100548EEE /* OWSOutgoingSenderKeyDistributionMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSOutgoingSenderKeyDistributionMessage.h; sourceTree = "<group>"; };
F9C5C954289453B100548EEE /* MessageSender+SenderKey.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "MessageSender+SenderKey.swift"; sourceTree = "<group>"; };
F9C5C956289453B100548EEE /* OWSGroupCallMessage+SDS.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "OWSGroupCallMessage+SDS.swift"; sourceTree = "<group>"; };
F9C5C957289453B100548EEE /* OWSRecoverableDecryptionPlaceholder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSRecoverableDecryptionPlaceholder.h; sourceTree = "<group>"; };
@ -7896,7 +7895,6 @@
F9C5C997289453B100548EEE /* OWSAddToProfileWhitelistOfferMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSAddToProfileWhitelistOfferMessage.h; sourceTree = "<group>"; };
F9C5C998289453B100548EEE /* OWSRecoverableDecryptionPlaceholder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSRecoverableDecryptionPlaceholder.m; sourceTree = "<group>"; };
F9C5C99B289453B100548EEE /* MessageSender+Errors.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "MessageSender+Errors.swift"; sourceTree = "<group>"; };
F9C5C99C289453B100548EEE /* OWSOutgoingSenderKeyDistributionMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSOutgoingSenderKeyDistributionMessage.m; sourceTree = "<group>"; };
F9C5C99D289453B100548EEE /* EarlyMessageManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EarlyMessageManager.swift; sourceTree = "<group>"; };
F9C5C99E289453B100548EEE /* OWSUnknownProtocolVersionMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSUnknownProtocolVersionMessage.m; sourceTree = "<group>"; };
F9C5C9A3289453B100548EEE /* SSKProtos.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SSKProtos.swift; sourceTree = "<group>"; };
@ -14416,6 +14414,7 @@
50F9460F2AD768AF002EF293 /* MockIdentityManager.swift */,
F96A534228A1AE7B003262D4 /* OutgoingGroupUpdateMessage.swift */,
F9C5C92D289453B100548EEE /* OutgoingResendRequest.swift */,
50DCCBFD2F1820600024D124 /* OutgoingSenderKeyDistributionMessage.swift */,
F9C5C959289453B100548EEE /* OWSAddToContactsOfferMessage+SDS.swift */,
F9C5C92C289453B100548EEE /* OWSAddToContactsOfferMessage.h */,
F9C5C979289453B100548EEE /* OWSAddToContactsOfferMessage.m */,
@ -14429,8 +14428,6 @@
F9C5C946289453B100548EEE /* OWSOutgoingNullMessage.m */,
505B228229F73ABE005578F3 /* OWSOutgoingResendResponse.swift */,
508C72232C2DFCB2000811F3 /* OWSOutgoingResendResponseTest.swift */,
F9C5C953289453B100548EEE /* OWSOutgoingSenderKeyDistributionMessage.h */,
F9C5C99C289453B100548EEE /* OWSOutgoingSenderKeyDistributionMessage.m */,
7273280A2CA797320080E2C7 /* OWSReadTracking.h */,
F9C5C993289453B100548EEE /* OWSReceiptManager.swift */,
F9C5C980289453B100548EEE /* OWSRecoverableDecryptionPlaceholder+SDS.swift */,
@ -15369,7 +15366,6 @@
F9C5CC6A289453B300548EEE /* OWSOutgoingNullMessage.h in Headers */,
F9C5CC05289453B300548EEE /* OWSOutgoingPaymentMessage.h in Headers */,
F9C5CC39289453B300548EEE /* OWSOutgoingReactionMessage.h in Headers */,
F9C5CC43289453B300548EEE /* OWSOutgoingSenderKeyDistributionMessage.h in Headers */,
F9C5CBC7289453B300548EEE /* OWSOutgoingSyncMessage.h in Headers */,
6642A8702A8D7B4B00E591C2 /* OWSPaymentActivationRequestFinishedMessage.h in Headers */,
6642A8742A8D80CB00E591C2 /* OWSPaymentActivationRequestMessage.h in Headers */,
@ -19132,6 +19128,7 @@
04472D5E2E8AD74200D69EE0 /* OutgoingPollVote.swift in Sources */,
50A5AA9D2A7475A900CF2ECC /* OutgoingReactionMessage.swift in Sources */,
F9C5CC1F289453B300548EEE /* OutgoingResendRequest.swift in Sources */,
50DCCBFE2F1820600024D124 /* OutgoingSenderKeyDistributionMessage.swift in Sources */,
C16B8B752B8940D40030BA24 /* OutgoingSentMessageTranscript.swift in Sources */,
F9C5CC5A289453B300548EEE /* OutgoingStoryMessage.swift in Sources */,
884E4C4828AF2F2A007A338C /* OutgoingStorySentMessageTranscript.swift in Sources */,
@ -19210,7 +19207,6 @@
6674807E2E344EE9004DA6E9 /* OWSOutgoingPaymentMessage.swift in Sources */,
F9C5CC3B289453B300548EEE /* OWSOutgoingReactionMessage.m in Sources */,
505B228329F73ABE005578F3 /* OWSOutgoingResendResponse.swift in Sources */,
F9C5CC89289453B300548EEE /* OWSOutgoingSenderKeyDistributionMessage.m in Sources */,
F9C5CBB7289453B300548EEE /* OWSOutgoingSyncMessage.m in Sources */,
6642A87A2A8D85F500E591C2 /* OWSPaymentActivationRequestFinishedMessage+SDS.swift in Sources */,
6642A8722A8D7C5700E591C2 /* OWSPaymentActivationRequestFinishedMessage.m in Sources */,

View File

@ -1725,7 +1725,7 @@ public final class MessageReceiver {
transaction tx: DBWriteTransaction,
) {
do {
let skdm = try SenderKeyDistributionMessage(bytes: skdmData)
let skdm = try LibSignalClient.SenderKeyDistributionMessage(bytes: skdmData)
let sourceAci = decryptedEnvelope.sourceAci
let sourceDeviceId = decryptedEnvelope.sourceDeviceId
let protocolAddress = ProtocolAddress(sourceAci, deviceId: sourceDeviceId)

View File

@ -351,18 +351,19 @@ extension MessageSender {
tx writeTx: DBWriteTransaction,
) throws -> PrepareDistributionResult {
let senderKeyStore = SSKEnvironment.shared.senderKeyStoreRef
let tsAccountManager = DependenciesBridge.shared.tsAccountManager
guard
let skdmData = senderKeyStore.skdmBytesForThread(
thread,
localAci: localIdentifiers.aci,
localDeviceId: DependenciesBridge.shared.tsAccountManager.storedDeviceId(tx: writeTx),
tx: writeTx,
)
else {
throw OWSAssertionError("Couldn't build SKDM")
guard let localDeviceId = tsAccountManager.storedDeviceId(tx: writeTx).ifValid else {
throw NotRegisteredError()
}
let senderKeyDistributionMessage = try senderKeyStore.senderKeyDistributionMessage(
forThread: thread,
localAci: localIdentifiers.aci,
localDeviceId: localDeviceId,
tx: writeTx,
)
var result = PrepareDistributionResult()
for serviceId in recipients {
Logger.info("Preparing SKDM for \(serviceId) in thread \(thread.logString)")
@ -371,23 +372,24 @@ extension MessageSender {
withContactAddress: SignalServiceAddress(serviceId),
transaction: writeTx,
)
let skdmMessage = OWSOutgoingSenderKeyDistributionMessage(
thread: contactThread,
senderKeyDistributionMessageBytes: skdmData,
transaction: writeTx,
let outgoingSKDM = OutgoingSenderKeyDistributionMessage(
recipientThread: contactThread,
senderKeyDistributionMessage: senderKeyDistributionMessage,
onBehalfOfMessage: originalMessage,
inThread: thread,
tx: writeTx,
)
skdmMessage.configureAsSentOnBehalfOf(originalMessage, in: thread)
let serializedMessage: SerializedMessage
do {
serializedMessage = try self.buildAndRecordMessage(skdmMessage, in: contactThread, tx: writeTx)
serializedMessage = try self.buildAndRecordMessage(outgoingSKDM, in: contactThread, tx: writeTx)
} catch {
result.failedRecipients.append((serviceId, error))
continue
}
let messageSend = OWSMessageSend(
message: skdmMessage,
message: outgoingSKDM,
plaintextContent: serializedMessage.plaintextData,
plaintextPayloadId: serializedMessage.payloadId,
thread: contactThread,
@ -396,7 +398,7 @@ extension MessageSender {
)
let sealedSenderParameters = SealedSenderParameters(
message: skdmMessage,
message: outgoingSKDM,
senderCertificate: senderCertificate,
accessKey: (serviceId as? Aci).flatMap { udAccessMap[$0] },
endorsement: endorsements?.tokenBuilder(forServiceId: serviceId),

View File

@ -10,7 +10,7 @@ import LibSignalClient
private extension TSOutgoingMessage {
var isTransientSKDM: Bool {
(self as? OWSOutgoingSenderKeyDistributionMessage)?.isSentOnBehalfOfOnlineMessage ?? false
(self as? OutgoingSenderKeyDistributionMessage)?.isSentOnBehalfOfOnlineMessage ?? false
}
var isResendRequest: Bool {

View File

@ -165,18 +165,29 @@ final class OWSOutgoingResendResponse: TSOutgoingMessage {
return nullMessageProtoBuilder()
}()
let tsAccountManager = DependenciesBridge.shared.tsAccountManager
if
let originalThreadId,
let originalThread = TSThread.anyFetch(uniqueId: originalThreadId, transaction: tx),
originalThread.usesSenderKey,
let recipientAddress = self.recipientAddresses().first,
originalThread.recipientAddresses(with: tx).contains(recipientAddress)
originalThread.recipientAddresses(with: tx).contains(recipientAddress),
let registeredState = try? tsAccountManager.registeredState(tx: tx),
let deviceId = tsAccountManager.storedDeviceId(tx: tx).ifValid
{
let skdmData = SSKEnvironment.shared.senderKeyStoreRef.skdmBytesForThread(originalThread, tx: tx)
if let skdmData {
contentBuilder.setSenderKeyDistributionMessage(skdmData)
let senderKeyStore = SSKEnvironment.shared.senderKeyStoreRef
do {
let senderKeyDistributionMessage = try senderKeyStore.senderKeyDistributionMessage(
forThread: originalThread,
localAci: registeredState.localIdentifiers.aci,
localDeviceId: deviceId,
tx: tx,
)
contentBuilder.setSenderKeyDistributionMessage(senderKeyDistributionMessage.serialize())
self.didAppendSKDM = true
} catch {
owsFailDebug("couldn't append SKDM: \(error)")
}
self.didAppendSKDM = skdmData != nil
}
do {

View File

@ -1,40 +0,0 @@
//
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//
#import <SignalServiceKit/TSOutgoingMessage.h>
@class TSContactThread;
NS_ASSUME_NONNULL_BEGIN
@interface OWSOutgoingSenderKeyDistributionMessage : TSOutgoingMessage
- (instancetype)initOutgoingMessageWithBuilder:(TSOutgoingMessageBuilder *)outgoingMessageBuilder
recipientAddressStates:
(NSDictionary<SignalServiceAddress *, TSOutgoingMessageRecipientState *> *)
recipientAddressStates NS_UNAVAILABLE;
- (instancetype)initOutgoingMessageWithBuilder:(TSOutgoingMessageBuilder *)outgoingMessageBuilder
additionalRecipients:(NSArray<ServiceIdObjC *> *)additionalRecipients
explicitRecipients:(NSArray<AciObjC *> *)explicitRecipients
skippedRecipients:(NSArray<ServiceIdObjC *> *)skippedRecipients
transaction:(DBReadTransaction *)transaction NS_UNAVAILABLE;
- (instancetype)initWithThread:(TSContactThread *)destinationThread
senderKeyDistributionMessageBytes:(NSData *)skdmBytes
transaction:(DBReadTransaction *)transaction;
/// Returns YES if this message is being sent as a precondition to sending an online-only message.
/// Typing indicators are only delivered to online devices. Since they're ephemeral we just don't bother sending a
/// typing indicator to a recipient if we need the user to verify a safety number change. Outgoing SKDMs being sent on
/// behalf of an outgoing typing indicator should inherit this behavior.
@property (assign, atomic, readonly) BOOL isSentOnBehalfOfOnlineMessage;
/// Returns YES if this message is being sent as a precondition to sending a story message.
@property (assign, atomic, readonly) BOOL isSentOnBehalfOfStoryMessage;
- (void)configureAsSentOnBehalfOf:(TSOutgoingMessage *)message
inThread:(TSThread *)thread NS_SWIFT_NAME(configureAsSentOnBehalfOf(_:in:));
@end
NS_ASSUME_NONNULL_END

View File

@ -1,118 +0,0 @@
//
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//
#import "OWSOutgoingSenderKeyDistributionMessage.h"
#import <SignalServiceKit/SignalServiceKit-Swift.h>
@interface OWSOutgoingSenderKeyDistributionMessage ()
@property (strong, nonatomic, readonly) NSData *serializedSKDM;
@property (assign, atomic) BOOL isSentOnBehalfOfOnlineMessage;
@property (assign, atomic) BOOL isSentOnBehalfOfStoryMessage;
@end
@implementation OWSOutgoingSenderKeyDistributionMessage
- (instancetype)initWithThread:(TSContactThread *)destinationThread
senderKeyDistributionMessageBytes:(NSData *)skdmBytes
transaction:(DBReadTransaction *)transaction
{
OWSAssertDebug(destinationThread);
OWSAssertDebug(skdmBytes);
if (!destinationThread || !skdmBytes) {
return nil;
}
TSOutgoingMessageBuilder *messageBuilder =
[TSOutgoingMessageBuilder outgoingMessageBuilderWithThread:destinationThread];
self = [super initOutgoingMessageWithBuilder:messageBuilder
additionalRecipients:@[]
explicitRecipients:@[]
skippedRecipients:@[]
transaction:transaction];
if (self) {
_serializedSKDM = [skdmBytes copy];
}
return self;
}
+ (BOOL)supportsSecureCoding
{
return YES;
}
- (void)encodeWithCoder:(NSCoder *)coder
{
OWSFail(@"Doesn't support serialization.");
}
- (nullable instancetype)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
// Doesn't support serialization.
return nil;
}
- (NSUInteger)hash
{
NSUInteger result = [super hash];
result ^= self.isSentOnBehalfOfOnlineMessage;
result ^= self.isSentOnBehalfOfStoryMessage;
result ^= self.serializedSKDM.hash;
return result;
}
- (BOOL)isEqual:(id)other
{
if (![super isEqual:other]) {
return NO;
}
OWSOutgoingSenderKeyDistributionMessage *typedOther = (OWSOutgoingSenderKeyDistributionMessage *)other;
if (self.isSentOnBehalfOfOnlineMessage != typedOther.isSentOnBehalfOfOnlineMessage) {
return NO;
}
if (self.isSentOnBehalfOfStoryMessage != typedOther.isSentOnBehalfOfStoryMessage) {
return NO;
}
if (![NSObject isObject:self.serializedSKDM equalToObject:typedOther.serializedSKDM]) {
return NO;
}
return YES;
}
- (BOOL)shouldBeSaved
{
return NO;
}
- (BOOL)isUrgent
{
return NO;
}
- (BOOL)isStorySend
{
return self.isSentOnBehalfOfStoryMessage;
}
- (SealedSenderContentHint)contentHint
{
return SealedSenderContentHintImplicit;
}
- (nullable SSKProtoContentBuilder *)contentBuilderWithThread:(TSThread *)thread
transaction:(DBReadTransaction *)transaction
{
SSKProtoContentBuilder *builder = [SSKProtoContent builder];
[builder setSenderKeyDistributionMessage:self.serializedSKDM];
return builder;
}
- (void)configureAsSentOnBehalfOf:(TSOutgoingMessage *)message inThread:(TSThread *)thread
{
self.isSentOnBehalfOfOnlineMessage = message.isOnline;
self.isSentOnBehalfOfStoryMessage = message.isStorySend && !thread.isGroupThread;
}
@end

View File

@ -0,0 +1,86 @@
//
// Copyright 2026 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//
import Foundation
import LibSignalClient
final class OutgoingSenderKeyDistributionMessage: TSOutgoingMessage {
/// True if this message is being sent as a precondition to sending an
/// online-only message. Typing indicators are only delivered to online
/// devices. Since they're ephemeral we just don't bother sending a typing
/// indicator to a recipient if we need the user to verify a safety number
/// change. Outgoing SKDMs being sent on behalf of an outgoing typing
/// indicator should inherit this behavior.
let isSentOnBehalfOfOnlineMessage: Bool
/// True if this message is being sent as a precondition to sending a story
/// message.
let isSentOnBehalfOfStoryMessage: Bool
let senderKeyDistributionMessage: SenderKeyDistributionMessage
init(
recipientThread: TSContactThread,
senderKeyDistributionMessage: SenderKeyDistributionMessage,
onBehalfOfMessage originalMessage: TSOutgoingMessage,
inThread originalThread: TSThread,
tx: DBReadTransaction,
) {
self.senderKeyDistributionMessage = senderKeyDistributionMessage
self.isSentOnBehalfOfOnlineMessage = originalMessage.isOnline
self.isSentOnBehalfOfStoryMessage = originalMessage.isStorySend && !originalThread.isGroupThread
super.init(
outgoingMessageWith: TSOutgoingMessageBuilder.outgoingMessageBuilder(thread: recipientThread),
additionalRecipients: [],
explicitRecipients: [],
skippedRecipients: [],
transaction: tx,
)
}
override class var supportsSecureCoding: Bool { true }
override func encode(with coder: NSCoder) {
owsFail("Doesn't support serialization.")
}
required init?(coder: NSCoder) {
// Doesn't support serialization.
return nil
}
override var hash: Int {
var hasher = Hasher()
hasher.combine(super.hash)
hasher.combine(self.isSentOnBehalfOfOnlineMessage)
hasher.combine(self.isSentOnBehalfOfStoryMessage)
hasher.combine(self.senderKeyDistributionMessage.serialize())
return hasher.finalize()
}
override func isEqual(_ object: Any?) -> Bool {
guard let object = object as? Self else { return false }
guard super.isEqual(object) else { return false }
guard self.isSentOnBehalfOfOnlineMessage == object.isSentOnBehalfOfOnlineMessage else { return false }
guard self.isSentOnBehalfOfStoryMessage == object.isSentOnBehalfOfStoryMessage else { return false }
guard self.senderKeyDistributionMessage.serialize() == object.senderKeyDistributionMessage.serialize() else { return false }
return true
}
override var shouldBeSaved: Bool { false }
override var isUrgent: Bool { false }
override var isStorySend: Bool { self.isSentOnBehalfOfStoryMessage }
override var contentHint: SealedSenderContentHint { .implicit }
override func contentBuilder(thread: TSThread, transaction: DBReadTransaction) -> SSKProtoContentBuilder? {
let builder = SSKProtoContent.builder()
builder.setSenderKeyDistributionMessage(self.senderKeyDistributionMessage.serialize())
return builder
}
}

View File

@ -32,7 +32,6 @@ FOUNDATION_EXPORT const unsigned char SignalServiceKitVersionString[];
#import <SignalServiceKit/OWSOutgoingNullMessage.h>
#import <SignalServiceKit/OWSOutgoingPaymentMessage.h>
#import <SignalServiceKit/OWSOutgoingReactionMessage.h>
#import <SignalServiceKit/OWSOutgoingSenderKeyDistributionMessage.h>
#import <SignalServiceKit/OWSOutgoingSyncMessage.h>
#import <SignalServiceKit/OWSPaymentActivationRequestFinishedMessage.h>
#import <SignalServiceKit/OWSPaymentActivationRequestMessage.h>

View File

@ -185,42 +185,20 @@ public class OldSenderKeyStore {
sendingDistributionIdStore.removeAll(transaction: writeTx)
}
public func skdmBytesForThread(_ thread: TSThread, tx: DBWriteTransaction) -> Data? {
guard let localIdentifiers = DependenciesBridge.shared.tsAccountManager.localIdentifiers(tx: tx) else {
return nil
}
return skdmBytesForThread(
thread,
localAci: localIdentifiers.aci,
localDeviceId: DependenciesBridge.shared.tsAccountManager.storedDeviceId(tx: tx),
tx: tx,
)
}
public func skdmBytesForThread(
_ thread: TSThread,
public func senderKeyDistributionMessage(
forThread thread: TSThread,
localAci: Aci,
localDeviceId: LocalDeviceId,
localDeviceId: DeviceId,
tx: DBWriteTransaction,
) -> Data? {
guard let localDeviceId = localDeviceId.ifValid else {
owsFailDebug("Can't construct sender key message if we're not registered")
return nil
}
do {
let localAddress = ProtocolAddress(localAci, deviceId: localDeviceId)
let distributionId = distributionIdForSendingToThread(thread, writeTx: tx)
let skdm = try SenderKeyDistributionMessage(
from: localAddress,
distributionId: distributionId,
store: self,
context: tx,
)
return skdm.serialize()
} catch {
owsFailDebug("Failed to construct sender key message: \(error)")
return nil
}
) throws -> SenderKeyDistributionMessage {
let localAddress = ProtocolAddress(localAci, deviceId: localDeviceId)
let distributionId = distributionIdForSendingToThread(thread, writeTx: tx)
return try LibSignalClient.SenderKeyDistributionMessage(
from: localAddress,
distributionId: distributionId,
store: self,
context: tx,
)
}
}