@mtcute/core 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cjs/base-client.js +4 -1
- package/cjs/base-client.js.map +1 -1
- package/cjs/network/auth-key.d.ts +3 -3
- package/cjs/network/auth-key.js +12 -12
- package/cjs/network/auth-key.js.map +1 -1
- package/cjs/network/auth-key.test.d.ts +1 -0
- package/cjs/network/auth-key.test.js +111 -0
- package/cjs/network/auth-key.test.js.map +1 -0
- package/cjs/network/authorization.js +62 -57
- package/cjs/network/authorization.js.map +1 -1
- package/cjs/network/config-manager.js +2 -1
- package/cjs/network/config-manager.js.map +1 -1
- package/cjs/network/config-manager.test.d.ts +1 -0
- package/cjs/network/config-manager.test.js +170 -0
- package/cjs/network/config-manager.test.js.map +1 -0
- package/cjs/network/mtproto-session.d.ts +2 -2
- package/cjs/network/mtproto-session.js +2 -2
- package/cjs/network/mtproto-session.js.map +1 -1
- package/cjs/network/multi-session-connection.d.ts +1 -1
- package/cjs/network/multi-session-connection.js +2 -2
- package/cjs/network/multi-session-connection.js.map +1 -1
- package/cjs/network/network-manager.d.ts +1 -0
- package/cjs/network/network-manager.js +21 -27
- package/cjs/network/network-manager.js.map +1 -1
- package/cjs/network/persistent-connection.test.d.ts +1 -0
- package/cjs/network/persistent-connection.test.js +157 -0
- package/cjs/network/persistent-connection.test.js.map +1 -0
- package/cjs/network/session-connection.d.ts +2 -1
- package/cjs/network/session-connection.js +51 -37
- package/cjs/network/session-connection.js.map +1 -1
- package/cjs/network/transports/intermediate.d.ts +3 -0
- package/cjs/network/transports/intermediate.js +5 -3
- package/cjs/network/transports/intermediate.js.map +1 -1
- package/cjs/network/transports/intermediate.test.d.ts +1 -0
- package/cjs/network/transports/intermediate.test.js +86 -0
- package/cjs/network/transports/intermediate.test.js.map +1 -0
- package/cjs/network/transports/obfuscated.js +15 -19
- package/cjs/network/transports/obfuscated.js.map +1 -1
- package/cjs/network/transports/obfuscated.test.d.ts +1 -0
- package/cjs/network/transports/obfuscated.test.js +131 -0
- package/cjs/network/transports/obfuscated.test.js.map +1 -0
- package/cjs/network/transports/tcp.js +1 -1
- package/cjs/network/transports/tcp.js.map +1 -1
- package/cjs/network/transports/tcp.test.d.ts +1 -0
- package/cjs/network/transports/tcp.test.js +97 -0
- package/cjs/network/transports/tcp.test.js.map +1 -0
- package/cjs/network/transports/websocket.test.d.ts +1 -0
- package/cjs/network/transports/websocket.test.js +91 -0
- package/cjs/network/transports/websocket.test.js.map +1 -0
- package/cjs/storage/abstract.d.ts +23 -2
- package/cjs/storage/abstract.js.map +1 -1
- package/cjs/storage/json.js +8 -9
- package/cjs/storage/json.js.map +1 -1
- package/cjs/storage/json.test.d.ts +1 -0
- package/cjs/storage/json.test.js +37 -0
- package/cjs/storage/json.test.js.map +1 -0
- package/cjs/storage/localstorage.js +5 -2
- package/cjs/storage/localstorage.js.map +1 -1
- package/cjs/storage/localstorage.test.d.ts +1 -0
- package/cjs/storage/localstorage.test.js +23 -0
- package/cjs/storage/localstorage.test.js.map +1 -0
- package/cjs/storage/memory.d.ts +7 -8
- package/cjs/storage/memory.js +7 -7
- package/cjs/storage/memory.js.map +1 -1
- package/cjs/storage/memory.test.d.ts +1 -0
- package/cjs/storage/memory.test.js +47 -0
- package/cjs/storage/memory.test.js.map +1 -0
- package/cjs/utils/async-lock.test.d.ts +1 -0
- package/cjs/utils/async-lock.test.js +25 -0
- package/cjs/utils/async-lock.test.js.map +1 -0
- package/cjs/utils/bigint-utils.d.ts +18 -11
- package/cjs/utils/bigint-utils.js +148 -47
- package/cjs/utils/bigint-utils.js.map +1 -1
- package/cjs/utils/bigint-utils.test.d.ts +1 -0
- package/cjs/utils/bigint-utils.test.js +150 -0
- package/cjs/utils/bigint-utils.test.js.map +1 -0
- package/cjs/utils/buffer-utils.d.ts +7 -1
- package/cjs/utils/buffer-utils.js +16 -3
- package/cjs/utils/buffer-utils.js.map +1 -1
- package/cjs/utils/buffer-utils.test.d.ts +1 -0
- package/cjs/utils/buffer-utils.test.js +69 -0
- package/cjs/utils/buffer-utils.test.js.map +1 -0
- package/cjs/utils/condition-variable.test.d.ts +1 -0
- package/cjs/utils/condition-variable.test.js +27 -0
- package/cjs/utils/condition-variable.test.js.map +1 -0
- package/cjs/utils/controllable-promise.test.d.ts +1 -0
- package/cjs/utils/controllable-promise.test.js +17 -0
- package/cjs/utils/controllable-promise.test.js.map +1 -0
- package/cjs/utils/crypto/abstract.d.ts +16 -9
- package/cjs/utils/crypto/abstract.js +6 -9
- package/cjs/utils/crypto/abstract.js.map +1 -1
- package/cjs/utils/crypto/factorization.d.ts +2 -1
- package/cjs/utils/crypto/factorization.js +28 -36
- package/cjs/utils/crypto/factorization.js.map +1 -1
- package/cjs/utils/crypto/index.d.ts +4 -0
- package/cjs/utils/crypto/index.js +4 -0
- package/cjs/utils/crypto/index.js.map +1 -1
- package/cjs/utils/crypto/keys.d.ts +2 -2
- package/cjs/utils/crypto/keys.js +4 -4
- package/cjs/utils/crypto/keys.js.map +1 -1
- package/cjs/utils/crypto/keys.test.d.ts +1 -0
- package/cjs/utils/crypto/keys.test.js +40 -0
- package/cjs/utils/crypto/keys.test.js.map +1 -0
- package/cjs/utils/crypto/miller-rabin.d.ts +2 -2
- package/cjs/utils/crypto/miller-rabin.js +20 -22
- package/cjs/utils/crypto/miller-rabin.js.map +1 -1
- package/cjs/utils/crypto/miller-rabin.test.d.ts +1 -0
- package/cjs/utils/crypto/miller-rabin.test.js +60 -0
- package/cjs/utils/crypto/miller-rabin.test.js.map +1 -0
- package/cjs/utils/crypto/mtproto.d.ts +3 -3
- package/cjs/utils/crypto/mtproto.js +12 -12
- package/cjs/utils/crypto/mtproto.js.map +1 -1
- package/cjs/utils/crypto/mtproto.test.d.ts +1 -0
- package/cjs/utils/crypto/mtproto.test.js +47 -0
- package/cjs/utils/crypto/mtproto.test.js.map +1 -0
- package/cjs/utils/crypto/node.d.ts +21 -0
- package/cjs/utils/crypto/node.js +74 -0
- package/cjs/utils/crypto/node.js.map +1 -0
- package/cjs/utils/crypto/node.test.d.ts +1 -0
- package/cjs/utils/crypto/node.test.js +13 -0
- package/cjs/utils/crypto/node.test.js.map +1 -0
- package/cjs/utils/crypto/password.js +22 -33
- package/cjs/utils/crypto/password.js.map +1 -1
- package/cjs/utils/crypto/password.test.d.ts +1 -0
- package/cjs/utils/crypto/password.test.js +95 -0
- package/cjs/utils/crypto/password.test.js.map +1 -0
- package/cjs/utils/crypto/utils.test.d.ts +1 -0
- package/cjs/utils/crypto/utils.test.js +49 -0
- package/cjs/utils/crypto/utils.test.js.map +1 -0
- package/cjs/utils/crypto/wasm.d.ts +22 -0
- package/cjs/utils/crypto/wasm.js +41 -0
- package/cjs/utils/crypto/wasm.js.map +1 -0
- package/cjs/utils/crypto/web.d.ts +11 -0
- package/cjs/utils/crypto/web.js +40 -0
- package/cjs/utils/crypto/web.js.map +1 -0
- package/cjs/utils/crypto/web.test.d.ts +1 -0
- package/cjs/utils/crypto/web.test.js +17 -0
- package/cjs/utils/crypto/web.test.js.map +1 -0
- package/cjs/utils/deque.d.ts +1 -1
- package/cjs/utils/deque.js +9 -3
- package/cjs/utils/deque.js.map +1 -1
- package/cjs/utils/deque.test.d.ts +1 -0
- package/cjs/utils/deque.test.js +128 -0
- package/cjs/utils/deque.test.js.map +1 -0
- package/cjs/utils/function-utils.d.ts +4 -1
- package/cjs/utils/function-utils.js +8 -1
- package/cjs/utils/function-utils.js.map +1 -1
- package/cjs/utils/function-utils.test.d.ts +1 -0
- package/cjs/utils/function-utils.test.js +23 -0
- package/cjs/utils/function-utils.test.js.map +1 -0
- package/cjs/utils/index.d.ts +0 -1
- package/cjs/utils/index.js +0 -1
- package/cjs/utils/index.js.map +1 -1
- package/cjs/utils/linked-list.test.d.ts +1 -0
- package/cjs/utils/linked-list.test.js +36 -0
- package/cjs/utils/linked-list.test.js.map +1 -0
- package/cjs/utils/links/bots.test.d.ts +1 -0
- package/cjs/utils/links/bots.test.js +152 -0
- package/cjs/utils/links/bots.test.js.map +1 -0
- package/cjs/utils/links/chat.test.d.ts +1 -0
- package/cjs/utils/links/chat.test.js +84 -0
- package/cjs/utils/links/chat.test.js.map +1 -0
- package/cjs/utils/links/misc.test.d.ts +1 -0
- package/cjs/utils/links/misc.test.js +153 -0
- package/cjs/utils/links/misc.test.js.map +1 -0
- package/cjs/utils/links/proxy.test.d.ts +1 -0
- package/cjs/utils/links/proxy.test.js +74 -0
- package/cjs/utils/links/proxy.test.js.map +1 -0
- package/cjs/utils/links/user.test.d.ts +1 -0
- package/cjs/utils/links/user.test.js +63 -0
- package/cjs/utils/links/user.test.js.map +1 -0
- package/cjs/utils/logger.d.ts +0 -1
- package/cjs/utils/logger.js +3 -4
- package/cjs/utils/logger.js.map +1 -1
- package/cjs/utils/logger.test.d.ts +1 -0
- package/cjs/utils/logger.test.js +125 -0
- package/cjs/utils/logger.test.js.map +1 -0
- package/cjs/utils/long-utils.test.d.ts +1 -0
- package/cjs/utils/long-utils.test.js +158 -0
- package/cjs/utils/long-utils.test.js.map +1 -0
- package/cjs/utils/lru-map.d.ts +1 -0
- package/cjs/utils/lru-map.js +6 -0
- package/cjs/utils/lru-map.js.map +1 -1
- package/cjs/utils/lru-map.test.d.ts +1 -0
- package/cjs/utils/lru-map.test.js +96 -0
- package/cjs/utils/lru-map.test.js.map +1 -0
- package/cjs/utils/lru-set.test.d.ts +1 -0
- package/cjs/utils/lru-set.test.js +77 -0
- package/cjs/utils/lru-set.test.js.map +1 -0
- package/cjs/utils/peer-utils.js +5 -1
- package/cjs/utils/peer-utils.js.map +1 -1
- package/cjs/utils/peer-utils.test.d.ts +1 -0
- package/cjs/utils/peer-utils.test.js +122 -0
- package/cjs/utils/peer-utils.test.js.map +1 -0
- package/cjs/utils/platform/crypto.js +2 -2
- package/cjs/utils/platform/crypto.js.map +1 -1
- package/cjs/utils/platform/crypto.web.js +2 -2
- package/cjs/utils/platform/crypto.web.js.map +1 -1
- package/cjs/utils/sorted-array.test.d.ts +1 -0
- package/cjs/utils/sorted-array.test.js +66 -0
- package/cjs/utils/sorted-array.test.js.map +1 -0
- package/cjs/utils/string-session.js +4 -2
- package/cjs/utils/string-session.js.map +1 -1
- package/cjs/utils/string-session.test.d.ts +1 -0
- package/cjs/utils/string-session.test.js +106 -0
- package/cjs/utils/string-session.test.js.map +1 -0
- package/cjs/utils/tl-json.test.d.ts +1 -0
- package/cjs/utils/tl-json.test.js +83 -0
- package/cjs/utils/tl-json.test.js.map +1 -0
- package/cjs/utils/type-assertions.test.d.ts +1 -0
- package/cjs/utils/type-assertions.test.js +67 -0
- package/cjs/utils/type-assertions.test.js.map +1 -0
- package/esm/base-client.js +4 -1
- package/esm/base-client.js.map +1 -1
- package/esm/network/auth-key.d.ts +3 -3
- package/esm/network/auth-key.js +13 -13
- package/esm/network/auth-key.js.map +1 -1
- package/esm/network/auth-key.test.d.ts +1 -0
- package/esm/network/auth-key.test.js +106 -0
- package/esm/network/auth-key.test.js.map +1 -0
- package/esm/network/authorization.js +64 -59
- package/esm/network/authorization.js.map +1 -1
- package/esm/network/config-manager.js +2 -1
- package/esm/network/config-manager.js.map +1 -1
- package/esm/network/config-manager.test.d.ts +1 -0
- package/esm/network/config-manager.test.js +168 -0
- package/esm/network/config-manager.test.js.map +1 -0
- package/esm/network/mtproto-session.d.ts +2 -2
- package/esm/network/mtproto-session.js +2 -2
- package/esm/network/mtproto-session.js.map +1 -1
- package/esm/network/multi-session-connection.d.ts +1 -1
- package/esm/network/multi-session-connection.js +2 -2
- package/esm/network/multi-session-connection.js.map +1 -1
- package/esm/network/network-manager.d.ts +1 -0
- package/esm/network/network-manager.js +21 -27
- package/esm/network/network-manager.js.map +1 -1
- package/esm/network/persistent-connection.test.d.ts +1 -0
- package/esm/network/persistent-connection.test.js +155 -0
- package/esm/network/persistent-connection.test.js.map +1 -0
- package/esm/network/session-connection.d.ts +2 -1
- package/esm/network/session-connection.js +53 -39
- package/esm/network/session-connection.js.map +1 -1
- package/esm/network/transports/intermediate.d.ts +3 -0
- package/esm/network/transports/intermediate.js +6 -4
- package/esm/network/transports/intermediate.js.map +1 -1
- package/esm/network/transports/intermediate.test.d.ts +1 -0
- package/esm/network/transports/intermediate.test.js +84 -0
- package/esm/network/transports/intermediate.test.js.map +1 -0
- package/esm/network/transports/obfuscated.js +16 -20
- package/esm/network/transports/obfuscated.js.map +1 -1
- package/esm/network/transports/obfuscated.test.d.ts +1 -0
- package/esm/network/transports/obfuscated.test.js +129 -0
- package/esm/network/transports/obfuscated.test.js.map +1 -0
- package/esm/network/transports/tcp.js +1 -1
- package/esm/network/transports/tcp.js.map +1 -1
- package/esm/network/transports/tcp.test.d.ts +1 -0
- package/esm/network/transports/tcp.test.js +95 -0
- package/esm/network/transports/tcp.test.js.map +1 -0
- package/esm/network/transports/websocket.test.d.ts +1 -0
- package/esm/network/transports/websocket.test.js +89 -0
- package/esm/network/transports/websocket.test.js.map +1 -0
- package/esm/storage/abstract.d.ts +23 -2
- package/esm/storage/abstract.js.map +1 -1
- package/esm/storage/json.js +8 -9
- package/esm/storage/json.js.map +1 -1
- package/esm/storage/json.test.d.ts +1 -0
- package/esm/storage/json.test.js +35 -0
- package/esm/storage/json.test.js.map +1 -0
- package/esm/storage/localstorage.js +5 -2
- package/esm/storage/localstorage.js.map +1 -1
- package/esm/storage/localstorage.test.d.ts +1 -0
- package/esm/storage/localstorage.test.js +21 -0
- package/esm/storage/localstorage.test.js.map +1 -0
- package/esm/storage/memory.d.ts +7 -8
- package/esm/storage/memory.js +7 -7
- package/esm/storage/memory.js.map +1 -1
- package/esm/storage/memory.test.d.ts +1 -0
- package/esm/storage/memory.test.js +45 -0
- package/esm/storage/memory.test.js.map +1 -0
- package/esm/utils/async-lock.test.d.ts +1 -0
- package/esm/utils/async-lock.test.js +23 -0
- package/esm/utils/async-lock.test.js.map +1 -0
- package/esm/utils/bigint-utils.d.ts +18 -11
- package/esm/utils/bigint-utils.js +142 -44
- package/esm/utils/bigint-utils.js.map +1 -1
- package/esm/utils/bigint-utils.test.d.ts +1 -0
- package/esm/utils/bigint-utils.test.js +148 -0
- package/esm/utils/bigint-utils.test.js.map +1 -0
- package/esm/utils/buffer-utils.d.ts +7 -1
- package/esm/utils/buffer-utils.js +14 -1
- package/esm/utils/buffer-utils.js.map +1 -1
- package/esm/utils/buffer-utils.test.d.ts +1 -0
- package/esm/utils/buffer-utils.test.js +67 -0
- package/esm/utils/buffer-utils.test.js.map +1 -0
- package/esm/utils/condition-variable.test.d.ts +1 -0
- package/esm/utils/condition-variable.test.js +25 -0
- package/esm/utils/condition-variable.test.js.map +1 -0
- package/esm/utils/controllable-promise.test.d.ts +1 -0
- package/esm/utils/controllable-promise.test.js +15 -0
- package/esm/utils/controllable-promise.test.js.map +1 -0
- package/esm/utils/crypto/abstract.d.ts +16 -9
- package/esm/utils/crypto/abstract.js +6 -9
- package/esm/utils/crypto/abstract.js.map +1 -1
- package/esm/utils/crypto/factorization.d.ts +2 -1
- package/esm/utils/crypto/factorization.js +29 -34
- package/esm/utils/crypto/factorization.js.map +1 -1
- package/esm/utils/crypto/index.d.ts +4 -0
- package/esm/utils/crypto/index.js +4 -0
- package/esm/utils/crypto/index.js.map +1 -1
- package/esm/utils/crypto/keys.d.ts +2 -2
- package/esm/utils/crypto/keys.js +4 -4
- package/esm/utils/crypto/keys.js.map +1 -1
- package/esm/utils/crypto/keys.test.d.ts +1 -0
- package/esm/utils/crypto/keys.test.js +38 -0
- package/esm/utils/crypto/keys.test.js.map +1 -0
- package/esm/utils/crypto/miller-rabin.d.ts +2 -2
- package/esm/utils/crypto/miller-rabin.js +21 -20
- package/esm/utils/crypto/miller-rabin.js.map +1 -1
- package/esm/utils/crypto/miller-rabin.test.d.ts +1 -0
- package/esm/utils/crypto/miller-rabin.test.js +58 -0
- package/esm/utils/crypto/miller-rabin.test.js.map +1 -0
- package/esm/utils/crypto/mtproto.d.ts +3 -3
- package/esm/utils/crypto/mtproto.js +12 -12
- package/esm/utils/crypto/mtproto.js.map +1 -1
- package/esm/utils/crypto/mtproto.test.d.ts +1 -0
- package/esm/utils/crypto/mtproto.test.js +45 -0
- package/esm/utils/crypto/mtproto.test.js.map +1 -0
- package/esm/utils/crypto/node.d.ts +21 -0
- package/esm/utils/crypto/node.js +69 -0
- package/esm/utils/crypto/node.js.map +1 -0
- package/esm/utils/crypto/node.test.d.ts +1 -0
- package/esm/utils/crypto/node.test.js +11 -0
- package/esm/utils/crypto/node.test.js.map +1 -0
- package/esm/utils/crypto/password.js +24 -32
- package/esm/utils/crypto/password.js.map +1 -1
- package/esm/utils/crypto/password.test.d.ts +1 -0
- package/esm/utils/crypto/password.test.js +90 -0
- package/esm/utils/crypto/password.test.js.map +1 -0
- package/esm/utils/crypto/utils.test.d.ts +1 -0
- package/esm/utils/crypto/utils.test.js +47 -0
- package/esm/utils/crypto/utils.test.js.map +1 -0
- package/esm/utils/crypto/wasm.d.ts +22 -0
- package/esm/utils/crypto/wasm.js +37 -0
- package/esm/utils/crypto/wasm.js.map +1 -0
- package/esm/utils/crypto/web.d.ts +11 -0
- package/esm/utils/crypto/web.js +36 -0
- package/esm/utils/crypto/web.js.map +1 -0
- package/esm/utils/crypto/web.test.d.ts +1 -0
- package/esm/utils/crypto/web.test.js +15 -0
- package/esm/utils/crypto/web.test.js.map +1 -0
- package/esm/utils/deque.d.ts +1 -1
- package/esm/utils/deque.js +9 -3
- package/esm/utils/deque.js.map +1 -1
- package/esm/utils/deque.test.d.ts +1 -0
- package/esm/utils/deque.test.js +126 -0
- package/esm/utils/deque.test.js.map +1 -0
- package/esm/utils/function-utils.d.ts +4 -1
- package/esm/utils/function-utils.js +8 -1
- package/esm/utils/function-utils.js.map +1 -1
- package/esm/utils/function-utils.test.d.ts +1 -0
- package/esm/utils/function-utils.test.js +21 -0
- package/esm/utils/function-utils.test.js.map +1 -0
- package/esm/utils/index.d.ts +0 -1
- package/esm/utils/index.js +0 -1
- package/esm/utils/index.js.map +1 -1
- package/esm/utils/linked-list.test.d.ts +1 -0
- package/esm/utils/linked-list.test.js +34 -0
- package/esm/utils/linked-list.test.js.map +1 -0
- package/esm/utils/links/bots.test.d.ts +1 -0
- package/esm/utils/links/bots.test.js +150 -0
- package/esm/utils/links/bots.test.js.map +1 -0
- package/esm/utils/links/chat.test.d.ts +1 -0
- package/esm/utils/links/chat.test.js +82 -0
- package/esm/utils/links/chat.test.js.map +1 -0
- package/esm/utils/links/misc.test.d.ts +1 -0
- package/esm/utils/links/misc.test.js +151 -0
- package/esm/utils/links/misc.test.js.map +1 -0
- package/esm/utils/links/proxy.test.d.ts +1 -0
- package/esm/utils/links/proxy.test.js +72 -0
- package/esm/utils/links/proxy.test.js.map +1 -0
- package/esm/utils/links/user.test.d.ts +1 -0
- package/esm/utils/links/user.test.js +61 -0
- package/esm/utils/links/user.test.js.map +1 -0
- package/esm/utils/logger.d.ts +0 -1
- package/esm/utils/logger.js +3 -4
- package/esm/utils/logger.js.map +1 -1
- package/esm/utils/logger.test.d.ts +1 -0
- package/esm/utils/logger.test.js +120 -0
- package/esm/utils/logger.test.js.map +1 -0
- package/esm/utils/long-utils.test.d.ts +1 -0
- package/esm/utils/long-utils.test.js +153 -0
- package/esm/utils/long-utils.test.js.map +1 -0
- package/esm/utils/lru-map.d.ts +1 -0
- package/esm/utils/lru-map.js +6 -0
- package/esm/utils/lru-map.js.map +1 -1
- package/esm/utils/lru-map.test.d.ts +1 -0
- package/esm/utils/lru-map.test.js +94 -0
- package/esm/utils/lru-map.test.js.map +1 -0
- package/esm/utils/lru-set.test.d.ts +1 -0
- package/esm/utils/lru-set.test.js +72 -0
- package/esm/utils/lru-set.test.js.map +1 -0
- package/esm/utils/peer-utils.js +5 -1
- package/esm/utils/peer-utils.js.map +1 -1
- package/esm/utils/peer-utils.test.d.ts +1 -0
- package/esm/utils/peer-utils.test.js +117 -0
- package/esm/utils/peer-utils.test.js.map +1 -0
- package/esm/utils/platform/crypto.js +1 -1
- package/esm/utils/platform/crypto.js.map +1 -1
- package/esm/utils/platform/crypto.web.js +2 -2
- package/esm/utils/platform/crypto.web.js.map +1 -1
- package/esm/utils/sorted-array.test.d.ts +1 -0
- package/esm/utils/sorted-array.test.js +64 -0
- package/esm/utils/sorted-array.test.js.map +1 -0
- package/esm/utils/string-session.js +4 -2
- package/esm/utils/string-session.js.map +1 -1
- package/esm/utils/string-session.test.d.ts +1 -0
- package/esm/utils/string-session.test.js +104 -0
- package/esm/utils/string-session.test.js.map +1 -0
- package/esm/utils/tl-json.test.d.ts +1 -0
- package/esm/utils/tl-json.test.js +81 -0
- package/esm/utils/tl-json.test.js.map +1 -0
- package/esm/utils/type-assertions.test.d.ts +1 -0
- package/esm/utils/type-assertions.test.js +65 -0
- package/esm/utils/type-assertions.test.js.map +1 -0
- package/package.json +4 -5
- package/cjs/utils/crypto/common.d.ts +0 -12
- package/cjs/utils/crypto/common.js +0 -54
- package/cjs/utils/crypto/common.js.map +0 -1
- package/cjs/utils/crypto/node-crypto.d.ts +0 -10
- package/cjs/utils/crypto/node-crypto.js +0 -46
- package/cjs/utils/crypto/node-crypto.js.map +0 -1
- package/cjs/utils/crypto/subtle.d.ts +0 -12
- package/cjs/utils/crypto/subtle.js +0 -86
- package/cjs/utils/crypto/subtle.js.map +0 -1
- package/cjs/utils/flood-control.d.ts +0 -14
- package/cjs/utils/flood-control.js +0 -65
- package/cjs/utils/flood-control.js.map +0 -1
- package/cjs/utils/platform/random.d.ts +0 -1
- package/cjs/utils/platform/random.js +0 -7
- package/cjs/utils/platform/random.js.map +0 -1
- package/cjs/utils/platform/random.web.d.ts +0 -1
- package/cjs/utils/platform/random.web.js +0 -10
- package/cjs/utils/platform/random.web.js.map +0 -1
- package/esm/utils/crypto/common.d.ts +0 -12
- package/esm/utils/crypto/common.js +0 -50
- package/esm/utils/crypto/common.js.map +0 -1
- package/esm/utils/crypto/node-crypto.d.ts +0 -10
- package/esm/utils/crypto/node-crypto.js +0 -42
- package/esm/utils/crypto/node-crypto.js.map +0 -1
- package/esm/utils/crypto/subtle.d.ts +0 -12
- package/esm/utils/crypto/subtle.js +0 -59
- package/esm/utils/crypto/subtle.js.map +0 -1
- package/esm/utils/flood-control.d.ts +0 -14
- package/esm/utils/flood-control.js +0 -61
- package/esm/utils/flood-control.js.map +0 -1
- package/esm/utils/platform/random.d.ts +0 -1
- package/esm/utils/platform/random.js +0 -4
- package/esm/utils/platform/random.js.map +0 -1
- package/esm/utils/platform/random.web.d.ts +0 -1
- package/esm/utils/platform/random.web.js +0 -6
- package/esm/utils/platform/random.web.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-key.test.js","sourceRoot":"","sources":["../../../src/network/auth-key.test.ts"],"names":[],"mappings":"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","sourcesContent":["import Long from 'long'\nimport { describe, expect, it, vi } from 'vitest'\n\nimport { defaultTestCryptoProvider } from '@mtcute/test'\nimport {\n hexDecode,\n hexDecodeToBuffer,\n hexEncode,\n TlBinaryReader,\n TlReaderMap,\n utf8Decode,\n utf8EncodeToBuffer,\n} from '@mtcute/tl-runtime'\n\nimport { LogManager } from '../utils/index.js'\nimport { AuthKey } from './auth-key.js'\n\nconst authKey = new Uint8Array(256)\n\nfor (let i = 0; i < 256; i += 32) {\n hexDecode(authKey.subarray(i, i + 32), '98cb29c6ffa89e79da695a54f572e6cb101e81c688b63a4bf73c3622dec230e0')\n}\n\ndescribe('AuthKey', () => {\n async function create() {\n const logger = new LogManager()\n const readerMap: TlReaderMap = {}\n const crypto = await defaultTestCryptoProvider()\n\n const key = new AuthKey(crypto, logger, readerMap)\n key.setup(authKey)\n\n return key\n }\n\n const msgId = Long.fromBits(0xbeef1234, 0x1234beef, true)\n const seqNo = 777\n const serverSalt = Long.fromBits(0xdeadbeef, 0xbeefdead)\n const sessionId = Long.fromBits(0xfeedbeef, 0xbeeffeed)\n\n function writeMessage(body: Uint8Array) {\n const buf = new Uint8Array(16 + body.length)\n const dv = new DataView(buf.buffer)\n\n dv.setInt32(0, msgId.low, true)\n dv.setInt32(4, msgId.high, true)\n dv.setInt32(8, seqNo, true)\n dv.setInt32(12, body.length, true)\n buf.set(body, 16)\n\n return buf\n }\n\n it('should calculate derivatives', async () => {\n const key = await create()\n\n expect(hexEncode(key.key)).toEqual(hexEncode(authKey))\n expect(hexEncode(key.clientSalt)).toEqual('f73c3622dec230e098cb29c6ffa89e79da695a54f572e6cb101e81c688b63a4b')\n expect(hexEncode(key.serverSalt)).toEqual('98cb29c6ffa89e79da695a54f572e6cb101e81c688b63a4bf73c3622dec230e0')\n expect(hexEncode(key.id)).toEqual('40fa5bb7cb56a895')\n })\n\n it('should encrypt a message', async () => {\n const message = writeMessage(utf8EncodeToBuffer('hello, world!!!!'))\n\n const key = await create()\n const msg = key.encryptMessage(message, serverSalt, sessionId)\n\n expect(hexEncode(msg)).toEqual(\n '40fa5bb7cb56a895f6f5a88914892aadf87c68031cc953ba29d68e118021f329' +\n 'be386a620d49f3ad3a50c60dcef3733f214e8cefa3e403c11d193637d4971dc1' +\n '5db7f74b26fd16cb0e8fee30bf7e3f68858fe82927e2cd06',\n )\n })\n\n describe('decrypt', () => {\n async function decrypt(message: Uint8Array) {\n const key = await create()\n\n return new Promise<[Long, number, TlBinaryReader]>((resolve, reject) => {\n // in this method, errors are not thrown but rather logged\n vi.spyOn(key.log, 'warn').mockImplementation((msg, ...fmt) =>\n reject(`${msg} : ${fmt.map((it) => JSON.stringify(it)).join(' ')}`),\n )\n\n key.decryptMessage(message, sessionId, (...args) => resolve(args))\n })\n }\n\n it('should decrypt a message', async () => {\n const message = hexDecodeToBuffer(\n '40fa5bb7cb56a8950c394b884f1529efc42fea22d972fea650a714ce6d2d1bdb' +\n '3d98ff5929b8768c401771a69795f36a7e720dcafac2efbccd0ba368e8a7f48b' +\n '07362cac1a32ffcabe188b51a36cc4d54e1d0633cf9eaf35',\n )\n\n const [decMsgId, decSeqNo, data] = await decrypt(message)\n\n expect(decMsgId).toEqual(msgId)\n expect(decSeqNo).toEqual(seqNo)\n expect(utf8Decode(data.raw(16))).toEqual('hello, world!!!!')\n })\n\n it('should decrypt a message with padding', async () => {\n const message = hexDecodeToBuffer(\n '40fa5bb7cb56a8950c394b884f1529efc42fea22d972fea650a714ce6d2d1bdb' +\n '3d98ff5929b8768c401771a69795f36a7e720dcafac2efbccd0ba368e8a7f48b' +\n '07362cac1a32ffcabe188b51a36cc4d54e1d0633cf9eaf35' +\n 'deadbeef', // some padding (e.g. from padded transport),\n )\n\n const [decMsgId, decSeqNo, data] = await decrypt(message)\n\n expect(decMsgId).toEqual(msgId)\n expect(decSeqNo).toEqual(seqNo)\n expect(utf8Decode(data.raw(16))).toEqual('hello, world!!!!')\n })\n\n it('should ignore messages with invalid message key', async () => {\n const message = hexDecodeToBuffer(\n '40fa5bb7cb56a8950000000000000000000000000000000050a714ce6d2d1bdb' +\n '3d98ff5929b8768c401771a69795f36a7e720dcafac2efbccd0ba368e8a7f48b' +\n '07362cac1a32ffcabe188b51a36cc4d54e1d0633cf9eaf35',\n )\n\n await expect(() => decrypt(message)).rejects.toThrow('message with invalid messageKey')\n })\n\n it('should ignore messages with invalid session_id', async () => {\n const message = hexDecodeToBuffer(\n '40fa5bb7cb56a895a986a7e97f4e90aa2769b5e702c6e86f5e1e82c6ff0c6829' +\n '2521a2ba9704fa37fb341d895cf32662c6cf47ba31cbf27c30d5c03f6c2930f4' +\n '30fd8858b836b73fe32d4a95b8ebcdbc9ca8908f7964c40a',\n )\n\n await expect(() => decrypt(message)).rejects.toThrow('message with invalid sessionId')\n })\n\n it('should ignore messages with invalid length', async () => {\n const messageTooLong = hexDecodeToBuffer(\n '40fa5bb7cb56a8950d19412233dd5d24be697c73274e08fbe515cf65e0c5f70c' +\n 'ad75fd2badc18c9f999f287351144eeb1cfcaa9bea33ef5058999ad96a498306' +\n '08d2859425685a55b21fab413bfabc42ec5da283853b28c0',\n )\n const messageUnaligned = hexDecodeToBuffer(\n '40fa5bb7cb56a8957b4e4bec561eee4a5a1025bc8a35d3d0c79a3685d2b90ff0' +\n '5f638e9c42c9fd9448b0ce8e7d49e7ea1ce458e47b825b5c7fd8ddf5b4fded46' +\n '2a4bcc02f3ff2e89de6764d6d219f575e457fdcf8c163cdf',\n )\n\n await expect(() => decrypt(messageTooLong)).rejects.toThrow('message with invalid length: %d > %d')\n await expect(() => decrypt(messageUnaligned)).rejects.toThrow(\n 'message with invalid length: %d is not a multiple of 4',\n )\n })\n\n it('should ignore messages with invalid padding', async () => {\n const message = hexDecodeToBuffer(\n '40fa5bb7cb56a895133671d1c637a9836e2c64b4d1a0521d8a25a6416fd4dc9e' +\n '79f9478fb837703cc9efa0a19d12143c2a26e57cb4bc64d7bc972dd8f19c53c590cc258162f44afc',\n )\n\n await expect(() => decrypt(message)).rejects.toThrow('message with invalid padding size')\n })\n })\n})\n"]}
|
|
@@ -1,36 +1,38 @@
|
|
|
1
|
-
import bigInt from 'big-integer';
|
|
2
1
|
import Long from 'long';
|
|
3
2
|
import { mtp } from '@mtcute/tl';
|
|
4
3
|
import { TlBinaryReader, TlBinaryWriter, TlSerializationCounter } from '@mtcute/tl-runtime';
|
|
5
4
|
import { MtArgumentError, MtSecurityError, MtTypeAssertionError } from '../types/index.js';
|
|
6
|
-
import { buffersEqual, concatBuffers, dataViewFromBuffer
|
|
5
|
+
import { buffersEqual, concatBuffers, dataViewFromBuffer } from '../utils/buffer-utils.js';
|
|
7
6
|
import { findKeyByFingerprints } from '../utils/crypto/keys.js';
|
|
8
7
|
import { millerRabin } from '../utils/crypto/miller-rabin.js';
|
|
9
8
|
import { generateKeyAndIvFromNonce } from '../utils/crypto/mtproto.js';
|
|
10
9
|
import { xorBuffer, xorBufferInPlace } from '../utils/crypto/utils.js';
|
|
11
|
-
import { bigIntToBuffer, bufferToBigInt } from '../utils/index.js';
|
|
10
|
+
import { bigIntModPow, bigIntToBuffer, bufferToBigInt } from '../utils/index.js';
|
|
12
11
|
import { mtpAssertTypeIs } from '../utils/type-assertions.js';
|
|
13
12
|
// Heavily based on code from https://github.com/LonamiWebs/Telethon/blob/master/telethon/network/authenticator.py
|
|
14
13
|
// see https://core.telegram.org/mtproto/security_guidelines
|
|
15
|
-
const DH_SAFETY_RANGE = bigInt[2].pow(2048 - 64)
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
|
|
14
|
+
// const DH_SAFETY_RANGE = bigInt[2].pow(2048 - 64)
|
|
15
|
+
const DH_SAFETY_RANGE = 2n ** (2048n - 64n);
|
|
16
|
+
const KNOWN_DH_PRIME =
|
|
17
|
+
// eslint-disable-next-line max-len
|
|
18
|
+
0xc71caeb9c6b1c9048e6c522f70f13f73980d40238e3e21c14934d037563d930f48198a0aa7c14058229493d22530f4dbfa336f6e0ac925139543aed44cce7c3720fd51f69458705ac68cd4fe6b6b13abdc9746512969328454f18faf8c595f642477fe96bb2a941d5bcd1d4ac8cc49880708fa9b378e3c4f3a9060bee67cf9a4a4a695811051907e162753b56b0f6b410dba74d8a84b2a14b3144e0ef1284754fd17ed950d5965b4b9dd46582db1178d169c6bc465b0d6ff9ca3928fef5b9ae4e418fc15e83ebea0f87fa9ff5eed70050ded2849f47bf959d956850ce929851f0d8115f635b105ee2e4e15d04b2454bf6f4fadf034b10403119cd8e3b92fcc5bn;
|
|
19
|
+
const TWO_POW_2047 = 2n ** 2047n;
|
|
20
|
+
const TWO_POW_2048 = 2n ** 2048n;
|
|
19
21
|
const checkedPrimesCache = [];
|
|
20
|
-
function checkDhPrime(log, dhPrime, g) {
|
|
21
|
-
if (KNOWN_DH_PRIME
|
|
22
|
+
function checkDhPrime(crypto, log, dhPrime, g) {
|
|
23
|
+
if (KNOWN_DH_PRIME === dhPrime) {
|
|
22
24
|
log.debug('server is using known dh prime, skipping validation');
|
|
23
25
|
return;
|
|
24
26
|
}
|
|
25
|
-
let checkedPrime = checkedPrimesCache.find((x) => x.prime
|
|
27
|
+
let checkedPrime = checkedPrimesCache.find((x) => x.prime === dhPrime);
|
|
26
28
|
if (!checkedPrime) {
|
|
27
|
-
if (dhPrime
|
|
29
|
+
if (dhPrime <= TWO_POW_2047 || dhPrime >= TWO_POW_2048) {
|
|
28
30
|
throw new MtSecurityError('Step 3: dh_prime is not in the 2048-bit range');
|
|
29
31
|
}
|
|
30
|
-
if (!millerRabin(dhPrime)) {
|
|
32
|
+
if (!millerRabin(crypto, dhPrime)) {
|
|
31
33
|
throw new MtSecurityError('Step 3: dh_prime is not prime');
|
|
32
34
|
}
|
|
33
|
-
if (!millerRabin(dhPrime
|
|
35
|
+
if (!millerRabin(crypto, (dhPrime - 1n) / 2n)) {
|
|
34
36
|
throw new MtSecurityError('Step 3: dh_prime is not a safe prime - (dh_prime-1)/2 is not prime');
|
|
35
37
|
}
|
|
36
38
|
log.debug('dh_prime is probably prime');
|
|
@@ -50,34 +52,34 @@ function checkDhPrime(log, dhPrime, g) {
|
|
|
50
52
|
}
|
|
51
53
|
switch (g) {
|
|
52
54
|
case 2:
|
|
53
|
-
if (dhPrime
|
|
55
|
+
if (dhPrime % 8n !== 7n) {
|
|
54
56
|
throw new MtSecurityError('Step 3: ivalid g - dh_prime mod 8 != 7');
|
|
55
57
|
}
|
|
56
58
|
break;
|
|
57
59
|
case 3:
|
|
58
|
-
if (dhPrime
|
|
60
|
+
if (dhPrime % 3n !== 2n) {
|
|
59
61
|
throw new MtSecurityError('Step 3: ivalid g - dh_prime mod 3 != 2');
|
|
60
62
|
}
|
|
61
63
|
break;
|
|
62
64
|
case 4:
|
|
63
65
|
break;
|
|
64
66
|
case 5: {
|
|
65
|
-
const mod = dhPrime
|
|
66
|
-
if (mod
|
|
67
|
+
const mod = dhPrime % 5n;
|
|
68
|
+
if (mod !== 1n && mod !== 4n) {
|
|
67
69
|
throw new MtSecurityError('Step 3: ivalid g - dh_prime mod 5 != 1 && dh_prime mod 5 != 4');
|
|
68
70
|
}
|
|
69
71
|
break;
|
|
70
72
|
}
|
|
71
73
|
case 6: {
|
|
72
|
-
const mod = dhPrime
|
|
73
|
-
if (mod
|
|
74
|
+
const mod = dhPrime % 24n;
|
|
75
|
+
if (mod !== 19n && mod !== 23n) {
|
|
74
76
|
throw new MtSecurityError('Step 3: ivalid g - dh_prime mod 24 != 19 && dh_prime mod 24 != 23');
|
|
75
77
|
}
|
|
76
78
|
break;
|
|
77
79
|
}
|
|
78
80
|
case 7: {
|
|
79
|
-
const mod = dhPrime
|
|
80
|
-
if (mod
|
|
81
|
+
const mod = dhPrime % 7n;
|
|
82
|
+
if (mod !== 3n && mod !== 5n && mod !== 6n) {
|
|
81
83
|
throw new MtSecurityError('Step 3: ivalid g - dh_prime mod 7 != 3 && dh_prime mod 7 != 5 && dh_prime mod 7 != 6');
|
|
82
84
|
}
|
|
83
85
|
break;
|
|
@@ -88,41 +90,44 @@ function checkDhPrime(log, dhPrime, g) {
|
|
|
88
90
|
checkedPrime.generators.push(g);
|
|
89
91
|
log.debug('g = %d is safe to use with dh_prime', g);
|
|
90
92
|
}
|
|
91
|
-
|
|
93
|
+
function rsaPad(data, crypto, key) {
|
|
92
94
|
// since Summer 2021, they use "version of RSA with a variant of OAEP+ padding explained below"
|
|
93
|
-
const keyModulus =
|
|
94
|
-
const keyExponent =
|
|
95
|
+
const keyModulus = BigInt(`0x${key.modulus}`);
|
|
96
|
+
const keyExponent = BigInt(`0x${key.exponent}`);
|
|
95
97
|
if (data.length > 144) {
|
|
96
98
|
throw new MtArgumentError('Failed to pad: too big data');
|
|
97
99
|
}
|
|
98
|
-
|
|
100
|
+
const dataPadded = new Uint8Array(192);
|
|
101
|
+
dataPadded.set(data, 0);
|
|
102
|
+
crypto.randomFill(dataPadded.subarray(data.length));
|
|
103
|
+
data = dataPadded;
|
|
99
104
|
for (;;) {
|
|
100
105
|
const aesIv = new Uint8Array(32);
|
|
101
|
-
const aesKey = randomBytes(32);
|
|
102
|
-
const dataWithHash = concatBuffers([data,
|
|
106
|
+
const aesKey = crypto.randomBytes(32);
|
|
107
|
+
const dataWithHash = concatBuffers([data, crypto.sha256(concatBuffers([aesKey, data]))]);
|
|
103
108
|
// we only need to reverse the data
|
|
104
109
|
dataWithHash.subarray(0, 192).reverse();
|
|
105
|
-
const aes =
|
|
106
|
-
const encrypted =
|
|
107
|
-
const encryptedHash =
|
|
110
|
+
const aes = crypto.createAesIge(aesKey, aesIv);
|
|
111
|
+
const encrypted = aes.encrypt(dataWithHash);
|
|
112
|
+
const encryptedHash = crypto.sha256(encrypted);
|
|
108
113
|
xorBufferInPlace(aesKey, encryptedHash);
|
|
109
114
|
const decryptedData = concatBuffers([aesKey, encrypted]);
|
|
110
115
|
const decryptedDataBigint = bufferToBigInt(decryptedData);
|
|
111
|
-
if (decryptedDataBigint
|
|
116
|
+
if (decryptedDataBigint >= keyModulus) {
|
|
112
117
|
continue;
|
|
113
118
|
}
|
|
114
|
-
const encryptedBigint = decryptedDataBigint
|
|
119
|
+
const encryptedBigint = bigIntModPow(decryptedDataBigint, keyExponent, keyModulus);
|
|
115
120
|
return bigIntToBuffer(encryptedBigint, 256);
|
|
116
121
|
}
|
|
117
122
|
}
|
|
118
|
-
|
|
123
|
+
function rsaEncrypt(data, crypto, key) {
|
|
119
124
|
const toEncrypt = concatBuffers([
|
|
120
|
-
|
|
125
|
+
crypto.sha1(data),
|
|
121
126
|
data,
|
|
122
127
|
// sha1 is always 20 bytes, so we're left with 255 - 20 - x padding
|
|
123
|
-
randomBytes(235 - data.length),
|
|
128
|
+
crypto.randomBytes(235 - data.length),
|
|
124
129
|
]);
|
|
125
|
-
const encryptedBigInt = bufferToBigInt(toEncrypt)
|
|
130
|
+
const encryptedBigInt = bigIntModPow(bufferToBigInt(toEncrypt), BigInt(`0x${key.exponent}`), BigInt(`0x${key.modulus}`));
|
|
126
131
|
return bigIntToBuffer(encryptedBigInt);
|
|
127
132
|
}
|
|
128
133
|
/**
|
|
@@ -154,7 +159,7 @@ export async function doAuthorization(connection, crypto, expiresIn) {
|
|
|
154
159
|
}
|
|
155
160
|
if (expiresIn)
|
|
156
161
|
log.prefix = '[PFS] ';
|
|
157
|
-
const nonce = randomBytes(16);
|
|
162
|
+
const nonce = crypto.randomBytes(16);
|
|
158
163
|
// Step 1: PQ request
|
|
159
164
|
log.debug('starting PQ handshake (temp = %b), nonce = %h', expiresIn, nonce);
|
|
160
165
|
await sendPlainMessage({ _: 'mt_req_pq_multi', nonce });
|
|
@@ -173,7 +178,7 @@ export async function doAuthorization(connection, crypto, expiresIn) {
|
|
|
173
178
|
log.debug('found server key, fp = %s, old = %s', publicKey.fingerprint, publicKey.old);
|
|
174
179
|
const [p, q] = await crypto.factorizePQ(resPq.pq);
|
|
175
180
|
log.debug('factorized PQ: PQ = %h, P = %h, Q = %h', resPq.pq, p, q);
|
|
176
|
-
const newNonce = randomBytes(32);
|
|
181
|
+
const newNonce = crypto.randomBytes(32);
|
|
177
182
|
let dcId = connection.params.dc.id;
|
|
178
183
|
if (connection.params.testMode)
|
|
179
184
|
dcId += 10000;
|
|
@@ -192,8 +197,8 @@ export async function doAuthorization(connection, crypto, expiresIn) {
|
|
|
192
197
|
};
|
|
193
198
|
const pqInnerData = TlBinaryWriter.serializeObject(writerMap, _pqInnerData);
|
|
194
199
|
const encryptedData = publicKey.old ?
|
|
195
|
-
|
|
196
|
-
|
|
200
|
+
rsaEncrypt(pqInnerData, crypto, publicKey) :
|
|
201
|
+
rsaPad(pqInnerData, crypto, publicKey);
|
|
197
202
|
log.debug('requesting DH params');
|
|
198
203
|
await sendPlainMessage({
|
|
199
204
|
_: 'mt_req_DH_params',
|
|
@@ -217,13 +222,13 @@ export async function doAuthorization(connection, crypto, expiresIn) {
|
|
|
217
222
|
throw new MtSecurityError('Step 2: AES block size is invalid');
|
|
218
223
|
}
|
|
219
224
|
// Step 3: complete DH exchange
|
|
220
|
-
const [key, iv] =
|
|
221
|
-
const ige =
|
|
222
|
-
const plainTextAnswer =
|
|
225
|
+
const [key, iv] = generateKeyAndIvFromNonce(crypto, resPq.serverNonce, newNonce);
|
|
226
|
+
const ige = crypto.createAesIge(key, iv);
|
|
227
|
+
const plainTextAnswer = ige.decrypt(serverDhParams.encryptedAnswer);
|
|
223
228
|
const innerDataHash = plainTextAnswer.subarray(0, 20);
|
|
224
229
|
const serverDhInnerReader = new TlBinaryReader(readerMap, plainTextAnswer, 20);
|
|
225
230
|
const serverDhInner = serverDhInnerReader.object();
|
|
226
|
-
if (!buffersEqual(innerDataHash,
|
|
231
|
+
if (!buffersEqual(innerDataHash, crypto.sha1(plainTextAnswer.subarray(20, serverDhInnerReader.pos)))) {
|
|
227
232
|
throw new MtSecurityError('Step 3: invalid inner data hash');
|
|
228
233
|
}
|
|
229
234
|
mtpAssertTypeIs('auth step 3', serverDhInner, 'mt_server_DH_inner_data');
|
|
@@ -235,30 +240,30 @@ export async function doAuthorization(connection, crypto, expiresIn) {
|
|
|
235
240
|
}
|
|
236
241
|
const dhPrime = bufferToBigInt(serverDhInner.dhPrime);
|
|
237
242
|
const timeOffset = Math.floor(Date.now() / 1000) - serverDhInner.serverTime;
|
|
238
|
-
const g =
|
|
243
|
+
const g = BigInt(serverDhInner.g);
|
|
239
244
|
const gA = bufferToBigInt(serverDhInner.gA);
|
|
240
|
-
checkDhPrime(log, dhPrime, serverDhInner.g);
|
|
245
|
+
checkDhPrime(crypto, log, dhPrime, serverDhInner.g);
|
|
241
246
|
let retryId = Long.ZERO;
|
|
242
247
|
const serverSalt = xorBuffer(newNonce.subarray(0, 8), resPq.serverNonce.subarray(0, 8));
|
|
243
248
|
for (;;) {
|
|
244
|
-
const b = bufferToBigInt(randomBytes(256));
|
|
245
|
-
const gB = g
|
|
246
|
-
const authKey = bigIntToBuffer(gA
|
|
247
|
-
const authKeyAuxHash =
|
|
249
|
+
const b = bufferToBigInt(crypto.randomBytes(256));
|
|
250
|
+
const gB = bigIntModPow(g, b, dhPrime);
|
|
251
|
+
const authKey = bigIntToBuffer(bigIntModPow(gA, b, dhPrime));
|
|
252
|
+
const authKeyAuxHash = crypto.sha1(authKey).subarray(0, 8);
|
|
248
253
|
// validate DH params
|
|
249
|
-
if (g
|
|
254
|
+
if (g <= 1 || g >= dhPrime - 1n) {
|
|
250
255
|
throw new MtSecurityError('g is not within (1, dh_prime - 1)');
|
|
251
256
|
}
|
|
252
|
-
if (gA
|
|
257
|
+
if (gA <= 1 || gA >= dhPrime - 1n) {
|
|
253
258
|
throw new MtSecurityError('g_a is not within (1, dh_prime - 1)');
|
|
254
259
|
}
|
|
255
|
-
if (gB
|
|
260
|
+
if (gB <= 1 || gB >= dhPrime - 1n) {
|
|
256
261
|
throw new MtSecurityError('g_b is not within (1, dh_prime - 1)');
|
|
257
262
|
}
|
|
258
|
-
if (gA
|
|
263
|
+
if (gA <= DH_SAFETY_RANGE || gA >= dhPrime - DH_SAFETY_RANGE) {
|
|
259
264
|
throw new MtSecurityError('g_a is not within (2^{2048-64}, dh_prime - 2^{2048-64})');
|
|
260
265
|
}
|
|
261
|
-
if (gB
|
|
266
|
+
if (gB <= DH_SAFETY_RANGE || gB >= dhPrime - DH_SAFETY_RANGE) {
|
|
262
267
|
throw new MtSecurityError('g_b is not within (2^{2048-64}, dh_prime - 2^{2048-64})');
|
|
263
268
|
}
|
|
264
269
|
const gB_ = bigIntToBuffer(gB, 0, false);
|
|
@@ -277,11 +282,11 @@ export async function doAuthorization(connection, crypto, expiresIn) {
|
|
|
277
282
|
const clientDhInnerWriter = TlBinaryWriter.alloc(writerMap, innerLength);
|
|
278
283
|
clientDhInnerWriter.pos = 20;
|
|
279
284
|
clientDhInnerWriter.object(clientDhInner);
|
|
280
|
-
const clientDhInnerHash =
|
|
285
|
+
const clientDhInnerHash = crypto.sha1(clientDhInnerWriter.uint8View.subarray(20, clientDhInnerWriter.pos));
|
|
281
286
|
clientDhInnerWriter.pos = 0;
|
|
282
287
|
clientDhInnerWriter.raw(clientDhInnerHash);
|
|
283
288
|
log.debug('sending client DH (timeOffset = %d)', timeOffset);
|
|
284
|
-
const clientDhEncrypted =
|
|
289
|
+
const clientDhEncrypted = ige.encrypt(clientDhInnerWriter.uint8View);
|
|
285
290
|
await sendPlainMessage({
|
|
286
291
|
_: 'mt_set_client_DH_params',
|
|
287
292
|
nonce,
|
|
@@ -304,7 +309,7 @@ export async function doAuthorization(connection, crypto, expiresIn) {
|
|
|
304
309
|
throw new MtTypeAssertionError('auth step 4', '!mt_dh_gen_fail', dhGen._);
|
|
305
310
|
}
|
|
306
311
|
if (dhGen._ === 'mt_dh_gen_retry') {
|
|
307
|
-
const expectedHash =
|
|
312
|
+
const expectedHash = crypto.sha1(concatBuffers([newNonce, new Uint8Array([2]), authKeyAuxHash]));
|
|
308
313
|
if (!buffersEqual(expectedHash.subarray(4, 20), dhGen.newNonceHash2)) {
|
|
309
314
|
throw Error('Step 4: invalid retry nonce hash from server');
|
|
310
315
|
}
|
|
@@ -313,7 +318,7 @@ export async function doAuthorization(connection, crypto, expiresIn) {
|
|
|
313
318
|
}
|
|
314
319
|
if (dhGen._ !== 'mt_dh_gen_ok')
|
|
315
320
|
throw new Error(); // unreachable
|
|
316
|
-
const expectedHash =
|
|
321
|
+
const expectedHash = crypto.sha1(concatBuffers([newNonce, new Uint8Array([1]), authKeyAuxHash]));
|
|
317
322
|
if (!buffersEqual(expectedHash.subarray(4, 20), dhGen.newNonceHash1)) {
|
|
318
323
|
throw Error('Step 4: invalid nonce hash from server');
|
|
319
324
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authorization.js","sourceRoot":"","sources":["../../../src/network/authorization.ts"],"names":[],"mappings":"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","sourcesContent":["import bigInt from 'big-integer'\nimport Long from 'long'\n\nimport { mtp } from '@mtcute/tl'\nimport { TlPublicKey } from '@mtcute/tl/binary/rsa-keys.js'\nimport { TlBinaryReader, TlBinaryWriter, TlSerializationCounter } from '@mtcute/tl-runtime'\n\nimport { MtArgumentError, MtSecurityError, MtTypeAssertionError } from '../types/index.js'\nimport { buffersEqual, concatBuffers, dataViewFromBuffer, randomBytes } from '../utils/buffer-utils.js'\nimport { findKeyByFingerprints } from '../utils/crypto/keys.js'\nimport { millerRabin } from '../utils/crypto/miller-rabin.js'\nimport { generateKeyAndIvFromNonce } from '../utils/crypto/mtproto.js'\nimport { xorBuffer, xorBufferInPlace } from '../utils/crypto/utils.js'\nimport { bigIntToBuffer, bufferToBigInt, ICryptoProvider, Logger } from '../utils/index.js'\nimport { mtpAssertTypeIs } from '../utils/type-assertions.js'\nimport { SessionConnection } from './session-connection.js'\n\n// Heavily based on code from https://github.com/LonamiWebs/Telethon/blob/master/telethon/network/authenticator.py\n\n// see https://core.telegram.org/mtproto/security_guidelines\nconst DH_SAFETY_RANGE = bigInt[2].pow(2048 - 64)\nconst KNOWN_DH_PRIME = bigInt(\n 'C71CAEB9C6B1C9048E6C522F70F13F73980D40238E3E21C14934D037563D930F48198A0AA7C14058229493D22530F4DBFA336F6E0AC925139543AED44CCE7C3720FD51F69458705AC68CD4FE6B6B13ABDC9746512969328454F18FAF8C595F642477FE96BB2A941D5BCD1D4AC8CC49880708FA9B378E3C4F3A9060BEE67CF9A4A4A695811051907E162753B56B0F6B410DBA74D8A84B2A14B3144E0EF1284754FD17ED950D5965B4B9DD46582DB1178D169C6BC465B0D6FF9CA3928FEF5B9AE4E418FC15E83EBEA0F87FA9FF5EED70050DED2849F47BF959D956850CE929851F0D8115F635B105EE2E4E15D04B2454BF6F4FADF034B10403119CD8E3B92FCC5B',\n 16,\n)\nconst TWO_POW_2047 = bigInt[2].pow(2047)\nconst TWO_POW_2048 = bigInt[2].pow(2048)\n\ninterface CheckedPrime {\n prime: bigInt.BigInteger\n generators: number[]\n}\nconst checkedPrimesCache: CheckedPrime[] = []\n\nfunction checkDhPrime(log: Logger, dhPrime: bigInt.BigInteger, g: number) {\n if (KNOWN_DH_PRIME.eq(dhPrime)) {\n log.debug('server is using known dh prime, skipping validation')\n\n return\n }\n\n let checkedPrime = checkedPrimesCache.find((x) => x.prime.eq(dhPrime))\n\n if (!checkedPrime) {\n if (dhPrime.lesserOrEquals(TWO_POW_2047) || dhPrime.greaterOrEquals(TWO_POW_2048)) {\n throw new MtSecurityError('Step 3: dh_prime is not in the 2048-bit range')\n }\n\n if (!millerRabin(dhPrime)) {\n throw new MtSecurityError('Step 3: dh_prime is not prime')\n }\n if (!millerRabin(dhPrime.minus(1).divide(2))) {\n throw new MtSecurityError('Step 3: dh_prime is not a safe prime - (dh_prime-1)/2 is not prime')\n }\n\n log.debug('dh_prime is probably prime')\n\n checkedPrime = {\n prime: dhPrime,\n generators: [],\n }\n checkedPrimesCache.push(checkedPrime)\n } else {\n log.debug('dh_prime is probably prime (cached)')\n }\n\n const generatorChecked = checkedPrime.generators.includes(g)\n\n if (generatorChecked) {\n log.debug('g = %d is already checked for dh_prime', g)\n\n return\n }\n\n switch (g) {\n case 2:\n if (dhPrime.mod(8).notEquals(7)) {\n throw new MtSecurityError('Step 3: ivalid g - dh_prime mod 8 != 7')\n }\n break\n case 3:\n if (dhPrime.mod(3).notEquals(2)) {\n throw new MtSecurityError('Step 3: ivalid g - dh_prime mod 3 != 2')\n }\n break\n case 4:\n break\n case 5: {\n const mod = dhPrime.mod(5)\n\n if (mod.notEquals(1) && mod.notEquals(4)) {\n throw new MtSecurityError('Step 3: ivalid g - dh_prime mod 5 != 1 && dh_prime mod 5 != 4')\n }\n break\n }\n case 6: {\n const mod = dhPrime.mod(24)\n\n if (mod.notEquals(19) && mod.notEquals(23)) {\n throw new MtSecurityError('Step 3: ivalid g - dh_prime mod 24 != 19 && dh_prime mod 24 != 23')\n }\n break\n }\n case 7: {\n const mod = dhPrime.mod(7)\n\n if (mod.notEquals(3) && mod.notEquals(5) && mod.notEquals(6)) {\n throw new MtSecurityError(\n 'Step 3: ivalid g - dh_prime mod 7 != 3 && dh_prime mod 7 != 5 && dh_prime mod 7 != 6',\n )\n }\n break\n }\n default:\n throw new MtSecurityError(`Step 3: ivalid g - unknown g = ${g}`)\n }\n\n checkedPrime.generators.push(g)\n\n log.debug('g = %d is safe to use with dh_prime', g)\n}\n\nasync function rsaPad(data: Uint8Array, crypto: ICryptoProvider, key: TlPublicKey): Promise<Uint8Array> {\n // since Summer 2021, they use \"version of RSA with a variant of OAEP+ padding explained below\"\n\n const keyModulus = bigInt(key.modulus, 16)\n const keyExponent = bigInt(key.exponent, 16)\n\n if (data.length > 144) {\n throw new MtArgumentError('Failed to pad: too big data')\n }\n\n data = concatBuffers([data, randomBytes(192 - data.length)])\n\n for (;;) {\n const aesIv = new Uint8Array(32)\n\n const aesKey = randomBytes(32)\n\n const dataWithHash = concatBuffers([data, await crypto.sha256(concatBuffers([aesKey, data]))])\n // we only need to reverse the data\n dataWithHash.subarray(0, 192).reverse()\n\n const aes = await crypto.createAesIge(aesKey, aesIv)\n const encrypted = await aes.encrypt(dataWithHash)\n const encryptedHash = await crypto.sha256(encrypted)\n\n xorBufferInPlace(aesKey, encryptedHash)\n const decryptedData = concatBuffers([aesKey, encrypted])\n\n const decryptedDataBigint = bufferToBigInt(decryptedData)\n\n if (decryptedDataBigint.geq(keyModulus)) {\n continue\n }\n\n const encryptedBigint = decryptedDataBigint.modPow(keyExponent, keyModulus)\n\n return bigIntToBuffer(encryptedBigint, 256)\n }\n}\n\nasync function rsaEncrypt(data: Uint8Array, crypto: ICryptoProvider, key: TlPublicKey): Promise<Uint8Array> {\n const toEncrypt = concatBuffers([\n await crypto.sha1(data),\n data,\n // sha1 is always 20 bytes, so we're left with 255 - 20 - x padding\n randomBytes(235 - data.length),\n ])\n\n const encryptedBigInt = bufferToBigInt(toEncrypt).modPow(bigInt(key.exponent, 16), bigInt(key.modulus, 16))\n\n return bigIntToBuffer(encryptedBigInt)\n}\n\n/**\n * Execute authorization flow on `connection` using `crypto`.\n *\n * @returns tuple: [authKey, serverSalt, timeOffset]\n */\nexport async function doAuthorization(\n connection: SessionConnection,\n crypto: ICryptoProvider,\n expiresIn?: number,\n): Promise<[Uint8Array, Long, number]> {\n // eslint-disable-next-line dot-notation\n const session = connection['_session']\n const readerMap = session._readerMap\n const writerMap = session._writerMap\n const log = connection.log.create('auth')\n\n function sendPlainMessage(message: mtp.TlObject): Promise<void> {\n const length = TlSerializationCounter.countNeededBytes(writerMap, message)\n const writer = TlBinaryWriter.alloc(writerMap, length + 20) // 20 bytes for mtproto header\n\n const messageId = session.getMessageId()\n\n log.verbose('[PLAIN] >>> %j', message)\n writer.long(Long.ZERO)\n writer.long(messageId)\n writer.uint(length)\n writer.object(message)\n\n return connection.send(writer.result())\n }\n\n async function readNext(): Promise<mtp.TlObject> {\n const res = TlBinaryReader.deserializeObject<mtp.TlObject>(\n readerMap,\n await connection.waitForUnencryptedMessage(),\n 20, // skip mtproto header\n )\n\n log.verbose('[PLAIN] <<< %j', res)\n\n return res\n }\n\n if (expiresIn) log.prefix = '[PFS] '\n\n const nonce = randomBytes(16)\n // Step 1: PQ request\n log.debug('starting PQ handshake (temp = %b), nonce = %h', expiresIn, nonce)\n\n await sendPlainMessage({ _: 'mt_req_pq_multi', nonce })\n const resPq = await readNext()\n\n mtpAssertTypeIs('auth step 1', resPq, 'mt_resPQ')\n\n if (!buffersEqual(resPq.nonce, nonce)) {\n throw new MtSecurityError('Step 1: invalid nonce from server')\n }\n\n const serverKeys = resPq.serverPublicKeyFingerprints.map((it) => it.toUnsigned().toString(16))\n log.debug('received PQ, keys: %j', serverKeys)\n\n // Step 2: DH exchange\n const publicKey = findKeyByFingerprints(serverKeys)\n\n if (!publicKey) {\n throw new MtSecurityError(\n 'Step 2: Could not find server public key with any of these fingerprints: ' + serverKeys.join(', '),\n )\n }\n log.debug('found server key, fp = %s, old = %s', publicKey.fingerprint, publicKey.old)\n\n const [p, q] = await crypto.factorizePQ(resPq.pq)\n log.debug('factorized PQ: PQ = %h, P = %h, Q = %h', resPq.pq, p, q)\n\n const newNonce = randomBytes(32)\n\n let dcId = connection.params.dc.id\n if (connection.params.testMode) dcId += 10000\n if (connection.params.dc.mediaOnly) dcId = -dcId\n\n const _pqInnerData: mtp.TypeP_Q_inner_data = {\n _: expiresIn ? 'mt_p_q_inner_data_temp_dc' : 'mt_p_q_inner_data_dc',\n pq: resPq.pq,\n p,\n q,\n nonce,\n newNonce,\n serverNonce: resPq.serverNonce,\n dc: dcId,\n expiresIn: expiresIn!, // whatever\n }\n const pqInnerData = TlBinaryWriter.serializeObject(writerMap, _pqInnerData)\n\n const encryptedData = publicKey.old ?\n await rsaEncrypt(pqInnerData, crypto, publicKey) :\n await rsaPad(pqInnerData, crypto, publicKey)\n\n log.debug('requesting DH params')\n\n await sendPlainMessage({\n _: 'mt_req_DH_params',\n nonce,\n serverNonce: resPq.serverNonce,\n p,\n q,\n publicKeyFingerprint: Long.fromString(publicKey.fingerprint, true, 16),\n encryptedData,\n })\n const serverDhParams = await readNext()\n\n mtpAssertTypeIs('auth step 2', serverDhParams, 'mt_server_DH_params_ok')\n\n if (!buffersEqual(serverDhParams.nonce, nonce)) {\n throw new MtSecurityError('Step 2: invalid nonce from server')\n }\n if (!buffersEqual(serverDhParams.serverNonce, resPq.serverNonce)) {\n throw new MtSecurityError('Step 2: invalid server nonce from server')\n }\n\n log.debug('server DH ok')\n\n if (serverDhParams.encryptedAnswer.length % 16 !== 0) {\n throw new MtSecurityError('Step 2: AES block size is invalid')\n }\n\n // Step 3: complete DH exchange\n const [key, iv] = await generateKeyAndIvFromNonce(crypto, resPq.serverNonce, newNonce)\n const ige = await crypto.createAesIge(key, iv)\n\n const plainTextAnswer = await ige.decrypt(serverDhParams.encryptedAnswer)\n const innerDataHash = plainTextAnswer.subarray(0, 20)\n const serverDhInnerReader = new TlBinaryReader(readerMap, plainTextAnswer, 20)\n const serverDhInner = serverDhInnerReader.object() as mtp.TlObject\n\n if (!buffersEqual(innerDataHash, await crypto.sha1(plainTextAnswer.subarray(20, serverDhInnerReader.pos)))) {\n throw new MtSecurityError('Step 3: invalid inner data hash')\n }\n\n mtpAssertTypeIs('auth step 3', serverDhInner, 'mt_server_DH_inner_data')\n\n if (!buffersEqual(serverDhInner.nonce, nonce)) {\n throw Error('Step 3: invalid nonce from server')\n }\n if (!buffersEqual(serverDhInner.serverNonce, resPq.serverNonce)) {\n throw Error('Step 3: invalid server nonce from server')\n }\n\n const dhPrime = bufferToBigInt(serverDhInner.dhPrime)\n const timeOffset = Math.floor(Date.now() / 1000) - serverDhInner.serverTime\n\n const g = bigInt(serverDhInner.g)\n const gA = bufferToBigInt(serverDhInner.gA)\n\n checkDhPrime(log, dhPrime, serverDhInner.g)\n\n let retryId = Long.ZERO\n const serverSalt = xorBuffer(newNonce.subarray(0, 8), resPq.serverNonce.subarray(0, 8))\n\n for (;;) {\n const b = bufferToBigInt(randomBytes(256))\n const gB = g.modPow(b, dhPrime)\n\n const authKey = bigIntToBuffer(gA.modPow(b, dhPrime))\n const authKeyAuxHash = (await crypto.sha1(authKey)).subarray(0, 8)\n\n // validate DH params\n if (g.lesserOrEquals(1) || g.greaterOrEquals(dhPrime.minus(bigInt.one))) {\n throw new MtSecurityError('g is not within (1, dh_prime - 1)')\n }\n if (gA.lesserOrEquals(1) || gA.greaterOrEquals(dhPrime.minus(bigInt.one))) {\n throw new MtSecurityError('g_a is not within (1, dh_prime - 1)')\n }\n if (gB.lesserOrEquals(1) || gB.greaterOrEquals(dhPrime.minus(bigInt.one))) {\n throw new MtSecurityError('g_b is not within (1, dh_prime - 1)')\n }\n\n if (gA.lt(DH_SAFETY_RANGE) || gA.gt(dhPrime.minus(DH_SAFETY_RANGE))) {\n throw new MtSecurityError('g_a is not within (2^{2048-64}, dh_prime - 2^{2048-64})')\n }\n if (gB.lt(DH_SAFETY_RANGE) || gB.gt(dhPrime.minus(DH_SAFETY_RANGE))) {\n throw new MtSecurityError('g_b is not within (2^{2048-64}, dh_prime - 2^{2048-64})')\n }\n\n const gB_ = bigIntToBuffer(gB, 0, false)\n\n // Step 4: send client DH\n const clientDhInner: mtp.RawMt_client_DH_inner_data = {\n _: 'mt_client_DH_inner_data',\n nonce,\n serverNonce: resPq.serverNonce,\n retryId,\n gB: gB_,\n }\n let innerLength = TlSerializationCounter.countNeededBytes(writerMap, clientDhInner) + 20 // for hash\n const innerPaddingLength = innerLength % 16\n if (innerPaddingLength > 0) innerLength += 16 - innerPaddingLength\n\n const clientDhInnerWriter = TlBinaryWriter.alloc(writerMap, innerLength)\n clientDhInnerWriter.pos = 20\n clientDhInnerWriter.object(clientDhInner)\n const clientDhInnerHash = await crypto.sha1(clientDhInnerWriter.uint8View.subarray(20, clientDhInnerWriter.pos))\n clientDhInnerWriter.pos = 0\n clientDhInnerWriter.raw(clientDhInnerHash)\n\n log.debug('sending client DH (timeOffset = %d)', timeOffset)\n\n const clientDhEncrypted = await ige.encrypt(clientDhInnerWriter.uint8View)\n await sendPlainMessage({\n _: 'mt_set_client_DH_params',\n nonce,\n serverNonce: resPq.serverNonce,\n encryptedData: clientDhEncrypted,\n })\n\n const dhGen = await readNext()\n\n if (!mtp.isAnySet_client_DH_params_answer(dhGen)) {\n throw new MtTypeAssertionError('auth step 4', 'set_client_DH_params_answer', dhGen._)\n }\n\n if (!buffersEqual(dhGen.nonce, nonce)) {\n throw Error('Step 4: invalid nonce from server')\n }\n if (!buffersEqual(dhGen.serverNonce, resPq.serverNonce)) {\n throw Error('Step 4: invalid server nonce from server')\n }\n\n log.debug('DH result: %s', dhGen._)\n\n if (dhGen._ === 'mt_dh_gen_fail') {\n // in theory i would be supposed to calculate newNonceHash, but why, we are failing anyway\n throw new MtTypeAssertionError('auth step 4', '!mt_dh_gen_fail', dhGen._)\n }\n\n if (dhGen._ === 'mt_dh_gen_retry') {\n const expectedHash = await crypto.sha1(concatBuffers([newNonce, new Uint8Array([2]), authKeyAuxHash]))\n\n if (!buffersEqual(expectedHash.subarray(4, 20), dhGen.newNonceHash2)) {\n throw Error('Step 4: invalid retry nonce hash from server')\n }\n retryId = Long.fromBytesLE(authKeyAuxHash as unknown as number[])\n continue\n }\n\n if (dhGen._ !== 'mt_dh_gen_ok') throw new Error() // unreachable\n\n const expectedHash = await crypto.sha1(concatBuffers([newNonce, new Uint8Array([1]), authKeyAuxHash]))\n\n if (!buffersEqual(expectedHash.subarray(4, 20), dhGen.newNonceHash1)) {\n throw Error('Step 4: invalid nonce hash from server')\n }\n\n log.info('authorization successful')\n\n const dv = dataViewFromBuffer(serverSalt)\n\n return [authKey, new Long(dv.getInt32(0, true), dv.getInt32(4, true)), timeOffset]\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"authorization.js","sourceRoot":"","sources":["../../../src/network/authorization.ts"],"names":[],"mappings":"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","sourcesContent":["import Long from 'long'\n\nimport { mtp } from '@mtcute/tl'\nimport { TlPublicKey } from '@mtcute/tl/binary/rsa-keys.js'\nimport { TlBinaryReader, TlBinaryWriter, TlSerializationCounter } from '@mtcute/tl-runtime'\n\nimport { MtArgumentError, MtSecurityError, MtTypeAssertionError } from '../types/index.js'\nimport { buffersEqual, concatBuffers, dataViewFromBuffer } from '../utils/buffer-utils.js'\nimport { findKeyByFingerprints } from '../utils/crypto/keys.js'\nimport { millerRabin } from '../utils/crypto/miller-rabin.js'\nimport { generateKeyAndIvFromNonce } from '../utils/crypto/mtproto.js'\nimport { xorBuffer, xorBufferInPlace } from '../utils/crypto/utils.js'\nimport { bigIntModPow, bigIntToBuffer, bufferToBigInt, ICryptoProvider, Logger } from '../utils/index.js'\nimport { mtpAssertTypeIs } from '../utils/type-assertions.js'\nimport { SessionConnection } from './session-connection.js'\n\n// Heavily based on code from https://github.com/LonamiWebs/Telethon/blob/master/telethon/network/authenticator.py\n\n// see https://core.telegram.org/mtproto/security_guidelines\n// const DH_SAFETY_RANGE = bigInt[2].pow(2048 - 64)\nconst DH_SAFETY_RANGE = 2n ** (2048n - 64n)\nconst KNOWN_DH_PRIME =\n // eslint-disable-next-line max-len\n 0xc71caeb9c6b1c9048e6c522f70f13f73980d40238e3e21c14934d037563d930f48198a0aa7c14058229493d22530f4dbfa336f6e0ac925139543aed44cce7c3720fd51f69458705ac68cd4fe6b6b13abdc9746512969328454f18faf8c595f642477fe96bb2a941d5bcd1d4ac8cc49880708fa9b378e3c4f3a9060bee67cf9a4a4a695811051907e162753b56b0f6b410dba74d8a84b2a14b3144e0ef1284754fd17ed950d5965b4b9dd46582db1178d169c6bc465b0d6ff9ca3928fef5b9ae4e418fc15e83ebea0f87fa9ff5eed70050ded2849f47bf959d956850ce929851f0d8115f635b105ee2e4e15d04b2454bf6f4fadf034b10403119cd8e3b92fcc5bn\nconst TWO_POW_2047 = 2n ** 2047n\nconst TWO_POW_2048 = 2n ** 2048n\n\ninterface CheckedPrime {\n prime: bigint\n generators: number[]\n}\n\nconst checkedPrimesCache: CheckedPrime[] = []\n\nfunction checkDhPrime(crypto: ICryptoProvider, log: Logger, dhPrime: bigint, g: number) {\n if (KNOWN_DH_PRIME === dhPrime) {\n log.debug('server is using known dh prime, skipping validation')\n\n return\n }\n\n let checkedPrime = checkedPrimesCache.find((x) => x.prime === dhPrime)\n\n if (!checkedPrime) {\n if (dhPrime <= TWO_POW_2047 || dhPrime >= TWO_POW_2048) {\n throw new MtSecurityError('Step 3: dh_prime is not in the 2048-bit range')\n }\n\n if (!millerRabin(crypto, dhPrime)) {\n throw new MtSecurityError('Step 3: dh_prime is not prime')\n }\n if (!millerRabin(crypto, (dhPrime - 1n) / 2n)) {\n throw new MtSecurityError('Step 3: dh_prime is not a safe prime - (dh_prime-1)/2 is not prime')\n }\n\n log.debug('dh_prime is probably prime')\n\n checkedPrime = {\n prime: dhPrime,\n generators: [],\n }\n checkedPrimesCache.push(checkedPrime)\n } else {\n log.debug('dh_prime is probably prime (cached)')\n }\n\n const generatorChecked = checkedPrime.generators.includes(g)\n\n if (generatorChecked) {\n log.debug('g = %d is already checked for dh_prime', g)\n\n return\n }\n\n switch (g) {\n case 2:\n if (dhPrime % 8n !== 7n) {\n throw new MtSecurityError('Step 3: ivalid g - dh_prime mod 8 != 7')\n }\n break\n case 3:\n if (dhPrime % 3n !== 2n) {\n throw new MtSecurityError('Step 3: ivalid g - dh_prime mod 3 != 2')\n }\n break\n case 4:\n break\n case 5: {\n const mod = dhPrime % 5n\n\n if (mod !== 1n && mod !== 4n) {\n throw new MtSecurityError('Step 3: ivalid g - dh_prime mod 5 != 1 && dh_prime mod 5 != 4')\n }\n break\n }\n case 6: {\n const mod = dhPrime % 24n\n\n if (mod !== 19n && mod !== 23n) {\n throw new MtSecurityError('Step 3: ivalid g - dh_prime mod 24 != 19 && dh_prime mod 24 != 23')\n }\n break\n }\n case 7: {\n const mod = dhPrime % 7n\n\n if (mod !== 3n && mod !== 5n && mod !== 6n) {\n throw new MtSecurityError(\n 'Step 3: ivalid g - dh_prime mod 7 != 3 && dh_prime mod 7 != 5 && dh_prime mod 7 != 6',\n )\n }\n break\n }\n default:\n throw new MtSecurityError(`Step 3: ivalid g - unknown g = ${g}`)\n }\n\n checkedPrime.generators.push(g)\n\n log.debug('g = %d is safe to use with dh_prime', g)\n}\n\nfunction rsaPad(data: Uint8Array, crypto: ICryptoProvider, key: TlPublicKey): Uint8Array {\n // since Summer 2021, they use \"version of RSA with a variant of OAEP+ padding explained below\"\n\n const keyModulus = BigInt(`0x${key.modulus}`)\n const keyExponent = BigInt(`0x${key.exponent}`)\n\n if (data.length > 144) {\n throw new MtArgumentError('Failed to pad: too big data')\n }\n\n const dataPadded = new Uint8Array(192)\n dataPadded.set(data, 0)\n crypto.randomFill(dataPadded.subarray(data.length))\n data = dataPadded\n\n for (;;) {\n const aesIv = new Uint8Array(32)\n\n const aesKey = crypto.randomBytes(32)\n\n const dataWithHash = concatBuffers([data, crypto.sha256(concatBuffers([aesKey, data]))])\n // we only need to reverse the data\n dataWithHash.subarray(0, 192).reverse()\n\n const aes = crypto.createAesIge(aesKey, aesIv)\n const encrypted = aes.encrypt(dataWithHash)\n const encryptedHash = crypto.sha256(encrypted)\n\n xorBufferInPlace(aesKey, encryptedHash)\n const decryptedData = concatBuffers([aesKey, encrypted])\n\n const decryptedDataBigint = bufferToBigInt(decryptedData)\n\n if (decryptedDataBigint >= keyModulus) {\n continue\n }\n\n const encryptedBigint = bigIntModPow(decryptedDataBigint, keyExponent, keyModulus)\n\n return bigIntToBuffer(encryptedBigint, 256)\n }\n}\n\nfunction rsaEncrypt(data: Uint8Array, crypto: ICryptoProvider, key: TlPublicKey): Uint8Array {\n const toEncrypt = concatBuffers([\n crypto.sha1(data),\n data,\n // sha1 is always 20 bytes, so we're left with 255 - 20 - x padding\n crypto.randomBytes(235 - data.length),\n ])\n\n const encryptedBigInt = bigIntModPow(\n bufferToBigInt(toEncrypt),\n BigInt(`0x${key.exponent}`),\n BigInt(`0x${key.modulus}`),\n )\n\n return bigIntToBuffer(encryptedBigInt)\n}\n\n/**\n * Execute authorization flow on `connection` using `crypto`.\n *\n * @returns tuple: [authKey, serverSalt, timeOffset]\n */\nexport async function doAuthorization(\n connection: SessionConnection,\n crypto: ICryptoProvider,\n expiresIn?: number,\n): Promise<[Uint8Array, Long, number]> {\n // eslint-disable-next-line dot-notation\n const session = connection['_session']\n const readerMap = session._readerMap\n const writerMap = session._writerMap\n const log = connection.log.create('auth')\n\n function sendPlainMessage(message: mtp.TlObject): Promise<void> {\n const length = TlSerializationCounter.countNeededBytes(writerMap, message)\n const writer = TlBinaryWriter.alloc(writerMap, length + 20) // 20 bytes for mtproto header\n\n const messageId = session.getMessageId()\n\n log.verbose('[PLAIN] >>> %j', message)\n writer.long(Long.ZERO)\n writer.long(messageId)\n writer.uint(length)\n writer.object(message)\n\n return connection.send(writer.result())\n }\n\n async function readNext(): Promise<mtp.TlObject> {\n const res = TlBinaryReader.deserializeObject<mtp.TlObject>(\n readerMap,\n await connection.waitForUnencryptedMessage(),\n 20, // skip mtproto header\n )\n\n log.verbose('[PLAIN] <<< %j', res)\n\n return res\n }\n\n if (expiresIn) log.prefix = '[PFS] '\n\n const nonce = crypto.randomBytes(16)\n // Step 1: PQ request\n log.debug('starting PQ handshake (temp = %b), nonce = %h', expiresIn, nonce)\n\n await sendPlainMessage({ _: 'mt_req_pq_multi', nonce })\n const resPq = await readNext()\n\n mtpAssertTypeIs('auth step 1', resPq, 'mt_resPQ')\n\n if (!buffersEqual(resPq.nonce, nonce)) {\n throw new MtSecurityError('Step 1: invalid nonce from server')\n }\n\n const serverKeys = resPq.serverPublicKeyFingerprints.map((it) => it.toUnsigned().toString(16))\n log.debug('received PQ, keys: %j', serverKeys)\n\n // Step 2: DH exchange\n const publicKey = findKeyByFingerprints(serverKeys)\n\n if (!publicKey) {\n throw new MtSecurityError(\n 'Step 2: Could not find server public key with any of these fingerprints: ' + serverKeys.join(', '),\n )\n }\n log.debug('found server key, fp = %s, old = %s', publicKey.fingerprint, publicKey.old)\n\n const [p, q] = await crypto.factorizePQ(resPq.pq)\n log.debug('factorized PQ: PQ = %h, P = %h, Q = %h', resPq.pq, p, q)\n\n const newNonce = crypto.randomBytes(32)\n\n let dcId = connection.params.dc.id\n if (connection.params.testMode) dcId += 10000\n if (connection.params.dc.mediaOnly) dcId = -dcId\n\n const _pqInnerData: mtp.TypeP_Q_inner_data = {\n _: expiresIn ? 'mt_p_q_inner_data_temp_dc' : 'mt_p_q_inner_data_dc',\n pq: resPq.pq,\n p,\n q,\n nonce,\n newNonce,\n serverNonce: resPq.serverNonce,\n dc: dcId,\n expiresIn: expiresIn!, // whatever\n }\n const pqInnerData = TlBinaryWriter.serializeObject(writerMap, _pqInnerData)\n\n const encryptedData = publicKey.old ?\n rsaEncrypt(pqInnerData, crypto, publicKey) :\n rsaPad(pqInnerData, crypto, publicKey)\n\n log.debug('requesting DH params')\n\n await sendPlainMessage({\n _: 'mt_req_DH_params',\n nonce,\n serverNonce: resPq.serverNonce,\n p,\n q,\n publicKeyFingerprint: Long.fromString(publicKey.fingerprint, true, 16),\n encryptedData,\n })\n const serverDhParams = await readNext()\n\n mtpAssertTypeIs('auth step 2', serverDhParams, 'mt_server_DH_params_ok')\n\n if (!buffersEqual(serverDhParams.nonce, nonce)) {\n throw new MtSecurityError('Step 2: invalid nonce from server')\n }\n if (!buffersEqual(serverDhParams.serverNonce, resPq.serverNonce)) {\n throw new MtSecurityError('Step 2: invalid server nonce from server')\n }\n\n log.debug('server DH ok')\n\n if (serverDhParams.encryptedAnswer.length % 16 !== 0) {\n throw new MtSecurityError('Step 2: AES block size is invalid')\n }\n\n // Step 3: complete DH exchange\n const [key, iv] = generateKeyAndIvFromNonce(crypto, resPq.serverNonce, newNonce)\n const ige = crypto.createAesIge(key, iv)\n\n const plainTextAnswer = ige.decrypt(serverDhParams.encryptedAnswer)\n const innerDataHash = plainTextAnswer.subarray(0, 20)\n const serverDhInnerReader = new TlBinaryReader(readerMap, plainTextAnswer, 20)\n const serverDhInner = serverDhInnerReader.object() as mtp.TlObject\n\n if (!buffersEqual(innerDataHash, crypto.sha1(plainTextAnswer.subarray(20, serverDhInnerReader.pos)))) {\n throw new MtSecurityError('Step 3: invalid inner data hash')\n }\n\n mtpAssertTypeIs('auth step 3', serverDhInner, 'mt_server_DH_inner_data')\n\n if (!buffersEqual(serverDhInner.nonce, nonce)) {\n throw Error('Step 3: invalid nonce from server')\n }\n if (!buffersEqual(serverDhInner.serverNonce, resPq.serverNonce)) {\n throw Error('Step 3: invalid server nonce from server')\n }\n\n const dhPrime = bufferToBigInt(serverDhInner.dhPrime)\n const timeOffset = Math.floor(Date.now() / 1000) - serverDhInner.serverTime\n\n const g = BigInt(serverDhInner.g)\n const gA = bufferToBigInt(serverDhInner.gA)\n\n checkDhPrime(crypto, log, dhPrime, serverDhInner.g)\n\n let retryId = Long.ZERO\n const serverSalt = xorBuffer(newNonce.subarray(0, 8), resPq.serverNonce.subarray(0, 8))\n\n for (;;) {\n const b = bufferToBigInt(crypto.randomBytes(256))\n const gB = bigIntModPow(g, b, dhPrime)\n\n const authKey = bigIntToBuffer(bigIntModPow(gA, b, dhPrime))\n const authKeyAuxHash = crypto.sha1(authKey).subarray(0, 8)\n\n // validate DH params\n if (g <= 1 || g >= dhPrime - 1n) {\n throw new MtSecurityError('g is not within (1, dh_prime - 1)')\n }\n if (gA <= 1 || gA >= dhPrime - 1n) {\n throw new MtSecurityError('g_a is not within (1, dh_prime - 1)')\n }\n if (gB <= 1 || gB >= dhPrime - 1n) {\n throw new MtSecurityError('g_b is not within (1, dh_prime - 1)')\n }\n\n if (gA <= DH_SAFETY_RANGE || gA >= dhPrime - DH_SAFETY_RANGE) {\n throw new MtSecurityError('g_a is not within (2^{2048-64}, dh_prime - 2^{2048-64})')\n }\n if (gB <= DH_SAFETY_RANGE || gB >= dhPrime - DH_SAFETY_RANGE) {\n throw new MtSecurityError('g_b is not within (2^{2048-64}, dh_prime - 2^{2048-64})')\n }\n\n const gB_ = bigIntToBuffer(gB, 0, false)\n\n // Step 4: send client DH\n const clientDhInner: mtp.RawMt_client_DH_inner_data = {\n _: 'mt_client_DH_inner_data',\n nonce,\n serverNonce: resPq.serverNonce,\n retryId,\n gB: gB_,\n }\n let innerLength = TlSerializationCounter.countNeededBytes(writerMap, clientDhInner) + 20 // for hash\n const innerPaddingLength = innerLength % 16\n if (innerPaddingLength > 0) innerLength += 16 - innerPaddingLength\n\n const clientDhInnerWriter = TlBinaryWriter.alloc(writerMap, innerLength)\n clientDhInnerWriter.pos = 20\n clientDhInnerWriter.object(clientDhInner)\n const clientDhInnerHash = crypto.sha1(clientDhInnerWriter.uint8View.subarray(20, clientDhInnerWriter.pos))\n clientDhInnerWriter.pos = 0\n clientDhInnerWriter.raw(clientDhInnerHash)\n\n log.debug('sending client DH (timeOffset = %d)', timeOffset)\n\n const clientDhEncrypted = ige.encrypt(clientDhInnerWriter.uint8View)\n await sendPlainMessage({\n _: 'mt_set_client_DH_params',\n nonce,\n serverNonce: resPq.serverNonce,\n encryptedData: clientDhEncrypted,\n })\n\n const dhGen = await readNext()\n\n if (!mtp.isAnySet_client_DH_params_answer(dhGen)) {\n throw new MtTypeAssertionError('auth step 4', 'set_client_DH_params_answer', dhGen._)\n }\n\n if (!buffersEqual(dhGen.nonce, nonce)) {\n throw Error('Step 4: invalid nonce from server')\n }\n if (!buffersEqual(dhGen.serverNonce, resPq.serverNonce)) {\n throw Error('Step 4: invalid server nonce from server')\n }\n\n log.debug('DH result: %s', dhGen._)\n\n if (dhGen._ === 'mt_dh_gen_fail') {\n // in theory i would be supposed to calculate newNonceHash, but why, we are failing anyway\n throw new MtTypeAssertionError('auth step 4', '!mt_dh_gen_fail', dhGen._)\n }\n\n if (dhGen._ === 'mt_dh_gen_retry') {\n const expectedHash = crypto.sha1(concatBuffers([newNonce, new Uint8Array([2]), authKeyAuxHash]))\n\n if (!buffersEqual(expectedHash.subarray(4, 20), dhGen.newNonceHash2)) {\n throw Error('Step 4: invalid retry nonce hash from server')\n }\n retryId = Long.fromBytesLE(authKeyAuxHash as unknown as number[])\n continue\n }\n\n if (dhGen._ !== 'mt_dh_gen_ok') throw new Error() // unreachable\n\n const expectedHash = crypto.sha1(concatBuffers([newNonce, new Uint8Array([1]), authKeyAuxHash]))\n\n if (!buffersEqual(expectedHash.subarray(4, 20), dhGen.newNonceHash1)) {\n throw Error('Step 4: invalid nonce hash from server')\n }\n\n log.info('authorization successful')\n\n const dv = dataViewFromBuffer(serverSalt)\n\n return [authKey, new Long(dv.getInt32(0, true), dv.getInt32(4, true)), timeOffset]\n }\n}\n"]}
|
|
@@ -11,7 +11,7 @@ export class ConfigManager {
|
|
|
11
11
|
this._listeners = [];
|
|
12
12
|
}
|
|
13
13
|
get isStale() {
|
|
14
|
-
return !this._config || this._config.expires
|
|
14
|
+
return !this._config || this._config.expires <= Date.now() / 1000;
|
|
15
15
|
}
|
|
16
16
|
update(force = false) {
|
|
17
17
|
if (!force && !this.isStale)
|
|
@@ -21,6 +21,7 @@ export class ConfigManager {
|
|
|
21
21
|
return (this._updatingPromise = this._update().then((config) => {
|
|
22
22
|
if (this._destroyed)
|
|
23
23
|
return;
|
|
24
|
+
this._updatingPromise = undefined;
|
|
24
25
|
this.setConfig(config);
|
|
25
26
|
}));
|
|
26
27
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-manager.js","sourceRoot":"","sources":["../../../src/network/config-manager.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,OAAO,aAAa;IACtB,YAAoB,OAAoC;QAApC,YAAO,GAAP,OAAO,CAA6B;QAEhD,eAAU,GAAG,KAAK,CAAA;QAOlB,eAAU,GAAuC,EAAE,CAAA;IATA,CAAC;IAW5D,IAAI,OAAO;QACP,OAAO,CAAC,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,
|
|
1
|
+
{"version":3,"file":"config-manager.js","sourceRoot":"","sources":["../../../src/network/config-manager.ts"],"names":[],"mappings":"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","sourcesContent":["import { tl } from '@mtcute/tl'\n\n/**\n * Config manager is responsible for keeping\n * the current server configuration up-to-date\n * and providing methods to find the best DC\n * option for the current session.\n */\nexport class ConfigManager {\n constructor(private _update: () => Promise<tl.RawConfig>) {}\n\n private _destroyed = false\n private _config?: tl.RawConfig\n private _cdnConfig?: tl.RawCdnConfig\n\n private _updateTimeout?: NodeJS.Timeout\n private _updatingPromise?: Promise<void>\n\n private _listeners: ((config: tl.RawConfig) => void)[] = []\n\n get isStale(): boolean {\n return !this._config || this._config.expires <= Date.now() / 1000\n }\n\n update(force = false): Promise<void> {\n if (!force && !this.isStale) return Promise.resolve()\n if (this._updatingPromise) return this._updatingPromise\n\n return (this._updatingPromise = this._update().then((config) => {\n if (this._destroyed) return\n this._updatingPromise = undefined\n\n this.setConfig(config)\n }))\n }\n\n setConfig(config: tl.RawConfig): void {\n this._config = config\n\n if (this._updateTimeout) clearTimeout(this._updateTimeout)\n this._updateTimeout = setTimeout(\n () => void this.update().catch(() => {}),\n (config.expires - Date.now() / 1000) * 1000,\n )\n\n for (const cb of this._listeners) cb(config)\n }\n\n onConfigUpdate(cb: (config: tl.RawConfig) => void): void {\n this._listeners.push(cb)\n }\n\n offConfigUpdate(cb: (config: tl.RawConfig) => void): void {\n const idx = this._listeners.indexOf(cb)\n if (idx >= 0) this._listeners.splice(idx, 1)\n }\n\n getNow(): tl.RawConfig | undefined {\n return this._config\n }\n\n async get(): Promise<tl.RawConfig> {\n if (this.isStale) await this.update()\n\n return this._config!\n }\n\n destroy(): void {\n if (this._updateTimeout) clearTimeout(this._updateTimeout)\n this._listeners.length = 0\n this._destroyed = true\n }\n\n async findOption(params: {\n dcId: number\n allowIpv6?: boolean\n preferIpv6?: boolean\n allowMedia?: boolean\n preferMedia?: boolean\n cdn?: boolean\n }): Promise<tl.RawDcOption | undefined> {\n if (this.isStale) await this.update()\n\n const options = this._config!.dcOptions.filter((opt) => {\n if (opt.tcpoOnly) return false // unsupported\n if (opt.ipv6 && !params.allowIpv6) return false\n if (opt.mediaOnly && !params.allowMedia) return false\n if (opt.cdn && !params.cdn) return false\n\n return opt.id === params.dcId\n })\n\n if (params.preferMedia && params.preferIpv6) {\n const r = options.find((opt) => opt.mediaOnly && opt.ipv6)\n if (r) return r\n }\n\n if (params.preferMedia) {\n const r = options.find((opt) => opt.mediaOnly)\n if (r) return r\n }\n\n if (params.preferIpv6) {\n const r = options.find((opt) => opt.ipv6)\n if (r) return r\n }\n\n return options[0]\n }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|