session-ios/SessionProtocolKit/Signal/Ratchet/TSDerivedSecrets.m

68 lines
2.1 KiB
Objective-C

//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "TSDerivedSecrets.h"
#import <Curve25519Kit/Curve25519.h>
#import <SignalCoreKit/OWSAsserts.h>
#import <HKDFKit/HKDFKit.h>
@implementation TSDerivedSecrets
+ (instancetype)throws_derivedSecretsWithSeed:(NSData *)masterKey salt:(NSData *)salt info:(NSData *)info
{
OWSAssert(masterKey.length == 32);
OWSAssert(info);
TSDerivedSecrets *secrets = [[TSDerivedSecrets alloc] init];
OWSAssert(secrets);
if (!salt) {
const char *HKDFDefaultSalt[4] = {0};
salt = [NSData dataWithBytes:HKDFDefaultSalt length:sizeof(HKDFDefaultSalt)];
}
@try {
NSData *derivedMaterial = [HKDFKit deriveKey:masterKey info:info salt:salt outputSize:96];
secrets.cipherKey = [derivedMaterial subdataWithRange:NSMakeRange(0, 32)];
secrets.macKey = [derivedMaterial subdataWithRange:NSMakeRange(32, 32)];
secrets.iv = [derivedMaterial subdataWithRange:NSMakeRange(64, 16)];
}
@catch (NSException *exception) {
@throw NSInvalidArgumentException;
}
OWSAssert(secrets.cipherKey.length == 32);
OWSAssert(secrets.macKey.length == 32);
OWSAssert(secrets.iv.length == 16);
return secrets;
}
+ (instancetype)throws_derivedInitialSecretsWithMasterKey:(NSData *)masterKey
{
OWSAssert(masterKey);
NSData *info = [@"WhisperText" dataUsingEncoding:NSUTF8StringEncoding];
return [self throws_derivedSecretsWithSeed:masterKey salt:nil info:info];
}
+ (instancetype)throws_derivedRatchetedSecretsWithSharedSecret:(NSData *)masterKey rootKey:(NSData *)rootKey
{
OWSAssert(masterKey);
OWSAssert(rootKey);
NSData *info = [@"WhisperRatchet" dataUsingEncoding:NSUTF8StringEncoding];
return [self throws_derivedSecretsWithSeed:masterKey salt:rootKey info:info];
}
+ (instancetype)throws_derivedMessageKeysWithData:(NSData *)data
{
OWSAssert(data);
NSData *info = [@"WhisperMessageKeys" dataUsingEncoding:NSUTF8StringEncoding];
return [self throws_derivedSecretsWithSeed:data salt:nil info:info];
}
@end