Support new padding scheme

This commit is contained in:
Ali 2021-07-04 17:23:58 +04:00
parent 3cff0fe015
commit e0abfd0f66
3 changed files with 353 additions and 157 deletions

View File

@ -379,14 +379,14 @@ static int32_t fixedTimeDifferenceValue = 0;
NSDictionary *datacenterAuthInfoById = [keychain objectForKey:@"datacenterAuthInfoById" group:@"persistent"];
if (datacenterAuthInfoById != nil) {
_datacenterAuthInfoById = [[NSMutableDictionary alloc] initWithDictionary:datacenterAuthInfoById];
/*#if DEBUG
#if DEBUG
NSArray<NSNumber *> *keys = [_datacenterAuthInfoById allKeys];
for (NSNumber *key in keys) {
if (parseAuthInfoMapKeyInteger(key).selector != MTDatacenterAuthInfoSelectorPersistent) {
[_datacenterAuthInfoById removeObjectForKey:key];
}
}
#endif*/
#endif
}
NSDictionary *datacenterPublicKeysById = [keychain objectForKey:@"datacenterPublicKeysById" group:@"ephemeral"];

View File

@ -13,6 +13,7 @@
#import <MtProtoKit/MTDatacenterSaltInfo.h>
#import "MTBuffer.h"
#import <MtProtoKit/MTEncryption.h>
#import <CommonCrypto/CommonCrypto.h>
#import "MTInternalMessageParser.h"
#import "MTServerDhInnerDataMessage.h"
@ -20,99 +21,133 @@
#import "MTServerDhParamsMessage.h"
#import "MTSetClientDhParamsResponseMessage.h"
static NSArray *defaultPublicKeys() {
static NSArray *serverPublicKeys = nil;
@interface MTDatacenterAuthPublicKey : NSObject
@property (nonatomic, strong, readonly) NSString *publicKey;
@property (nonatomic, readonly) bool usesModernPaddingScheme;
@end
@implementation MTDatacenterAuthPublicKey
- (instancetype)initWithPublicKey:(NSString *)publicKey usesModernPaddingScheme:(bool)usesModernPaddingScheme {
self = [super init];
if (self != nil) {
_publicKey = publicKey;
_usesModernPaddingScheme = usesModernPaddingScheme;
}
return self;
}
- (uint64_t)fingerprintWithEncryptionProvider:(id<EncryptionProvider>)encryptionProvider {
return MTRsaFingerprint(encryptionProvider, _publicKey);
}
@end
static NSArray<MTDatacenterAuthPublicKey *> *defaultPublicKeys() {
static NSArray<MTDatacenterAuthPublicKey *> *serverPublicKeys = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^
{
serverPublicKeys = [[NSArray alloc] initWithObjects:
[[NSDictionary alloc] initWithObjectsAndKeys:@"-----BEGIN RSA PUBLIC KEY-----\n"
"MIIBCgKCAQEAxq7aeLAqJR20tkQQMfRn+ocfrtMlJsQ2Uksfs7Xcoo77jAid0bRt\n"
"ksiVmT2HEIJUlRxfABoPBV8wY9zRTUMaMA654pUX41mhyVN+XoerGxFvrs9dF1Ru\n"
"vCHbI02dM2ppPvyytvvMoefRoL5BTcpAihFgm5xCaakgsJ/tH5oVl74CdhQw8J5L\n"
"xI/K++KJBUyZ26Uba1632cOiq05JBUW0Z2vWIOk4BLysk7+U9z+SxynKiZR3/xdi\n"
"XvFKk01R3BHV+GUKM2RYazpS/P8v7eyKhAbKxOdRcFpHLlVwfjyM1VlDQrEZxsMp\n"
"NTLYXb6Sce1Uov0YtNx5wEowlREH1WOTlwIDAQAB\n"
"-----END RSA PUBLIC KEY-----", @"key", [[NSNumber alloc] initWithUnsignedLongLong:0x9a996a1db11c729bUL], @"fingerprint", nil],
[[NSDictionary alloc] initWithObjectsAndKeys:@"-----BEGIN RSA PUBLIC KEY-----\n"
"MIIBCgKCAQEAsQZnSWVZNfClk29RcDTJQ76n8zZaiTGuUsi8sUhW8AS4PSbPKDm+\n"
"DyJgdHDWdIF3HBzl7DHeFrILuqTs0vfS7Pa2NW8nUBwiaYQmPtwEa4n7bTmBVGsB\n"
"1700/tz8wQWOLUlL2nMv+BPlDhxq4kmJCyJfgrIrHlX8sGPcPA4Y6Rwo0MSqYn3s\n"
"g1Pu5gOKlaT9HKmE6wn5Sut6IiBjWozrRQ6n5h2RXNtO7O2qCDqjgB2vBxhV7B+z\n"
"hRbLbCmW0tYMDsvPpX5M8fsO05svN+lKtCAuz1leFns8piZpptpSCFn7bWxiA9/f\n"
"x5x17D7pfah3Sy2pA+NDXyzSlGcKdaUmwQIDAQAB\n"
"-----END RSA PUBLIC KEY-----", @"key", [[NSNumber alloc] initWithUnsignedLongLong:0xb05b2a6f70cdea78UL], @"fingerprint", nil],
[[NSDictionary alloc] initWithObjectsAndKeys:@"-----BEGIN RSA PUBLIC KEY-----\n"
"MIIBCgKCAQEAwVACPi9w23mF3tBkdZz+zwrzKOaaQdr01vAbU4E1pvkfj4sqDsm6\n"
"lyDONS789sVoD/xCS9Y0hkkC3gtL1tSfTlgCMOOul9lcixlEKzwKENj1Yz/s7daS\n"
"an9tqw3bfUV/nqgbhGX81v/+7RFAEd+RwFnK7a+XYl9sluzHRyVVaTTveB2GazTw\n"
"Efzk2DWgkBluml8OREmvfraX3bkHZJTKX4EQSjBbbdJ2ZXIsRrYOXfaA+xayEGB+\n"
"8hdlLmAjbCVfaigxX0CDqWeR1yFL9kwd9P0NsZRPsmoqVwMbMu7mStFai6aIhc3n\n"
"Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB\n"
"-----END RSA PUBLIC KEY-----", @"key", [[NSNumber alloc] initWithUnsignedLongLong:0xc3b42b026ce86b21UL], @"fingerprint", nil],
[[NSDictionary alloc] initWithObjectsAndKeys:@"-----BEGIN RSA PUBLIC KEY-----\n"
"MIIBCgKCAQEAwqjFW0pi4reKGbkc9pK83Eunwj/k0G8ZTioMMPbZmW99GivMibwa\n"
"xDM9RDWabEMyUtGoQC2ZcDeLWRK3W8jMP6dnEKAlvLkDLfC4fXYHzFO5KHEqF06i\n"
"qAqBdmI1iBGdQv/OQCBcbXIWCGDY2AsiqLhlGQfPOI7/vvKc188rTriocgUtoTUc\n"
"/n/sIUzkgwTqRyvWYynWARWzQg0I9olLBBC2q5RQJJlnYXZwyTL3y9tdb7zOHkks\n"
"WV9IMQmZmyZh/N7sMbGWQpt4NMchGpPGeJ2e5gHBjDnlIf2p1yZOYeUYrdbwcS0t\n"
"UiggS4UeE8TzIuXFQxw7fzEIlmhIaq3FnwIDAQAB\n"
"-----END RSA PUBLIC KEY-----", @"key", [[NSNumber alloc] initWithUnsignedLongLong:0x71e025b6c76033e3UL], @"fingerprint", nil],
[[NSDictionary alloc] initWithObjectsAndKeys:@"-----BEGIN RSA PUBLIC KEY-----\n"
"MIIBCgKCAQEAruw2yP/BCcsJliRoW5eBVBVle9dtjJw+OYED160Wybum9SXtBBLX\n"
"riwt4rROd9csv0t0OHCaTmRqBcQ0J8fxhN6/cpR1GWgOZRUAiQxoMnlt0R93LCX/\n"
"j1dnVa/gVbCjdSxpbrfY2g2L4frzjJvdl84Kd9ORYjDEAyFnEA7dD556OptgLQQ2\n"
"e2iVNq8NZLYTzLp5YpOdO1doK+ttrltggTCy5SrKeLoCPPbOgGsdxJxyz5KKcZnS\n"
"Lj16yE5HvJQn0CNpRdENvRUXe6tBP78O39oJ8BTHp9oIjd6XWXAsp2CvK45Ol8wF\n"
"XGF710w9lwCGNbmNxNYhtIkdqfsEcwR5JwIDAQAB\n"
"-----END RSA PUBLIC KEY-----", @"key", [[NSNumber alloc] initWithUnsignedLongLong:0xbc35f3509f7b7a5UL], @"fingerprint", nil],
[[NSDictionary alloc] initWithObjectsAndKeys:@"-----BEGIN RSA PUBLIC KEY-----\n"
"MIIBCgKCAQEAvfLHfYH2r9R70w8prHblWt/nDkh+XkgpflqQVcnAfSuTtO05lNPs\n"
"pQmL8Y2XjVT4t8cT6xAkdgfmmvnvRPOOKPi0OfJXoRVylFzAQG/j83u5K3kRLbae\n"
"7fLccVhKZhY46lvsueI1hQdLgNV9n1cQ3TDS2pQOCtovG4eDl9wacrXOJTG2990V\n"
"jgnIKNA0UMoP+KF03qzryqIt3oTvZq03DyWdGK+AZjgBLaDKSnC6qD2cFY81UryR\n"
"WOab8zKkWAnhw2kFpcqhI0jdV5QaSCExvnsjVaX0Y1N0870931/5Jb9ICe4nweZ9\n"
"kSDF/gip3kWLG0o8XQpChDfyvsqB9OLV/wIDAQAB\n"
"-----END RSA PUBLIC KEY-----", @"key", [[NSNumber alloc] initWithUnsignedLongLong:0x15ae5fa8b5529542UL], @"fingerprint", nil],
[[NSDictionary alloc] initWithObjectsAndKeys:@"-----BEGIN RSA PUBLIC KEY-----\n"
"MIIBCgKCAQEAs/ditzm+mPND6xkhzwFIz6J/968CtkcSE/7Z2qAJiXbmZ3UDJPGr\n"
"zqTDHkO30R8VeRM/Kz2f4nR05GIFiITl4bEjvpy7xqRDspJcCFIOcyXm8abVDhF+\n"
"th6knSU0yLtNKuQVP6voMrnt9MV1X92LGZQLgdHZbPQz0Z5qIpaKhdyA8DEvWWvS\n"
"Uwwc+yi1/gGaybwlzZwqXYoPOhwMebzKUk0xW14htcJrRrq+PXXQbRzTMynseCoP\n"
"Ioke0dtCodbA3qQxQovE16q9zz4Otv2k4j63cz53J+mhkVWAeWxVGI0lltJmWtEY\n"
"K6er8VqqWot3nqmWMXogrgRLggv/NbbooQIDAQAB\n"
"-----END RSA PUBLIC KEY-----", @"key", [[NSNumber alloc] initWithUnsignedLongLong:0xaeae98e13cd7f94fUL], @"fingerprint", nil],
[[NSDictionary alloc] initWithObjectsAndKeys:@"-----BEGIN RSA PUBLIC KEY-----\n"
"MIIBCgKCAQEAvmpxVY7ld/8DAjz6F6q05shjg8/4p6047bn6/m8yPy1RBsvIyvuD\n"
"uGnP/RzPEhzXQ9UJ5Ynmh2XJZgHoE9xbnfxL5BXHplJhMtADXKM9bWB11PU1Eioc\n"
"3+AXBB8QiNFBn2XI5UkO5hPhbb9mJpjA9Uhw8EdfqJP8QetVsI/xrCEbwEXe0xvi\n"
"fRLJbY08/Gp66KpQvy7g8w7VB8wlgePexW3pT13Ap6vuC+mQuJPyiHvSxjEKHgqe\n"
"Pji9NP3tJUFQjcECqcm0yV7/2d0t/pbCm+ZH1sadZspQCEPPrtbkQBlvHb4OLiIW\n"
"PGHKSMeRFvp3IWcmdJqXahxLCUS1Eh6MAQIDAQAB\n"
"-----END RSA PUBLIC KEY-----", @"key", [[NSNumber alloc] initWithUnsignedLongLong:0x5a181b2235057d98UL], @"fingerprint", nil],
[[NSDictionary alloc] initWithObjectsAndKeys:@"-----BEGIN RSA PUBLIC KEY-----\n"
"MIIBCgKCAQEAr4v4wxMDXIaMOh8bayF/NyoYdpcysn5EbjTIOZC0RkgzsRj3SGlu\n"
"52QSz+ysO41dQAjpFLgxPVJoOlxXokaOq827IfW0bGCm0doT5hxtedu9UCQKbE8j\n"
"lDOk+kWMXHPZFJKWRgKgTu9hcB3y3Vk+JFfLpq3d5ZB48B4bcwrRQnzkx5GhWOFX\n"
"x73ZgjO93eoQ2b/lDyXxK4B4IS+hZhjzezPZTI5upTRbs5ljlApsddsHrKk6jJNj\n"
"8Ygs/ps8e6ct82jLXbnndC9s8HjEvDvBPH9IPjv5JUlmHMBFZ5vFQIfbpo0u0+1P\n"
"n6bkEi5o7/ifoyVv2pAZTRwppTz0EuXD8QIDAQAB\n"
"-----END RSA PUBLIC KEY-----", @"key", [[NSNumber alloc] initWithUnsignedLongLong:0x9692106da14b9f02UL], @"fingerprint", nil],
nil];
dispatch_once(&onceToken, ^{
serverPublicKeys = @[
[[MTDatacenterAuthPublicKey alloc] initWithPublicKey:@"-----BEGIN RSA PUBLIC KEY-----\n"
"MIIBCgKCAQEAxq7aeLAqJR20tkQQMfRn+ocfrtMlJsQ2Uksfs7Xcoo77jAid0bRt\n"
"ksiVmT2HEIJUlRxfABoPBV8wY9zRTUMaMA654pUX41mhyVN+XoerGxFvrs9dF1Ru\n"
"vCHbI02dM2ppPvyytvvMoefRoL5BTcpAihFgm5xCaakgsJ/tH5oVl74CdhQw8J5L\n"
"xI/K++KJBUyZ26Uba1632cOiq05JBUW0Z2vWIOk4BLysk7+U9z+SxynKiZR3/xdi\n"
"XvFKk01R3BHV+GUKM2RYazpS/P8v7eyKhAbKxOdRcFpHLlVwfjyM1VlDQrEZxsMp\n"
"NTLYXb6Sce1Uov0YtNx5wEowlREH1WOTlwIDAQAB\n"
"-----END RSA PUBLIC KEY-----" usesModernPaddingScheme:false],
[[MTDatacenterAuthPublicKey alloc] initWithPublicKey:@"-----BEGIN RSA PUBLIC KEY-----\n"
"MIIBCgKCAQEAsQZnSWVZNfClk29RcDTJQ76n8zZaiTGuUsi8sUhW8AS4PSbPKDm+\n"
"DyJgdHDWdIF3HBzl7DHeFrILuqTs0vfS7Pa2NW8nUBwiaYQmPtwEa4n7bTmBVGsB\n"
"1700/tz8wQWOLUlL2nMv+BPlDhxq4kmJCyJfgrIrHlX8sGPcPA4Y6Rwo0MSqYn3s\n"
"g1Pu5gOKlaT9HKmE6wn5Sut6IiBjWozrRQ6n5h2RXNtO7O2qCDqjgB2vBxhV7B+z\n"
"hRbLbCmW0tYMDsvPpX5M8fsO05svN+lKtCAuz1leFns8piZpptpSCFn7bWxiA9/f\n"
"x5x17D7pfah3Sy2pA+NDXyzSlGcKdaUmwQIDAQAB\n"
"-----END RSA PUBLIC KEY-----" usesModernPaddingScheme:false],
[[MTDatacenterAuthPublicKey alloc] initWithPublicKey:@"-----BEGIN RSA PUBLIC KEY-----\n"
"MIIBCgKCAQEAwVACPi9w23mF3tBkdZz+zwrzKOaaQdr01vAbU4E1pvkfj4sqDsm6\n"
"lyDONS789sVoD/xCS9Y0hkkC3gtL1tSfTlgCMOOul9lcixlEKzwKENj1Yz/s7daS\n"
"an9tqw3bfUV/nqgbhGX81v/+7RFAEd+RwFnK7a+XYl9sluzHRyVVaTTveB2GazTw\n"
"Efzk2DWgkBluml8OREmvfraX3bkHZJTKX4EQSjBbbdJ2ZXIsRrYOXfaA+xayEGB+\n"
"8hdlLmAjbCVfaigxX0CDqWeR1yFL9kwd9P0NsZRPsmoqVwMbMu7mStFai6aIhc3n\n"
"Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB\n"
"-----END RSA PUBLIC KEY-----" usesModernPaddingScheme:false],
[[MTDatacenterAuthPublicKey alloc] initWithPublicKey:@"-----BEGIN RSA PUBLIC KEY-----\n"
"MIIBCgKCAQEAwqjFW0pi4reKGbkc9pK83Eunwj/k0G8ZTioMMPbZmW99GivMibwa\n"
"xDM9RDWabEMyUtGoQC2ZcDeLWRK3W8jMP6dnEKAlvLkDLfC4fXYHzFO5KHEqF06i\n"
"qAqBdmI1iBGdQv/OQCBcbXIWCGDY2AsiqLhlGQfPOI7/vvKc188rTriocgUtoTUc\n"
"/n/sIUzkgwTqRyvWYynWARWzQg0I9olLBBC2q5RQJJlnYXZwyTL3y9tdb7zOHkks\n"
"WV9IMQmZmyZh/N7sMbGWQpt4NMchGpPGeJ2e5gHBjDnlIf2p1yZOYeUYrdbwcS0t\n"
"UiggS4UeE8TzIuXFQxw7fzEIlmhIaq3FnwIDAQAB\n"
"-----END RSA PUBLIC KEY-----" usesModernPaddingScheme:false],
[[MTDatacenterAuthPublicKey alloc] initWithPublicKey:@"-----BEGIN RSA PUBLIC KEY-----\n"
"MIIBCgKCAQEAruw2yP/BCcsJliRoW5eBVBVle9dtjJw+OYED160Wybum9SXtBBLX\n"
"riwt4rROd9csv0t0OHCaTmRqBcQ0J8fxhN6/cpR1GWgOZRUAiQxoMnlt0R93LCX/\n"
"j1dnVa/gVbCjdSxpbrfY2g2L4frzjJvdl84Kd9ORYjDEAyFnEA7dD556OptgLQQ2\n"
"e2iVNq8NZLYTzLp5YpOdO1doK+ttrltggTCy5SrKeLoCPPbOgGsdxJxyz5KKcZnS\n"
"Lj16yE5HvJQn0CNpRdENvRUXe6tBP78O39oJ8BTHp9oIjd6XWXAsp2CvK45Ol8wF\n"
"XGF710w9lwCGNbmNxNYhtIkdqfsEcwR5JwIDAQAB\n"
"-----END RSA PUBLIC KEY-----" usesModernPaddingScheme:false],
[[MTDatacenterAuthPublicKey alloc] initWithPublicKey:@"-----BEGIN RSA PUBLIC KEY-----\n"
"MIIBCgKCAQEAvfLHfYH2r9R70w8prHblWt/nDkh+XkgpflqQVcnAfSuTtO05lNPs\n"
"pQmL8Y2XjVT4t8cT6xAkdgfmmvnvRPOOKPi0OfJXoRVylFzAQG/j83u5K3kRLbae\n"
"7fLccVhKZhY46lvsueI1hQdLgNV9n1cQ3TDS2pQOCtovG4eDl9wacrXOJTG2990V\n"
"jgnIKNA0UMoP+KF03qzryqIt3oTvZq03DyWdGK+AZjgBLaDKSnC6qD2cFY81UryR\n"
"WOab8zKkWAnhw2kFpcqhI0jdV5QaSCExvnsjVaX0Y1N0870931/5Jb9ICe4nweZ9\n"
"kSDF/gip3kWLG0o8XQpChDfyvsqB9OLV/wIDAQAB\n"
"-----END RSA PUBLIC KEY-----" usesModernPaddingScheme:false],
[[MTDatacenterAuthPublicKey alloc] initWithPublicKey:@"-----BEGIN RSA PUBLIC KEY-----\n"
"MIIBCgKCAQEAs/ditzm+mPND6xkhzwFIz6J/968CtkcSE/7Z2qAJiXbmZ3UDJPGr\n"
"zqTDHkO30R8VeRM/Kz2f4nR05GIFiITl4bEjvpy7xqRDspJcCFIOcyXm8abVDhF+\n"
"th6knSU0yLtNKuQVP6voMrnt9MV1X92LGZQLgdHZbPQz0Z5qIpaKhdyA8DEvWWvS\n"
"Uwwc+yi1/gGaybwlzZwqXYoPOhwMebzKUk0xW14htcJrRrq+PXXQbRzTMynseCoP\n"
"Ioke0dtCodbA3qQxQovE16q9zz4Otv2k4j63cz53J+mhkVWAeWxVGI0lltJmWtEY\n"
"K6er8VqqWot3nqmWMXogrgRLggv/NbbooQIDAQAB\n"
"-----END RSA PUBLIC KEY-----" usesModernPaddingScheme:false],
[[MTDatacenterAuthPublicKey alloc] initWithPublicKey:@"-----BEGIN RSA PUBLIC KEY-----\n"
"MIIBCgKCAQEAvmpxVY7ld/8DAjz6F6q05shjg8/4p6047bn6/m8yPy1RBsvIyvuD\n"
"uGnP/RzPEhzXQ9UJ5Ynmh2XJZgHoE9xbnfxL5BXHplJhMtADXKM9bWB11PU1Eioc\n"
"3+AXBB8QiNFBn2XI5UkO5hPhbb9mJpjA9Uhw8EdfqJP8QetVsI/xrCEbwEXe0xvi\n"
"fRLJbY08/Gp66KpQvy7g8w7VB8wlgePexW3pT13Ap6vuC+mQuJPyiHvSxjEKHgqe\n"
"Pji9NP3tJUFQjcECqcm0yV7/2d0t/pbCm+ZH1sadZspQCEPPrtbkQBlvHb4OLiIW\n"
"PGHKSMeRFvp3IWcmdJqXahxLCUS1Eh6MAQIDAQAB\n"
"-----END RSA PUBLIC KEY-----" usesModernPaddingScheme:false],
[[MTDatacenterAuthPublicKey alloc] initWithPublicKey:@"-----BEGIN RSA PUBLIC KEY-----\n"
"MIIBCgKCAQEAr4v4wxMDXIaMOh8bayF/NyoYdpcysn5EbjTIOZC0RkgzsRj3SGlu\n"
"52QSz+ysO41dQAjpFLgxPVJoOlxXokaOq827IfW0bGCm0doT5hxtedu9UCQKbE8j\n"
"lDOk+kWMXHPZFJKWRgKgTu9hcB3y3Vk+JFfLpq3d5ZB48B4bcwrRQnzkx5GhWOFX\n"
"x73ZgjO93eoQ2b/lDyXxK4B4IS+hZhjzezPZTI5upTRbs5ljlApsddsHrKk6jJNj\n"
"8Ygs/ps8e6ct82jLXbnndC9s8HjEvDvBPH9IPjv5JUlmHMBFZ5vFQIfbpo0u0+1P\n"
"n6bkEi5o7/ifoyVv2pAZTRwppTz0EuXD8QIDAQAB\n"
"-----END RSA PUBLIC KEY-----" usesModernPaddingScheme:false],
[[MTDatacenterAuthPublicKey alloc] initWithPublicKey:@"-----BEGIN RSA PUBLIC KEY-----\n"
"MIIBCgKCAQEAyMEdY1aR+sCR3ZSJrtztKTKqigvO/vBfqACJLZtS7QMgCGXJ6XIR\n"
"yy7mx66W0/sOFa7/1mAZtEoIokDP3ShoqF4fVNb6XeqgQfaUHd8wJpDWHcR2OFwv\n"
"plUUI1PLTktZ9uW2WE23b+ixNwJjJGwBDJPQEQFBE+vfmH0JP503wr5INS1poWg/\n"
"j25sIWeYPHYeOrFp/eXaqhISP6G+q2IeTaWTXpwZj4LzXq5YOpk4bYEQ6mvRq7D1\n"
"aHWfYmlEGepfaYR8Q0YqvvhYtMte3ITnuSJs171+GDqpdKcSwHnd6FudwGO4pcCO\n"
"j4WcDuXc2CTHgH8gFTNhp/Y8/SpDOhvn9QIDAQAB\n"
"-----END RSA PUBLIC KEY-----" usesModernPaddingScheme:true]
];
});
return serverPublicKeys;
}
static NSDictionary *selectPublicKey(NSArray *fingerprints, NSArray<NSDictionary *> *publicKeys)
{
for (NSNumber *nFingerprint in fingerprints)
{
for (NSDictionary *keyDesc in publicKeys)
{
uint64_t keyFingerprint = [[keyDesc objectForKey:@"fingerprint"] unsignedLongLongValue];
static MTDatacenterAuthPublicKey *selectPublicKey(id<EncryptionProvider> encryptionProvider, NSArray<NSNumber *> *fingerprints, NSArray<MTDatacenterAuthPublicKey *> *publicKeys, bool onlyModernPadding) {
for (NSNumber *nFingerprint in fingerprints) {
for (MTDatacenterAuthPublicKey *key in publicKeys) {
if (onlyModernPadding) {
if (!key.usesModernPaddingScheme) {
continue;
}
}
uint64_t keyFingerprint = [key fingerprintWithEncryptionProvider:encryptionProvider];
if ([nFingerprint unsignedLongLongValue] == keyFingerprint)
return keyDesc;
if ([nFingerprint unsignedLongLongValue] == keyFingerprint) {
return key;
}
}
}
@ -150,7 +185,7 @@ typedef enum {
MTDatacenterAuthKey *_authKey;
NSData *_encryptedClientData;
NSArray<NSDictionary *> *_publicKeys;
NSArray<MTDatacenterAuthPublicKey *> *_publicKeys;
}
@end
@ -168,6 +203,17 @@ typedef enum {
return self;
}
- (NSArray<MTDatacenterAuthPublicKey *> *)convertPublicKeysFromDictionaries:(NSArray<NSDictionary *> *)list {
NSMutableArray<MTDatacenterAuthPublicKey *> *cdnKeys = [[NSMutableArray alloc] init];
for (NSDictionary *dict in list) {
NSString *key = dict[@"key"];
if ([key isKindOfClass:[NSString class]]) {
[cdnKeys addObject:[[MTDatacenterAuthPublicKey alloc] initWithPublicKey:key usesModernPaddingScheme:false]];
}
}
return cdnKeys;
}
- (void)reset:(MTProto *)mtProto
{
_currentStageMessageId = 0;
@ -187,8 +233,8 @@ typedef enum {
_encryptedClientData = nil;
if (mtProto.cdn) {
_publicKeys = [mtProto.context publicKeysForDatacenterWithId:mtProto.datacenterId];
if (_publicKeys == nil) {
_publicKeys = [self convertPublicKeysFromDictionaries:[mtProto.context publicKeysForDatacenterWithId:mtProto.datacenterId]];
if (_publicKeys.count == 0) {
_stage = MTDatacenterAuthStageWaitingForPublicKeys;
[mtProto.context publicKeysForDatacenterWithIdRequired:mtProto.datacenterId];
} else {
@ -211,7 +257,7 @@ typedef enum {
- (void)mtProtoPublicKeysUpdated:(MTProto *)mtProto datacenterId:(NSInteger)datacenterId publicKeys:(NSArray<NSDictionary *> *)publicKeys {
if (_stage == MTDatacenterAuthStageWaitingForPublicKeys) {
if (mtProto.datacenterId == datacenterId) {
_publicKeys = publicKeys;
_publicKeys = [self convertPublicKeysFromDictionaries:publicKeys];
if (_publicKeys != nil && _publicKeys.count != 0) {
_stage = MTDatacenterAuthStagePQ;
[mtProto requestTransportTransaction];
@ -238,7 +284,7 @@ typedef enum {
}
MTBuffer *reqPqBuffer = [[MTBuffer alloc] init];
[reqPqBuffer appendInt32:(int32_t)0x60469778];
[reqPqBuffer appendInt32:(int32_t)0xbe7e8ef1];
[reqPqBuffer appendBytes:_nonce.bytes length:_nonce.length];
NSString *messageDescription = [NSString stringWithFormat:@"reqPq nonce:%@", _nonce];
@ -306,6 +352,178 @@ typedef enum {
return nil;
}
static NSData *aesCbcEncrypt(NSData *data, NSData *key, NSData *iv) {
size_t keyLength = kCCKeySizeAES256;
if (key.length != keyLength) {
return nil;
}
if (iv.length != 16) {
return nil;
}
if (data.length % 16 != 0) {
return nil;
}
NSMutableData *outData = [[NSMutableData alloc] initWithLength:data.length];
CCOperation operation = kCCEncrypt;
CCAlgorithm algoritm = kCCAlgorithmAES128;
CCOptions options = 0; // No padding
size_t outDataActualSize = 0;
int status = CCCrypt(
operation,
algoritm,
options,
key.bytes,
keyLength,
iv.bytes,
data.bytes,
data.length,
outData.mutableBytes,
outData.length,
&outDataActualSize
);
if (status != kCCSuccess) {
return nil;
}
if (outDataActualSize != data.length) {
return nil;
}
return outData;
}
static NSData *encryptRSALegacy(id<EncryptionProvider> encryptionProvider, NSData *pqInnerData, NSString *publicKey) {
NSMutableData *dataWithHash = [[NSMutableData alloc] init];
[dataWithHash appendData:MTSha1(pqInnerData)];
[dataWithHash appendData:pqInnerData];
while (dataWithHash.length < 255) {
uint8_t random = 0;
arc4random_buf(&random, 1);
[dataWithHash appendBytes:&random length:1];
}
NSData *encryptedData = MTRsaEncrypt(encryptionProvider, publicKey, dataWithHash);
if (encryptedData.length < 256) {
NSMutableData *newEncryptedData = [[NSMutableData alloc] init];
for (int i = 0; i < 256 - (int)encryptedData.length; i++)
{
uint8_t random = 0;
arc4random_buf(&random, 1);
[newEncryptedData appendBytes:&random length:1];
}
[newEncryptedData appendData:encryptedData];
encryptedData = newEncryptedData;
}
return encryptedData;
}
static NSData *encryptRSAModernPadding(id<EncryptionProvider> encryptionProvider, NSData *pqInnerData, NSString *publicKey) {
NSMutableData *dataWithPadding = [[NSMutableData alloc] init];
[dataWithPadding appendData:pqInnerData];
if (dataWithPadding.length > 176) {
return nil;
}
if (dataWithPadding.length != 176) {
int originalLength = (int)dataWithPadding.length;
int numPaddingBytes = 176 - originalLength;
[dataWithPadding setLength:176];
int randomResult = SecRandomCopyBytes(kSecRandomDefault, numPaddingBytes, ((uint8_t *)dataWithPadding.mutableBytes) + originalLength);
if (randomResult != errSecSuccess) {
return nil;
}
}
NSMutableData *dataWithHash = [[NSMutableData alloc] init];
[dataWithHash appendData:dataWithPadding];
[dataWithHash appendData:MTSha256(dataWithPadding)];
if (dataWithHash.length != 208) {
return nil;
}
while (true) {
int randomResult = 0;
NSMutableData *tempKey = [[NSMutableData alloc] initWithLength:32];
randomResult = SecRandomCopyBytes(kSecRandomDefault, tempKey.length, tempKey.mutableBytes);
if (randomResult != errSecSuccess) {
return nil;
}
NSMutableData *tempIv = [[NSMutableData alloc] initWithLength:16];
randomResult = SecRandomCopyBytes(kSecRandomDefault, tempIv.length, tempIv.mutableBytes);
if (randomResult != errSecSuccess) {
return nil;
}
NSData *aesEncrypted = aesCbcEncrypt(dataWithHash, tempKey, tempIv);
if (aesEncrypted == nil) {
return nil;
}
NSMutableData *tempIvPlusAesEncrypted = [[NSMutableData alloc] init];
[tempIvPlusAesEncrypted appendData:tempIv];
[tempIvPlusAesEncrypted appendData:aesEncrypted];
NSData *shaTempIvPlusAesEncrypted = MTSha256(tempIvPlusAesEncrypted);
NSMutableData *tempKeyXor = [[NSMutableData alloc] initWithLength:tempKey.length];
if (tempKeyXor.length != shaTempIvPlusAesEncrypted.length) {
return nil;
}
for (NSUInteger i = 0; i < tempKey.length; i++) {
((uint8_t *)tempKeyXor.mutableBytes)[i] = ((uint8_t *)tempKey.bytes)[i] ^ ((uint8_t *)shaTempIvPlusAesEncrypted.bytes)[i];
}
NSMutableData *keyAesEncrypted = [[NSMutableData alloc] init];
[keyAesEncrypted appendData:tempKeyXor];
[keyAesEncrypted appendData:tempIv];
[keyAesEncrypted appendData:aesEncrypted];
if (keyAesEncrypted.length != 256) {
return nil;
}
id<MTBignumContext> bignumContext = [encryptionProvider createBignumContext];
if (bignumContext == nil) {
return nil;
}
id<MTRsaPublicKey> rsaPublicKey = [encryptionProvider parseRSAPublicKey:publicKey];
if (rsaPublicKey == nil) {
return nil;
}
id<MTBignum> rsaModule = [bignumContext rsaGetN:rsaPublicKey];
if (rsaModule == nil) {
return nil;
}
id<MTBignum> bignumKeyAesEncrypted = [bignumContext create];
if (bignumKeyAesEncrypted == nil) {
return nil;
}
[bignumContext assignBinTo:bignumKeyAesEncrypted value:keyAesEncrypted];
int compareResult = [bignumContext compare:rsaModule with:bignumKeyAesEncrypted];
if (compareResult == -1) {
continue;
}
NSData *encryptedData = [encryptionProvider rsaEncryptWithPublicKey:publicKey data:keyAesEncrypted];
NSMutableData *paddedEncryptedData = [[NSMutableData alloc] init];
[paddedEncryptedData appendData:encryptedData];
while (paddedEncryptedData.length < 256) {
uint8_t zero = 0;
[paddedEncryptedData replaceBytesInRange:NSMakeRange(0, 0) withBytes:&zero];
}
if (paddedEncryptedData.length != 256) {
return nil;
}
return paddedEncryptedData;
}
}
- (void)mtProto:(MTProto *)mtProto receivedMessage:(MTIncomingMessage *)message authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector
{
if (_stage == MTDatacenterAuthStagePQ && [message.body isKindOfClass:[MTResPqMessage class]])
@ -314,10 +532,13 @@ typedef enum {
if ([_nonce isEqualToData:resPqMessage.nonce])
{
NSDictionary *publicKey = selectPublicKey(resPqMessage.serverPublicKeyFingerprints, _publicKeys);
MTDatacenterAuthPublicKey *publicKey = selectPublicKey(_encryptionProvider, resPqMessage.serverPublicKeyFingerprints, _publicKeys, true);
if (publicKey == nil) {
publicKey = selectPublicKey(mtProto.context.encryptionProvider, resPqMessage.serverPublicKeyFingerprints, _publicKeys, false);
}
if (publicKey == nil && mtProto.cdn && resPqMessage.serverPublicKeyFingerprints.count == 1 && _publicKeys.count == 1) {
publicKey = @{@"key": _publicKeys[0][@"key"], @"fingerprint": resPqMessage.serverPublicKeyFingerprints[0]};
publicKey = _publicKeys[0];
}
if (publicKey == nil)
@ -367,7 +588,7 @@ typedef enum {
} while (q > 0);
_dhQ = qBytes;
_dhPublicKeyFingerprint = [[publicKey objectForKey:@"fingerprint"] longLongValue];
_dhPublicKeyFingerprint = [publicKey fingerprintWithEncryptionProvider:_encryptionProvider];
uint8_t nonceBytes[32];
__unused int result = SecRandomCopyBytes(kSecRandomDefault, 32, nonceBytes);
@ -390,37 +611,17 @@ typedef enum {
[innerDataBuffer appendInt32:mtProto.context.tempKeyExpiration];
NSData *innerDataBytes = innerDataBuffer.data;
NSMutableData *dataWithHash = [[NSMutableData alloc] init];
[dataWithHash appendData:MTSha1(innerDataBytes)];
[dataWithHash appendData:innerDataBytes];
while (dataWithHash.length < 255)
{
uint8_t random = 0;
arc4random_buf(&random, 1);
[dataWithHash appendBytes:&random length:1];
NSData *encryptedData = nil;
if (publicKey.usesModernPaddingScheme) {
encryptedData = encryptRSAModernPadding(_encryptionProvider, innerDataBytes, publicKey.publicKey);
} else {
encryptedData = encryptRSALegacy(_encryptionProvider, innerDataBytes, publicKey.publicKey);
}
NSData *encryptedData = MTRsaEncrypt(_encryptionProvider, [publicKey objectForKey:@"key"], dataWithHash);
if (MTLogEnabled()) {
MTLog(@"[MTDatacenterAuthMessageService#%p encryptedData length %d dataWithHash length %d]", self, (int)encryptedData.length, (int)dataWithHash.length);
MTLog(@"[MTDatacenterAuthMessageService#%p encryptedData length %d]", self, (int)encryptedData.length);
}
if (encryptedData.length < 256)
{
NSMutableData *newEncryptedData = [[NSMutableData alloc] init];
for (int i = 0; i < 256 - (int)encryptedData.length; i++)
{
uint8_t random = 0;
arc4random_buf(&random, 1);
[newEncryptedData appendBytes:&random length:1];
}
[newEncryptedData appendData:encryptedData];
encryptedData = newEncryptedData;
}
#if DEBUG
assert(encryptedData.length == 256);
#endif
_dhEncryptedData = encryptedData;
} else {
MTBuffer *innerDataBuffer = [[MTBuffer alloc] init];
@ -433,42 +634,30 @@ typedef enum {
[innerDataBuffer appendBytes:_newNonce.bytes length:_newNonce.length];
NSData *innerDataBytes = innerDataBuffer.data;
NSMutableData *dataWithHash = [[NSMutableData alloc] init];
[dataWithHash appendData:MTSha1(innerDataBytes)];
[dataWithHash appendData:innerDataBytes];
while (dataWithHash.length < 255)
{
uint8_t random = 0;
arc4random_buf(&random, 1);
[dataWithHash appendBytes:&random length:1];
}
NSData *encryptedData = MTRsaEncrypt(_encryptionProvider, [publicKey objectForKey:@"key"], dataWithHash);
if (MTLogEnabled()) {
MTLog(@"[MTDatacenterAuthMessageService#%p encryptedData length %d dataWithHash length %d]", self, (int)encryptedData.length, (int)dataWithHash.length);
}
if (encryptedData.length < 256)
{
NSMutableData *newEncryptedData = [[NSMutableData alloc] init];
for (int i = 0; i < 256 - (int)encryptedData.length; i++)
{
uint8_t random = 0;
arc4random_buf(&random, 1);
[newEncryptedData appendBytes:&random length:1];
}
[newEncryptedData appendData:encryptedData];
encryptedData = newEncryptedData;
NSData *encryptedData = nil;
if (publicKey.usesModernPaddingScheme) {
encryptedData = encryptRSAModernPadding(_encryptionProvider, innerDataBytes, publicKey.publicKey);
} else {
encryptedData = encryptRSALegacy(_encryptionProvider, innerDataBytes, publicKey.publicKey);
}
_dhEncryptedData = encryptedData;
}
_stage = MTDatacenterAuthStageReqDH;
_currentStageMessageId = 0;
_currentStageMessageSeqNo = 0;
_currentStageTransactionId = nil;
[mtProto requestTransportTransaction];
if (_dhEncryptedData == nil) {
_stage = MTDatacenterAuthStagePQ;
_currentStageMessageId = 0;
_currentStageMessageSeqNo = 0;
_currentStageTransactionId = nil;
[mtProto requestTransportTransaction];
} else {
_stage = MTDatacenterAuthStageReqDH;
_currentStageMessageId = 0;
_currentStageMessageSeqNo = 0;
_currentStageTransactionId = nil;
[mtProto requestTransportTransaction];
}
}
}
}

View File

@ -16,7 +16,14 @@
}
- (NSString *)description {
return [NSString stringWithFormat:@"res_pq nonce:%@ serverNonce:%@ pq:%@ fingerprints:%@", _nonce, _serverNonce, _pq, _serverPublicKeyFingerprints];
NSMutableString *fingerprintsString = [[NSMutableString alloc] init];
for (NSNumber *value in _serverPublicKeyFingerprints) {
if (fingerprintsString.length != 0) {
[fingerprintsString appendString:@"\n"];
}
[fingerprintsString appendFormat:@"%llx", [value longLongValue]];
}
return [NSString stringWithFormat:@"res_pq nonce:%@ serverNonce:%@ pq:%@ fingerprints:%@", _nonce, _serverNonce, _pq, fingerprintsString];
}
@end