diff --git a/submodules/MtProtoKit/Sources/MTContext.m b/submodules/MtProtoKit/Sources/MTContext.m index b394ac923c..bde013a54e 100644 --- a/submodules/MtProtoKit/Sources/MTContext.m +++ b/submodules/MtProtoKit/Sources/MTContext.m @@ -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 *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"]; diff --git a/submodules/MtProtoKit/Sources/MTDatacenterAuthMessageService.m b/submodules/MtProtoKit/Sources/MTDatacenterAuthMessageService.m index da1ca4e98a..6f78dbf3a2 100644 --- a/submodules/MtProtoKit/Sources/MTDatacenterAuthMessageService.m +++ b/submodules/MtProtoKit/Sources/MTDatacenterAuthMessageService.m @@ -13,6 +13,7 @@ #import #import "MTBuffer.h" #import +#import #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 { + return MTRsaFingerprint(encryptionProvider, _publicKey); +} + +@end + +static NSArray *defaultPublicKeys() { + static NSArray *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 *publicKeys) -{ - for (NSNumber *nFingerprint in fingerprints) - { - for (NSDictionary *keyDesc in publicKeys) - { - uint64_t keyFingerprint = [[keyDesc objectForKey:@"fingerprint"] unsignedLongLongValue]; +static MTDatacenterAuthPublicKey *selectPublicKey(id encryptionProvider, NSArray *fingerprints, NSArray *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 *_publicKeys; + NSArray *_publicKeys; } @end @@ -168,6 +203,17 @@ typedef enum { return self; } +- (NSArray *)convertPublicKeysFromDictionaries:(NSArray *)list { + NSMutableArray *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 *)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, 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, 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 bignumContext = [encryptionProvider createBignumContext]; + if (bignumContext == nil) { + return nil; + } + id rsaPublicKey = [encryptionProvider parseRSAPublicKey:publicKey]; + if (rsaPublicKey == nil) { + return nil; + } + id rsaModule = [bignumContext rsaGetN:rsaPublicKey]; + if (rsaModule == nil) { + return nil; + } + id 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]; + } } } } diff --git a/submodules/MtProtoKit/Sources/MTResPqMessage.m b/submodules/MtProtoKit/Sources/MTResPqMessage.m index 6156721256..2aa73435cd 100644 --- a/submodules/MtProtoKit/Sources/MTResPqMessage.m +++ b/submodules/MtProtoKit/Sources/MTResPqMessage.m @@ -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