217 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			Mathematica
		
	
	
	
		
		
			
		
	
	
			217 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			Mathematica
		
	
	
	
|  | //
 | ||
|  | //  TDEncryptManager.m
 | ||
|  | //  ThinkingSDK
 | ||
|  | //
 | ||
|  | //  Created by wwango on 2022/1/21.
 | ||
|  | //
 | ||
|  | 
 | ||
|  | #import "TDEncryptManager.h"
 | ||
|  | #import "TDEncryptProtocol.h"
 | ||
|  | #import "TDSecretKey.h"
 | ||
|  | #import "TDRSAEncryptorPlugin.h"
 | ||
|  | #if __has_include(<ThinkingDataCore/NSData+TDGzip.h>)
 | ||
|  | #import <ThinkingDataCore/NSData+TDGzip.h>
 | ||
|  | #else
 | ||
|  | #import "NSData+TDGzip.h"
 | ||
|  | #endif
 | ||
|  | #if __has_include(<ThinkingDataCore/TDJSONUtil.h>)
 | ||
|  | #import <ThinkingDataCore/TDJSONUtil.h>
 | ||
|  | #else
 | ||
|  | #import "TDJSONUtil.h"
 | ||
|  | #endif
 | ||
|  | #import "TDLogging.h"
 | ||
|  | 
 | ||
|  | @interface TDEncryptManager ()
 | ||
|  | @property (nonatomic, strong) id<TDEncryptProtocol> encryptor;
 | ||
|  | @property (nonatomic, copy) NSArray<id<TDEncryptProtocol>> *encryptors;
 | ||
|  | @property (nonatomic, copy) NSString *encryptedSymmetricKey;
 | ||
|  | @property (nonatomic, strong) TDSecretKey *secretKey;
 | ||
|  | @property (nonatomic, strong) TDSecretKey *customSecretKey;
 | ||
|  | 
 | ||
|  | @end
 | ||
|  | 
 | ||
|  | @implementation TDEncryptManager
 | ||
|  | 
 | ||
|  | - (instancetype)initWithSecretKey:(TDSecretKey *)secretKey {
 | ||
|  |     self = [self init];
 | ||
|  |     if (self) {
 | ||
|  |         self.customSecretKey = secretKey;
 | ||
|  |         [self updateEncryptor:secretKey];
 | ||
|  |     }
 | ||
|  |     return self;
 | ||
|  | }
 | ||
|  | 
 | ||
|  | - (instancetype)init
 | ||
|  | {
 | ||
|  |     self = [super init];
 | ||
|  |     if (self) {
 | ||
|  |         NSMutableArray *encryptors = [NSMutableArray array];
 | ||
|  |         [encryptors addObject:[TDRSAEncryptorPlugin new]];
 | ||
|  |         self.encryptors = encryptors;
 | ||
|  |     }
 | ||
|  |     return self;
 | ||
|  | }
 | ||
|  | 
 | ||
|  | - (void)handleEncryptWithConfig:(NSDictionary *)encryptConfig {
 | ||
|  |     
 | ||
|  |     if (!encryptConfig || ![encryptConfig isKindOfClass:[NSDictionary class]]) {
 | ||
|  |         return;
 | ||
|  |     }
 | ||
|  |     
 | ||
|  |     if (![encryptConfig objectForKey:@"version"]) {
 | ||
|  |         return;
 | ||
|  |     }
 | ||
|  |     
 | ||
|  |     NSInteger version = [[encryptConfig objectForKey:@"version"] integerValue];
 | ||
|  |     TDSecretKey *secretKey = [[TDSecretKey alloc] initWithVersion:version
 | ||
|  |                                                         publicKey:encryptConfig[@"key"]
 | ||
|  |                                              asymmetricEncryption:encryptConfig[@"asymmetric"]
 | ||
|  |                                               symmetricEncryption:encryptConfig[@"symmetric"]];
 | ||
|  |     
 | ||
|  |     
 | ||
|  |     if (![secretKey isValid]) {
 | ||
|  |         return;
 | ||
|  |     }
 | ||
|  |     
 | ||
|  |     
 | ||
|  |     if (![self encryptorWithSecretKey:secretKey]) {
 | ||
|  |         return;
 | ||
|  |     }
 | ||
|  |     
 | ||
|  |     
 | ||
|  |     [self updateEncryptor:secretKey];
 | ||
|  | }
 | ||
