forked from TelegramMessenger/Telegram-iOS
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathAccountData.swift
65 lines (54 loc) · 2.39 KB
/
AccountData.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
import Foundation
import CommonCrypto
private func sha256Digest(_ data: Data) -> Data {
let length = data.count
return data.withUnsafeBytes { (bytes: UnsafePointer<UInt8>) -> Data in
var result = Data(count: Int(CC_SHA256_DIGEST_LENGTH))
result.withUnsafeMutableBytes { (destBytes: UnsafeMutablePointer<UInt8>) -> Void in
CC_SHA256(bytes, UInt32(length), destBytes)
}
return result
}
}
func decryptedNotificationPayload(accounts: [StoredAccountInfo], data: Data) -> (StoredAccountInfo, [AnyHashable: Any])? {
if data.count < 8 + 16 {
return nil
}
for account in accounts {
let notificationKey = account.notificationKey
if data.subdata(in: 0 ..< 8) != notificationKey.id {
continue
}
let x = 8
let msgKey = data.subdata(in: 8 ..< (8 + 16))
let rawData = data.subdata(in: (8 + 16) ..< data.count)
let sha256_a = sha256Digest(msgKey + notificationKey.data.subdata(in: x ..< (x + 36)))
let sha256_b = sha256Digest(notificationKey.data.subdata(in: (40 + x) ..< (40 + x + 36)) + msgKey)
let aesKey = sha256_a.subdata(in: 0 ..< 8) + sha256_b.subdata(in: 8 ..< (8 + 16)) + sha256_a.subdata(in: 24 ..< (24 + 8))
let aesIv = sha256_b.subdata(in: 0 ..< 8) + sha256_a.subdata(in: 8 ..< (8 + 16)) + sha256_b.subdata(in: 24 ..< (24 + 8))
guard let data = MTAesDecrypt(rawData, aesKey, aesIv), data.count > 4 else {
return nil
}
var dataLength: Int32 = 0
data.withUnsafeBytes { (bytes: UnsafePointer<Int8>) -> Void in
memcpy(&dataLength, bytes, 4)
}
if dataLength < 0 || dataLength > data.count - 4 {
return nil
}
let checkMsgKeyLarge = sha256Digest(notificationKey.data.subdata(in: (88 + x) ..< (88 + x + 32)) + data)
let checkMsgKey = checkMsgKeyLarge.subdata(in: 8 ..< (8 + 16))
if checkMsgKey != msgKey {
return nil
}
let contentData = data.subdata(in: 4 ..< (4 + Int(dataLength)))
guard let result = try? JSONSerialization.jsonObject(with: contentData, options: []) else {
return nil
}
guard let dict = result as? [AnyHashable: Any] else {
return nil
}
return (account, dict)
}
return nil
}