From 41879ac729088cb50d170ab7a2d7eb6efc1a6349 Mon Sep 17 00:00:00 2001 From: Matt Packer Date: Mon, 9 Oct 2017 09:56:15 -0600 Subject: [PATCH] Fix #4: Add encryption for group messaging Co-Authored-By: Matthew Di Pasquale --- Classes/Models/SignalCiphertext.h | 4 +- .../SignalSenderKeyDistributionMessage.h | 16 ++++ .../SignalSenderKeyDistributionMessage.m | 51 +++++++++++++ ...nalSenderKeyDistributionMessage_Internal.h | 14 ++++ Classes/Models/SignalSenderKeyMessage.h | 14 ++++ Classes/Models/SignalSenderKeyMessage.m | 36 +++++++++ .../Models/SignalSenderKeyMessage_Internal.h | 12 +++ Classes/Models/SignalSenderKeyName.h | 14 ++++ Classes/Models/SignalSenderKeyName.m | 39 ++++++++++ Classes/Models/SignalSenderKeyName_Internal.h | 14 ++++ Classes/SignalGroupCipher.h | 20 +++++ Classes/SignalGroupCipher.m | 76 +++++++++++++++++++ Classes/SignalGroupSessionBuilder.h | 22 ++++++ Classes/SignalGroupSessionBuilder.m | 74 ++++++++++++++++++ Classes/SignalProtocolObjC.h | 4 + Classes/Storage/SignalSenderKeyStore.h | 6 +- Classes/Storage/SignalStorage.m | 13 ++-- 17 files changed, 418 insertions(+), 11 deletions(-) create mode 100644 Classes/Models/SignalSenderKeyDistributionMessage.h create mode 100644 Classes/Models/SignalSenderKeyDistributionMessage.m create mode 100644 Classes/Models/SignalSenderKeyDistributionMessage_Internal.h create mode 100644 Classes/Models/SignalSenderKeyMessage.h create mode 100644 Classes/Models/SignalSenderKeyMessage.m create mode 100644 Classes/Models/SignalSenderKeyMessage_Internal.h create mode 100644 Classes/Models/SignalSenderKeyName.h create mode 100644 Classes/Models/SignalSenderKeyName.m create mode 100644 Classes/Models/SignalSenderKeyName_Internal.h create mode 100644 Classes/SignalGroupCipher.h create mode 100644 Classes/SignalGroupCipher.m create mode 100644 Classes/SignalGroupSessionBuilder.h create mode 100644 Classes/SignalGroupSessionBuilder.m diff --git a/Classes/Models/SignalCiphertext.h b/Classes/Models/SignalCiphertext.h index bf44662..9a3a14b 100644 --- a/Classes/Models/SignalCiphertext.h +++ b/Classes/Models/SignalCiphertext.h @@ -3,7 +3,9 @@ typedef NS_ENUM(NSInteger, SignalCiphertextType) { SignalCiphertextTypeUnknown, SignalCiphertextTypeMessage, - SignalCiphertextTypePreKeyMessage + SignalCiphertextTypePreKeyMessage, + SignalCiphertextTypeSenderKeyMessage, + SignalCiphertextTypeSenderKeyDistributionMessage }; NS_ASSUME_NONNULL_BEGIN diff --git a/Classes/Models/SignalSenderKeyDistributionMessage.h b/Classes/Models/SignalSenderKeyDistributionMessage.h new file mode 100644 index 0000000..7c72ba4 --- /dev/null +++ b/Classes/Models/SignalSenderKeyDistributionMessage.h @@ -0,0 +1,16 @@ +@import Foundation; +#import "SignalContext.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface SignalSenderKeyDistributionMessage : NSObject + +- (nullable instancetype)initWithData:(NSData *)data + context:(SignalContext *)context + error:(NSError **)error; + +- (NSData *)serializedData; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Classes/Models/SignalSenderKeyDistributionMessage.m b/Classes/Models/SignalSenderKeyDistributionMessage.m new file mode 100644 index 0000000..6f2b177 --- /dev/null +++ b/Classes/Models/SignalSenderKeyDistributionMessage.m @@ -0,0 +1,51 @@ +#import "SignalSenderKeyDistributionMessage_Internal.h" +#import "SignalContext_Internal.h" +#import "SignalError.h" + +@implementation SignalSenderKeyDistributionMessage + +- (void)dealloc { + if (_sender_key_distribution_message) { + SIGNAL_UNREF(_sender_key_distribution_message); + } +} + +- (instancetype)initWithSenderKeyDistributionMessage:(sender_key_distribution_message *)sender_key_distribution_message { + NSParameterAssert(sender_key_distribution_message); + if (!sender_key_distribution_message) { return nil; } + if (self = [super init]) { + _sender_key_distribution_message = sender_key_distribution_message; + } + return self; +} + +- (instancetype)initWithData:(NSData *)data + context:(SignalContext *)context + error:(NSError **)error { + NSParameterAssert(data); + NSParameterAssert(context); + if (!data || !context) { + if (error) { + *error = ErrorFromSignalError(SignalErrorInvalidArgument); + } + return nil; + } + if (self = [super init]) { + int result = sender_key_distribution_message_deserialize(&_sender_key_distribution_message, data.bytes, data.length, context.context); + if (result < 0 || !_sender_key_distribution_message) { + if (error) { + *error = ErrorFromSignalError(SignalErrorFromCode(result)); + } + return nil; + } + } + return self; +} + +- (NSData *)serializedData { + ciphertext_message *message = (ciphertext_message *)_sender_key_distribution_message; + signal_buffer *serialized = ciphertext_message_get_serialized(message); + return [NSData dataWithBytes:signal_buffer_data(serialized) length:signal_buffer_len(serialized)]; +} + +@end diff --git a/Classes/Models/SignalSenderKeyDistributionMessage_Internal.h b/Classes/Models/SignalSenderKeyDistributionMessage_Internal.h new file mode 100644 index 0000000..f17d6ce --- /dev/null +++ b/Classes/Models/SignalSenderKeyDistributionMessage_Internal.h @@ -0,0 +1,14 @@ +#import "SignalSenderKeyDistributionMessage.h" +@import SignalProtocolC; + +NS_ASSUME_NONNULL_BEGIN + +@interface SignalSenderKeyDistributionMessage () + +@property (readonly, nonatomic) sender_key_distribution_message *sender_key_distribution_message; + +- (instancetype)initWithSenderKeyDistributionMessage:(sender_key_distribution_message *)sender_key_distribution_message; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Classes/Models/SignalSenderKeyMessage.h b/Classes/Models/SignalSenderKeyMessage.h new file mode 100644 index 0000000..93e67b2 --- /dev/null +++ b/Classes/Models/SignalSenderKeyMessage.h @@ -0,0 +1,14 @@ +@import Foundation; +#import "SignalContext.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface SignalSenderKeyMessage : NSObject + +- (nullable instancetype)initWithData:(NSData *)data + context:(SignalContext *)context + error:(NSError **)error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Classes/Models/SignalSenderKeyMessage.m b/Classes/Models/SignalSenderKeyMessage.m new file mode 100644 index 0000000..82f19ab --- /dev/null +++ b/Classes/Models/SignalSenderKeyMessage.m @@ -0,0 +1,36 @@ +#import "SignalSenderKeyMessage_Internal.h" +#import "SignalContext_Internal.h" +#import "SignalError.h" + +@implementation SignalSenderKeyMessage + +- (void)dealloc { + if (_sender_key_message) { + SIGNAL_UNREF(_sender_key_message); + } +} + +- (instancetype)initWithData:(NSData *)data + context:(SignalContext *)context + error:(NSError **)error { + NSParameterAssert(data); + NSParameterAssert(context); + if (!data || !context) { + if (error) { + *error = ErrorFromSignalError(SignalErrorInvalidArgument); + } + return nil; + } + if (self = [super init]) { + int result = sender_key_message_deserialize(&_sender_key_message, data.bytes, data.length, context.context); + if (result < 0 || !_sender_key_message) { + if (error) { + *error = ErrorFromSignalError(SignalErrorFromCode(result)); + } + return nil; + } + } + return self; +} + +@end diff --git a/Classes/Models/SignalSenderKeyMessage_Internal.h b/Classes/Models/SignalSenderKeyMessage_Internal.h new file mode 100644 index 0000000..c43b8b8 --- /dev/null +++ b/Classes/Models/SignalSenderKeyMessage_Internal.h @@ -0,0 +1,12 @@ +#import "SignalSenderKeyMessage.h" +@import SignalProtocolC; + +NS_ASSUME_NONNULL_BEGIN + +@interface SignalSenderKeyMessage () + +@property (readonly, nonatomic) sender_key_message *sender_key_message; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Classes/Models/SignalSenderKeyName.h b/Classes/Models/SignalSenderKeyName.h new file mode 100644 index 0000000..4b9a29d --- /dev/null +++ b/Classes/Models/SignalSenderKeyName.h @@ -0,0 +1,14 @@ +#import "SignalAddress.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface SignalSenderKeyName : NSObject + +@property (readonly, copy, nonatomic) NSString *groupId; +@property (readonly, nonatomic) SignalAddress *address; + +- (instancetype)initWithGroupId:(NSString *)groupId address:(SignalAddress *)address; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Classes/Models/SignalSenderKeyName.m b/Classes/Models/SignalSenderKeyName.m new file mode 100644 index 0000000..d575c00 --- /dev/null +++ b/Classes/Models/SignalSenderKeyName.m @@ -0,0 +1,39 @@ +#import "SignalSenderKeyName_Internal.h" +#import "SignalAddress_Internal.h" + +@implementation SignalSenderKeyName + +- (void)dealloc { + if (_sender_key_name) { + free((void *)_sender_key_name->group_id); + free(_sender_key_name); + } +} + +- (instancetype)initWithGroupId:(NSString *)groupId address:(SignalAddress *)address { + NSParameterAssert(groupId); + NSParameterAssert(address); + if (!groupId || !address) { return nil; } + if (self = [super init]) { + _groupId = [groupId copy]; + _address = address; + _sender_key_name = malloc(sizeof(signal_protocol_sender_key_name)); + _sender_key_name->group_id = strdup([groupId UTF8String]); + _sender_key_name->group_id_len = [groupId lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; + _sender_key_name->sender = *(address.address); + } + return self; +} + +- (instancetype)initWithSenderKeyName:(const signal_protocol_sender_key_name *)sender_key_name { + NSParameterAssert(sender_key_name); + NSParameterAssert(sender_key_name->group_id); + if (!sender_key_name || !sender_key_name->group_id) { return nil; } + NSString *groupId = [NSString stringWithUTF8String:sender_key_name->group_id]; + SignalAddress *address = [[SignalAddress alloc] initWithAddress:&sender_key_name->sender]; + if (self = [self initWithGroupId:groupId address:address]) { + } + return self; +} + +@end diff --git a/Classes/Models/SignalSenderKeyName_Internal.h b/Classes/Models/SignalSenderKeyName_Internal.h new file mode 100644 index 0000000..5fc6fdb --- /dev/null +++ b/Classes/Models/SignalSenderKeyName_Internal.h @@ -0,0 +1,14 @@ +#import "SignalSenderKeyName.h" +@import SignalProtocolC; + +NS_ASSUME_NONNULL_BEGIN + +@interface SignalSenderKeyName () + +@property (readonly, nonatomic) signal_protocol_sender_key_name *sender_key_name; + +- (nullable instancetype)initWithSenderKeyName:(const signal_protocol_sender_key_name *)sender_key_name; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Classes/SignalGroupCipher.h b/Classes/SignalGroupCipher.h new file mode 100644 index 0000000..4a3acc6 --- /dev/null +++ b/Classes/SignalGroupCipher.h @@ -0,0 +1,20 @@ +@import Foundation; +#import "SignalCiphertext.h" +#import "SignalContext.h" +#import "SignalSenderKeyName.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface SignalGroupCipher : NSObject + +@property (readonly, nonatomic) SignalContext *context; + +- (instancetype)initWithSenderKeyName:(SignalSenderKeyName *)senderKeyName + context:(SignalContext *)context; + +- (nullable SignalCiphertext *)encryptData:(NSData *)data error:(NSError **)error; +- (nullable NSData *)decryptCiphertext:(SignalCiphertext *)ciphertext error:(NSError **)error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Classes/SignalGroupCipher.m b/Classes/SignalGroupCipher.m new file mode 100644 index 0000000..e0492f4 --- /dev/null +++ b/Classes/SignalGroupCipher.m @@ -0,0 +1,76 @@ +#import "SignalGroupCipher.h" +#import "SignalContext_Internal.h" +#import "SignalError.h" +#import "SignalSenderKeyMessage_Internal.h" +#import "SignalSenderKeyName_Internal.h" +#import "SignalStorage_Internal.h" + +@interface SignalGroupCipher () +@property (readonly, nonatomic) group_cipher *cipher; +@end + +@implementation SignalGroupCipher + +- (instancetype)initWithSenderKeyName:(SignalSenderKeyName *)senderKeyName + context:(SignalContext *)context { + NSParameterAssert(senderKeyName); + NSParameterAssert(context); + if (!senderKeyName || !context) { return nil; } + if (self = [super init]) { + _context = context; + int result = group_cipher_create(&_cipher, context.storage.storeContext, senderKeyName.sender_key_name, context.context); + NSAssert(result >= 0 && _cipher, @"couldn't create cipher"); + if (result < 0 || !_cipher) { + return nil; + } + } + return self; +} + +- (SignalCiphertext *)encryptData:(NSData *)data error:(NSError **)error { + NSParameterAssert(data); + if (!data) { + if (error) { + *error = ErrorFromSignalError(SignalErrorInvalidArgument); + } + return nil; + } + ciphertext_message *message = NULL; + int result = group_cipher_encrypt(_cipher, data.bytes, data.length, &message); + if (result < 0 || !message) { + *error = ErrorFromSignalError(SignalErrorFromCode(result)); + return nil; + } + signal_buffer *serialized = ciphertext_message_get_serialized(message); + NSData *outData = [NSData dataWithBytes:signal_buffer_data(serialized) length:signal_buffer_len(serialized)]; + SignalCiphertextType outType = SignalCiphertextTypeSenderKeyMessage; + SignalCiphertext *encrypted = [[SignalCiphertext alloc] initWithData:outData type:outType]; + SIGNAL_UNREF(message); + return encrypted; +} + +- (nullable NSData *)decryptCiphertext:(SignalCiphertext *)ciphertext error:(NSError **)error { + NSParameterAssert(ciphertext && ciphertext.data); + if (!ciphertext || !ciphertext.data) { + if (error) { + *error = ErrorFromSignalError(SignalErrorInvalidArgument); + } + return nil; + } + SignalSenderKeyMessage *message = [[SignalSenderKeyMessage alloc] initWithData:ciphertext.data context:_context error:error]; + if (!message) { return nil; } + signal_buffer *buffer = NULL; + int result = SG_ERR_UNKNOWN; + result = group_cipher_decrypt(_cipher, message.sender_key_message, NULL, &buffer); + if (result < 0 || !buffer) { + if (error) { + *error = ErrorFromSignalError(SignalErrorFromCode(result)); + } + return nil; + } + NSData *outData = [NSData dataWithBytes:signal_buffer_data(buffer) length:signal_buffer_len(buffer)]; + signal_buffer_free(buffer); + return outData; +} + +@end diff --git a/Classes/SignalGroupSessionBuilder.h b/Classes/SignalGroupSessionBuilder.h new file mode 100644 index 0000000..3760f46 --- /dev/null +++ b/Classes/SignalGroupSessionBuilder.h @@ -0,0 +1,22 @@ +@import Foundation; +#import "SignalContext.h" +#import "SignalSenderKeyDistributionMessage.h" +#import "SignalSenderKeyName.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface SignalGroupSessionBuilder : NSObject + +@property (readonly, nonatomic) SignalContext *context; + +- (instancetype)initWithContext:(SignalContext *)context; + +- (BOOL)processSessionWithSenderKeyName:(SignalSenderKeyName *)senderKeyName + senderKeyDistributionMessage:(SignalSenderKeyDistributionMessage *)senderKeyDistributionMessage + error:(NSError **)error; +- (nullable SignalSenderKeyDistributionMessage *)createSessionWithSenderKeyName:(SignalSenderKeyName *)senderKeyName + error:(NSError **)error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Classes/SignalGroupSessionBuilder.m b/Classes/SignalGroupSessionBuilder.m new file mode 100644 index 0000000..4b6587e --- /dev/null +++ b/Classes/SignalGroupSessionBuilder.m @@ -0,0 +1,74 @@ +#import "SignalGroupSessionBuilder.h" +#import "SignalContext_Internal.h" +#import "SignalError.h" +#import "SignalSenderKeyDistributionMessage_Internal.h" +#import "SignalSenderKeyName_Internal.h" +#import "SignalStorage_Internal.h" + +@interface SignalGroupSessionBuilder () +@property (readonly, nonatomic) group_session_builder *builder; +@end + +@implementation SignalGroupSessionBuilder + +- (void)dealloc { + if (_builder) { + group_session_builder_free(_builder); + } + _builder = NULL; +} + +- (instancetype)initWithContext:(SignalContext *)context { + NSParameterAssert(context); + if (!context) { return nil; } + if (self = [super init]) { + _context = context; + int result = group_session_builder_create(&_builder, context.storage.storeContext, context.context); + NSAssert(result == 0 && _builder, @"couldn't create builder"); + if (result < 0 || !_builder) { + return nil; + } + } + return self; +} + +- (BOOL)processSessionWithSenderKeyName:(SignalSenderKeyName *)senderKeyName + senderKeyDistributionMessage:(SignalSenderKeyDistributionMessage *)senderKeyDistributionMessage + error:(NSError **)error { + NSParameterAssert(senderKeyName); + NSParameterAssert(senderKeyDistributionMessage); + if (!senderKeyName || !senderKeyDistributionMessage) { + if (error) { + *error = ErrorFromSignalError(SignalErrorInvalidArgument); + } + return NO; + } + int result = group_session_builder_process_session(_builder, senderKeyName.sender_key_name, senderKeyDistributionMessage.sender_key_distribution_message); + if (result < 0) { + if (error) { + *error = ErrorFromSignalError(result); + } + return NO; + } + return YES; +} + +- (SignalSenderKeyDistributionMessage *)createSessionWithSenderKeyName:(SignalSenderKeyName *)senderKeyName + error:(NSError **)error { + NSParameterAssert(senderKeyName); + if (!senderKeyName) { + if (error) { + *error = ErrorFromSignalError(SignalErrorInvalidArgument); + } + return nil; + } + sender_key_distribution_message *distribution_message = NULL; + int result = group_session_builder_create_session(_builder, &distribution_message, senderKeyName.sender_key_name); + if (result < 0 || !distribution_message) { + *error = ErrorFromSignalError(SignalErrorFromCode(result)); + return nil; + } + return [[SignalSenderKeyDistributionMessage alloc] initWithSenderKeyDistributionMessage:distribution_message]; +} + +@end diff --git a/Classes/SignalProtocolObjC.h b/Classes/SignalProtocolObjC.h index 27978c2..817125b 100644 --- a/Classes/SignalProtocolObjC.h +++ b/Classes/SignalProtocolObjC.h @@ -11,6 +11,8 @@ FOUNDATION_EXPORT const unsigned char SignalProtocolObjCVersionString[]; #import "SignalCommonCryptoProvider.h" #import "SignalContext.h" #import "SignalError.h" +#import "SignalGroupCipher.h" +#import "SignalGroupSessionBuilder.h" #import "SignalIdentityKeyPair.h" #import "SignalIdentityKeyStore.h" #import "SignalKeyHelper.h" @@ -19,6 +21,8 @@ FOUNDATION_EXPORT const unsigned char SignalProtocolObjCVersionString[]; #import "SignalPreKeyBundle.h" #import "SignalPreKeyMessage.h" #import "SignalPreKeyStore.h" +#import "SignalSenderKeyDistributionMessage.h" +#import "SignalSenderKeyName.h" #import "SignalSenderKeyStore.h" #import "SignalSerializable.h" #import "SignalSessionBuilder.h" diff --git a/Classes/Storage/SignalSenderKeyStore.h b/Classes/Storage/SignalSenderKeyStore.h index be1cf22..4de3b04 100644 --- a/Classes/Storage/SignalSenderKeyStore.h +++ b/Classes/Storage/SignalSenderKeyStore.h @@ -1,5 +1,5 @@ @import Foundation; -#import "SignalAddress.h" +#import "SignalSenderKeyName.h" NS_ASSUME_NONNULL_BEGIN @@ -11,13 +11,13 @@ NS_ASSUME_NONNULL_BEGIN * Store a serialized sender key record for a given * (groupId + senderId + deviceId) tuple. */ -- (BOOL) storeSenderKey:(NSData*)senderKey address:(SignalAddress*)address groupId:(NSString*)groupId; +- (BOOL)storeSenderKey:(NSData *)senderKey senderKeyName:(SignalSenderKeyName *)senderKeyName; /** * Returns a copy of the sender key record corresponding to the * (groupId + senderId + deviceId) tuple. */ -- (nullable NSData*) loadSenderKeyForAddress:(SignalAddress*)address groupId:(NSString*)groupId; +- (nullable NSData *)loadSenderKeyForSenderKeyName:(SignalSenderKeyName *)senderKeyName; @end diff --git a/Classes/Storage/SignalStorage.m b/Classes/Storage/SignalStorage.m index 22715a5..999cab9 100644 --- a/Classes/Storage/SignalStorage.m +++ b/Classes/Storage/SignalStorage.m @@ -1,5 +1,6 @@ #import "SignalStorage.h" #import "SignalAddress_Internal.h" +#import "SignalSenderKeyName_Internal.h" #import "SignalStorage_Internal.h" #pragma mark signal_protocol_session_store callbacks @@ -216,10 +217,9 @@ static int is_trusted_identity(const signal_protocol_address *_address, uint8_t static int store_sender_key(const signal_protocol_sender_key_name *sender_key_name, uint8_t *record, size_t record_len, void *user_data) { id senderKeyStore = (__bridge id)(user_data); - SignalAddress *address = [[SignalAddress alloc] initWithAddress:&sender_key_name->sender]; - NSString *groupId = [NSString stringWithUTF8String:sender_key_name->group_id]; NSData *key = [NSData dataWithBytes:record length:record_len]; - BOOL result = [senderKeyStore storeSenderKey:key address:address groupId:groupId]; + SignalSenderKeyName *senderKeyName = [[SignalSenderKeyName alloc] initWithSenderKeyName:sender_key_name]; + BOOL result = [senderKeyStore storeSenderKey:key senderKeyName:senderKeyName]; if (result) { return 0; } else { @@ -229,9 +229,8 @@ static int store_sender_key(const signal_protocol_sender_key_name *sender_key_na static int load_sender_key(signal_buffer **record, const signal_protocol_sender_key_name *sender_key_name, void *user_data) { id senderKeyStore = (__bridge id)(user_data); - SignalAddress *address = [[SignalAddress alloc] initWithAddress:&sender_key_name->sender]; - NSString *groupId = [NSString stringWithUTF8String:sender_key_name->group_id]; - NSData *key = [senderKeyStore loadSenderKeyForAddress:address groupId:groupId]; + SignalSenderKeyName *senderKeyName = [[SignalSenderKeyName alloc] initWithSenderKeyName:sender_key_name]; + NSData *key = [senderKeyStore loadSenderKeyForSenderKeyName:senderKeyName]; if (key) { signal_buffer *buffer = signal_buffer_create(key.bytes, key.length); *record = buffer; @@ -332,7 +331,7 @@ - (void)setupWithContext:(signal_context *)context { senderKeyStoreCallbacks.store_sender_key = store_sender_key; senderKeyStoreCallbacks.load_sender_key = load_sender_key; senderKeyStoreCallbacks.destroy_func = destroy_func; - identityKeyStoreCallbacks.user_data = (__bridge void *)(_senderKeyStore); + senderKeyStoreCallbacks.user_data = (__bridge void *)(_senderKeyStore); signal_protocol_store_context_set_sender_key_store(_storeContext, &senderKeyStoreCallbacks); }