|  | 
 | ||
|  | - (void)updateEncryptor:(TDSecretKey *)obj {
 | ||
|  |     @try {
 | ||
|  | 
 | ||
|  |         TDSecretKey *secretKey = obj;
 | ||
|  |         if (!secretKey.publicKey.length) {
 | ||
|  |             return;
 | ||
|  |         }
 | ||
|  | 
 | ||
|  |         if ([self needUpdateSecretKey:self.secretKey newSecretKey:secretKey]) {
 | ||
|  |             return;
 | ||
|  |         }
 | ||
|  | 
 | ||
|  |         id<TDEncryptProtocol> encryptor = [self filterEncrptor:secretKey];
 | ||
|  |         if (!encryptor) {
 | ||
|  |             return;
 | ||
|  |         }
 | ||
|  | 
 | ||
|  |         NSString *encryptedSymmetricKey = [encryptor encryptSymmetricKeyWithPublicKey:secretKey.publicKey];
 | ||
|  |         
 | ||
|  |         if (encryptedSymmetricKey.length) {
 | ||
|  | 
 | ||
|  |             self.secretKey = secretKey;
 | ||
|  | 
 | ||
|  |             self.encryptor = encryptor;
 | ||
|  | 
 | ||
|  |             self.encryptedSymmetricKey = encryptedSymmetricKey;
 | ||
|  |             
 | ||
|  |             TDLogDebug(@"\n****************secretKey****************\n public key: %@ \n encrypted symmetric key: %@\n****************secretKey****************", secretKey.publicKey, encryptedSymmetricKey);
 | ||
|  |         }
 | ||
|  |     } @catch (NSException *exception) {
 | ||
|  |         TDLogError(@"%@ error: %@", self, exception);
 | ||
|  |     }
 | ||
|  | }
 | ||
|  | 
 | ||
|  | - (BOOL)needUpdateSecretKey:(TDSecretKey *)oldSecretKey newSecretKey:(TDSecretKey *)newSecretKey {
 | ||
|  |     if (oldSecretKey.version != newSecretKey.version) {
 | ||
|  |         return NO;
 | ||
|  |     }
 | ||
|  |     if (![oldSecretKey.publicKey isEqualToString:newSecretKey.publicKey]) {
 | ||
|  |         return NO;
 | ||
|  |     }
 | ||
|  |     if (![oldSecretKey.symmetricEncryption isEqualToString:newSecretKey.symmetricEncryption]) {
 | ||
|  |         return NO;
 | ||
|  |     }
 | ||
|  |     if (![oldSecretKey.asymmetricEncryption isEqualToString:newSecretKey.asymmetricEncryption]) {
 | ||
|  |         return NO;
 | ||
|  |     }
 | ||
|  |     return YES;
 | ||
|  | }
 | ||
|  | 
 | ||
|  | - (id<TDEncryptProtocol>)filterEncrptor:(TDSecretKey *)secretKey {
 | ||
|  |     id<TDEncryptProtocol> encryptor = [self encryptorWithSecretKey:secretKey];
 | ||
|  |     if (!encryptor) {
 | ||
|  |         NSString *format = @"\n You have used the [%@] key, but the corresponding encryption plugin has not been registered. \n";
 | ||
|  |         NSString *type = [NSString stringWithFormat:@"%@+%@", secretKey.asymmetricEncryption, secretKey.symmetricEncryption];
 | ||
|  |         NSString *message = [NSString stringWithFormat:format, type];
 | ||
|  |         NSAssert(NO, message);
 | ||
|  |         return nil;
 | ||
|  |     }
 | ||
|  |     return encryptor;
 | ||
|  | }
 | ||
|  | 
 | ||
|  | - (id<TDEncryptProtocol>)encryptorWithSecretKey:(TDSecretKey *)secretKey {
 | ||
|  |     if (!secretKey) {
 | ||
|  |         return nil;
 | ||
|  |     }
 | ||
|  |     __block id<TDEncryptProtocol> encryptor;
 | ||
|  |     [self.encryptors enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(id<TDEncryptProtocol> obj, NSUInteger idx, BOOL *stop) {
 | ||
|  |         BOOL isSameAsymmetricType = [[obj asymmetricEncryptType] isEqualToString:secretKey.asymmetricEncryption];
 | ||
|  |         BOOL isSameSymmetricType = [[obj symmetricEncryptType] isEqualToString:secretKey.symmetricEncryption];
 | ||
|  |         if (isSameAsymmetricType && isSameSymmetricType) {
 | ||
|  |             encryptor = obj;
 | ||
|  |             *stop = YES;
 | ||
|  |         }
 | ||
|  |     }];
 | ||
|  |     return encryptor;
 | ||
|  | }
 | ||
|  | 
 | ||
|  | - (NSDictionary *)encryptJSONObject:(NSDictionary *)obj {
 | ||
|  |     @try {
 | ||
|  |         if (!obj) {
 | ||
|  |             TDLogDebug(@"Enable encryption but the input obj is invalid!");
 | ||
|  |             return nil;
 | ||
|  |         }
 | ||
|  | 
 | ||
|  |         if (!self.encryptor) {
 | ||
|  |             TDLogDebug(@"Enable encryption but the secret key is invalid!");
 | ||
|  |             return nil;
 | ||
|  |         }
 | ||
|  | 
 | ||
|  |         if (![self encryptSymmetricKey]) {
 | ||
|  |             TDLogDebug(@"Enable encryption but encrypt symmetric key is failed!");
 | ||
|  |             return nil;
 | ||
|  |         }
 | ||
|  | 
 | ||
|  |         
 | ||
|  |         NSData *jsonData = [TDJSONUtil JSONSerializeForObject:obj];
 | ||
|  | 
 | ||
|  |         
 | ||
|  |         NSString *encryptedString =  [self.encryptor encryptEvent:jsonData];
 | ||
|  |         if (!encryptedString) {
 | ||
|  |             TDLogDebug(@"Enable encryption but encrypted input obj is invalid!");
 | ||
|  |             return nil;
 | ||
|  |         }
 | ||
|  | 
 | ||
|  |         
 | ||
|  |         NSMutableDictionary *secretObj = [NSMutableDictionary dictionary];
 | ||
|  |         secretObj[@"pkv"] = @(self.secretKey.version);
 | ||
|  |         secretObj[@"ekey"] = self.encryptedSymmetricKey;
 | ||
|  |         secretObj[@"payload"] = encryptedString;
 | ||
|  |         return [NSDictionary dictionaryWithDictionary:secretObj];
 | ||
|  |     } @catch (NSException *exception) {
 | ||
|  |         TDLogDebug(@"%@ error: %@", self, exception);
 | ||
|  |         return nil;
 | ||
|  |     }
 | ||
|  | }
 | ||
|  | 
 | ||
|  | 
 | ||
|  | - (BOOL)encryptSymmetricKey {
 | ||
|  |     if (self.encryptedSymmetricKey) {
 | ||
|  |         return YES;
 | ||
|  |     }
 | ||
|  |     NSString *publicKey = self.secretKey.publicKey;
 | ||
|  |     self.encryptedSymmetricKey = [self.encryptor encryptSymmetricKeyWithPublicKey:publicKey];
 | ||
|  |     return self.encryptedSymmetricKey != nil;
 | ||
|  | }
 | ||
|  | 
 | ||
|  | - (BOOL)isValid {
 | ||
|  |     return _encryptor ? YES:NO;
 | ||
|  | }
 | ||
|  | 
 | ||
|  | @end
 |