From 0d97b10ff5270cfd66f152db4db35fbb7127615e Mon Sep 17 00:00:00 2001 From: alina sireneva Date: Thu, 28 Nov 2024 17:55:47 +0300 Subject: [PATCH] feat(convert): tdata conversion --- packages/convert/package.json | 8 +- packages/convert/src/index.ts | 1 + .../__fixtures__/multiacc/A7FDF864FBC10B77s | Bin 0 -> 876 bytes .../__fixtures__/multiacc/D877F783D5D3EF8Cs | Bin 0 -> 1132 bytes .../tdesktop/__fixtures__/multiacc/key_datas | Bin 0 -> 404 bytes .../__fixtures__/passcode/D877F783D5D3EF8Cs | Bin 0 -> 1132 bytes .../tdesktop/__fixtures__/passcode/key_datas | Bin 0 -> 388 bytes .../__fixtures__/simple/D877F783D5D3EF8Cs | Bin 0 -> 1132 bytes .../tdesktop/__fixtures__/simple/key_datas | Bin 0 -> 388 bytes .../tdesktop/__snapshots__/tdata.test.ts.snap | 5519 +++++++++++++++++ packages/convert/src/tdesktop/convert.ts | 73 + packages/convert/src/tdesktop/docs.md | 55 + packages/convert/src/tdesktop/index.ts | 6 + packages/convert/src/tdesktop/qt-bundle.ts | 4 + packages/convert/src/tdesktop/qt-reader.ts | 35 + packages/convert/src/tdesktop/qt-writer.ts | 31 + packages/convert/src/tdesktop/tdata.test.ts | 106 + packages/convert/src/tdesktop/tdata.ts | 494 ++ packages/convert/src/tdesktop/types.ts | 26 + packages/convert/src/utils/crypto.ts | 29 + packages/convert/src/utils/fs.ts | 6 + 21 files changed, 6390 insertions(+), 3 deletions(-) create mode 100644 packages/convert/src/tdesktop/__fixtures__/multiacc/A7FDF864FBC10B77s create mode 100644 packages/convert/src/tdesktop/__fixtures__/multiacc/D877F783D5D3EF8Cs create mode 100644 packages/convert/src/tdesktop/__fixtures__/multiacc/key_datas create mode 100644 packages/convert/src/tdesktop/__fixtures__/passcode/D877F783D5D3EF8Cs create mode 100644 packages/convert/src/tdesktop/__fixtures__/passcode/key_datas create mode 100644 packages/convert/src/tdesktop/__fixtures__/simple/D877F783D5D3EF8Cs create mode 100644 packages/convert/src/tdesktop/__fixtures__/simple/key_datas create mode 100644 packages/convert/src/tdesktop/__snapshots__/tdata.test.ts.snap create mode 100644 packages/convert/src/tdesktop/convert.ts create mode 100644 packages/convert/src/tdesktop/docs.md create mode 100644 packages/convert/src/tdesktop/index.ts create mode 100644 packages/convert/src/tdesktop/qt-bundle.ts create mode 100644 packages/convert/src/tdesktop/qt-reader.ts create mode 100644 packages/convert/src/tdesktop/qt-writer.ts create mode 100644 packages/convert/src/tdesktop/tdata.test.ts create mode 100644 packages/convert/src/tdesktop/tdata.ts create mode 100644 packages/convert/src/tdesktop/types.ts create mode 100644 packages/convert/src/utils/crypto.ts create mode 100644 packages/convert/src/utils/fs.ts diff --git a/packages/convert/package.json b/packages/convert/package.json index 9b0fb642..9d35095e 100644 --- a/packages/convert/package.json +++ b/packages/convert/package.json @@ -10,10 +10,12 @@ "exports": "./src/index.ts", "dependencies": { "@mtcute/core": "workspace:^", - "@fuman/utils": "https://pkg.pr.new/teidesu/fuman/@fuman/utils@6017eb4", - "@fuman/net": "https://pkg.pr.new/teidesu/fuman/@fuman/net@6017eb4" + "@fuman/utils": "https://pkg.pr.new/teidesu/fuman/@fuman/utils@b0c74cb", + "@fuman/net": "https://pkg.pr.new/teidesu/fuman/@fuman/net@b0c74cb", + "@fuman/io": "https://pkg.pr.new/teidesu/fuman/@fuman/io@b0c74cb" }, "devDependencies": { - "@mtcute/test": "workspace:^" + "@mtcute/test": "workspace:^", + "@mtcute/node": "workspace:^" } } diff --git a/packages/convert/src/index.ts b/packages/convert/src/index.ts index f989f7a8..efa91ec9 100644 --- a/packages/convert/src/index.ts +++ b/packages/convert/src/index.ts @@ -3,3 +3,4 @@ export * from './gramjs/index.js' export * from './mtkruto/index.js' export * from './pyrogram/index.js' export * from './telethon/index.js' +export * from './tdesktop/index.js' diff --git a/packages/convert/src/tdesktop/__fixtures__/multiacc/A7FDF864FBC10B77s b/packages/convert/src/tdesktop/__fixtures__/multiacc/A7FDF864FBC10B77s new file mode 100644 index 0000000000000000000000000000000000000000..31e92220ed6ea9592e8ece4fd7bbbf24691e12aa GIT binary patch literal 876 zcmV-y1C#tzL`EcoYD@qC00U6q!alDpYI^jzkYtHqh_-Gwaql1mMd74tRVgZh#eHX~ zIy>uUC&h~F?4+ku)?xlUB+C6tx#h@j$BNek^*nK!HU8{(j7ETWFAd9Uz%qQPY}%3+ z^r!1pv#HiBr3bh>W)H=94RQE4L!qw*yZn%zM=QONZdlg-1NS( z=vCtN<)G7ylL0yx|5RY&_uSJGr%aW!!KFc5j+QOFY<4EtCI4{LkPmw028#<3s{;5GLYmtr^3oB}?YN?pg-{-sJ_4=aU z0^K<+sONDq4$%0+mrt*b;7uVH)0o^oV zUD1VniOxNTnkkSd&Hl^SI|!Ed^HK{mOq6WHKr0Y#;;E!@Tx`a`XX-ZCc*#FlH^iz+ zhO|N6KaaTW=q&I&nQKfKH6x0%=PWs4TUDMOAZ4S6f22sGS6=7B_+9gFll2 zuS}jx=`Y$CIyld>2BYBT39r=c)%z`Dg$vQ6)*~3|^2c5u@)T?H>p1~$-rMC32gxn- zA5%j)X%Z9I_1@A^=fjMCE|PhiOZ!oP_hdjqv<4VllCP~rVqyLN!)00En6bT_adkb! z$~`02u-e-o?oaqC{8Ie)yN7JSsJw8yo{+^b0Y8wE*nH1m!V5~Lg;1OR|UICfLsq0+OaRQo-)@FdU-K$VUB>tg9`?i3;n{9YMuv2i{ zhL>iNU@k7AtI^7`M$oZhu|pjpAL4ecCKvuBiJY_h=Q~W;eC3;ZOfVf((JiVccBlP3 z{*FK*pNdcbnjU7W+AjxkiTol2lQir*KgoG4qUteOx57-9VTC)n*0k^qj>%<}+bfb9 zlUK2eJ?Mn(bxVnP;33D={xJD(d?2EFn59qGH>!EFCARLvu=7KdwuCBTfivG|wl`VN C;>B(N literal 0 HcmV?d00001 diff --git a/packages/convert/src/tdesktop/__fixtures__/multiacc/D877F783D5D3EF8Cs b/packages/convert/src/tdesktop/__fixtures__/multiacc/D877F783D5D3EF8Cs new file mode 100644 index 0000000000000000000000000000000000000000..5804c37e6150a83473522c444a709287f07986d6 GIT binary patch literal 1132 zcmV-y1e5zzL`EcoYD@qC00dBoktZi;BHmC26z7?=4xo0)pfG)cP#otBTi$?S5u=E0 zZ>f$laz+(w9k2p2*Y1&~580v{UDGjlP<^qfZ$V2T#S9ZEU4$gn zghh3)B?X3SUXyBTDS>XT3FJGgR?IrH6%!wV3<6{@J(k&t*E+|*Q=?t%2nU@-hjfqu z3ibf^32-hi>A99xHW3y(zf}v5yb@}vu0MBXK;n_fPBZSJ2g~>aC>9P_^=ocC{+JoU zPQNi&QReJC2=v)-&JQuLK$72TDsA4zbUs<%Nkq^`q~}{Z9}Tuqj2& zB6C(FGNbM(?K@Em@-e;K`0OKB_yYbMdI-dUs6=14xoPzXR!RF3qstu-GqBaGFcI~DZIP|O$dz+`a1o$a6(+}Oa0_YuFK_pCCZ^^?j2 zsYDc27K}Hy+CneMxFSblBkJ*d6?{4rRn@7bDvukLz0Y~v8=xgWDuJ?j`BNmmwL?r8 z+W+QxW!d)NaXWRa0-5F#^U6K-fmPr@SY(^7<-d?1+yKjiEEOrWpc6 z6$l-PJL7ykwtLu$KB}vAYtR&D8{h(HMQ*E(%>)x!`P~hsyU=u8#QOtE5jJR97T{hm z^QPp!71W$D->lK`QlF~q`kz$OgP&!82j4DgU`$B8h9ki%-k)PbAMu?96!Z(?)Q{^; zhf>f7`=Vb5sRCieaic)nE~fjme8uno$ci#Ac<744HE~x zz#tS9KEQ!Lc<2%N??S$zxdCBSyofOzsY5zR8AtCj4N{;NL+mCElq;l9U8N-<>J;`O zWe+>6y@a6*ou5%~Oh^bhlBK=hlD5(ix*i)`s-ZYx$=WJi#{6>qqtOoYan!wrPi)9p zs#aRW&cuGqn0P(+^W0IliHxed8V3!C{M`twYA@rqjVcP!*n7oVZh+YuE9P! y^6ky)A%|#+9l&P9&M7ncrF(B1bXKXA-ql>*;tvOTA@h}2(E49tO~|?uIAw#MJsFVz literal 0 HcmV?d00001 diff --git a/packages/convert/src/tdesktop/__fixtures__/multiacc/key_datas b/packages/convert/src/tdesktop/__fixtures__/multiacc/key_datas new file mode 100644 index 0000000000000000000000000000000000000000..a256631e8ec89cfa9c2c9608c8bc5808f136fbd8 GIT binary patch literal 404 zcmV;F0c-wLL`EcoYD@qC001DDt2f6~o}qEjLK<%Pvmv{gG)o=)hxm5c`b+Wzb@> zhN|9&wevtV>A823wZ~6%4zD{J#T`%U(LqChY;aW^mtvtCSY_a-236kmxM=yG{5>t# zf8WuVN{+GR>e%V*3m+?e>pXTrT?0&U24Yd}nfA?C#`C8S2B1kWzK&L|sPf^~gaisX zbEFlGw_{;dxtow8xCbRnEk`WM3bIXwI4$6fE=#!-> zLa%NLnc)|rYXBLxbJ6d8SmJ2Z{f&Yk9gVrUPI7<^)d?*h099=TM1z%1>rWAULTfEV zl2OxJb}1QOz-y@7+e%iIQhNl#py&aXpmRvxl{M@D001!0ETxr}NUu>VJE95~Lr5*g yR{1pqU^MR%)5=rteAd^U5q8eFzc-j+>LoDy)7QgJxR8Ey_6$^g$sBEGs4R}1OvaA@ literal 0 HcmV?d00001 diff --git a/packages/convert/src/tdesktop/__fixtures__/passcode/D877F783D5D3EF8Cs b/packages/convert/src/tdesktop/__fixtures__/passcode/D877F783D5D3EF8Cs new file mode 100644 index 0000000000000000000000000000000000000000..5804c37e6150a83473522c444a709287f07986d6 GIT binary patch literal 1132 zcmV-y1e5zzL`EcoYD@qC00dBoktZi;BHmC26z7?=4xo0)pfG)cP#otBTi$?S5u=E0 zZ>f$laz+(w9k2p2*Y1&~580v{UDGjlP<^qfZ$V2T#S9ZEU4$gn zghh3)B?X3SUXyBTDS>XT3FJGgR?IrH6%!wV3<6{@J(k&t*E+|*Q=?t%2nU@-hjfqu z3ibf^32-hi>A99xHW3y(zf}v5yb@}vu0MBXK;n_fPBZSJ2g~>aC>9P_^=ocC{+JoU zPQNi&QReJC2=v)-&JQuLK$72TDsA4zbUs<%Nkq^`q~}{Z9}Tuqj2& zB6C(FGNbM(?K@Em@-e;K`0OKB_yYbMdI-dUs6=14xoPzXR!RF3qstu-GqBaGFcI~DZIP|O$dz+`a1o$a6(+}Oa0_YuFK_pCCZ^^?j2 zsYDc27K}Hy+CneMxFSblBkJ*d6?{4rRn@7bDvukLz0Y~v8=xgWDuJ?j`BNmmwL?r8 z+W+QxW!d)NaXWRa0-5F#^U6K-fmPr@SY(^7<-d?1+yKjiEEOrWpc6 z6$l-PJL7ykwtLu$KB}vAYtR&D8{h(HMQ*E(%>)x!`P~hsyU=u8#QOtE5jJR97T{hm z^QPp!71W$D->lK`QlF~q`kz$OgP&!82j4DgU`$B8h9ki%-k)PbAMu?96!Z(?)Q{^; zhf>f7`=Vb5sRCieaic)nE~fjme8uno$ci#Ac<744HE~x zz#tS9KEQ!Lc<2%N??S$zxdCBSyofOzsY5zR8AtCj4N{;NL+mCElq;l9U8N-<>J;`O zWe+>6y@a6*ou5%~Oh^bhlBK=hlD5(ix*i)`s-ZYx$=WJi#{6>qqtOoYan!wrPi)9p zs#aRW&cuGqn0P(+^W0IliHxed8V3!C{M`twYA@rqjVcP!*n7oVZh+YuE9P! y^6ky)A%|#+9l&P9&M7ncrF(B1bXKXA-ql>*;tvOTA@h}2(E49tO~|?uIAw#MJsFVz literal 0 HcmV?d00001 diff --git a/packages/convert/src/tdesktop/__fixtures__/passcode/key_datas b/packages/convert/src/tdesktop/__fixtures__/passcode/key_datas new file mode 100644 index 0000000000000000000000000000000000000000..fdd52a459783e8206d270bf4e1200f90a17cdc49 GIT binary patch literal 388 zcmV-~0ek*bL`EcoYD@qC001C^knN8*D0`;A;w15x3QOQB&rv*sa+qd1jQO$B9*f-o z00AI^?wkA8bv@lqY!x|y%T^z#b6YC~jrDB@&2Z#VF$C!F> zy1o9&%4+kGS|KAU;`wD7tkDP&G0TLmejDJTm2KqFrUw#-sLhBVP=}flMLpRaazOUk#fK|56-jGo00--&Sv4;L6Q#L*_p{9?;};wcvE~2PjE&py25N_pU0K(_j+MqVPr||#sRj5leON=}{7p!;s4OL@ za#Q?6<}^#DhnyPD){-C-d5(75JxK@GIo#+N@~5%&LklK`Dx1u#-e6v5!4^+!(X-c5 z>4jVJB|tf6%+D6%iDh<)7zTF?OTxl!Wl3Vd;mzRy001Bgo@vI|d1(@^)})E%x$)iQ iIzHw+hF!v5#Af0mI+Lanh{l-qPf$laz+(w9k2p2*Y1&~580v{UDGjlP<^qfZ$V2T#S9ZEU4$gn zghh3)B?X3SUXyBTDS>XT3FJGgR?IrH6%!wV3<6{@J(k&t*E+|*Q=?t%2nU@-hjfqu z3ibf^32-hi>A99xHW3y(zf}v5yb@}vu0MBXK;n_fPBZSJ2g~>aC>9P_^=ocC{+JoU zPQNi&QReJC2=v)-&JQuLK$72TDsA4zbUs<%Nkq^`q~}{Z9}Tuqj2& zB6C(FGNbM(?K@Em@-e;K`0OKB_yYbMdI-dUs6=14xoPzXR!RF3qstu-GqBaGFcI~DZIP|O$dz+`a1o$a6(+}Oa0_YuFK_pCCZ^^?j2 zsYDc27K}Hy+CneMxFSblBkJ*d6?{4rRn@7bDvukLz0Y~v8=xgWDuJ?j`BNmmwL?r8 z+W+QxW!d)NaXWRa0-5F#^U6K-fmPr@SY(^7<-d?1+yKjiEEOrWpc6 z6$l-PJL7ykwtLu$KB}vAYtR&D8{h(HMQ*E(%>)x!`P~hsyU=u8#QOtE5jJR97T{hm z^QPp!71W$D->lK`QlF~q`kz$OgP&!82j4DgU`$B8h9ki%-k)PbAMu?96!Z(?)Q{^; zhf>f7`=Vb5sRCieaic)nE~fjme8uno$ci#Ac<744HE~x zz#tS9KEQ!Lc<2%N??S$zxdCBSyofOzsY5zR8AtCj4N{;NL+mCElq;l9U8N-<>J;`O zWe+>6y@a6*ou5%~Oh^bhlBK=hlD5(ix*i)`s-ZYx$=WJi#{6>qqtOoYan!wrPi)9p zs#aRW&cuGqn0P(+^W0IliHxed8V3!C{M`twYA@rqjVcP!*n7oVZh+YuE9P! y^6ky)A%|#+9l&P9&M7ncrF(B1bXKXA-ql>*;tvOTA@h}2(E49tO~|?uIAw#MJsFVz literal 0 HcmV?d00001 diff --git a/packages/convert/src/tdesktop/__fixtures__/simple/key_datas b/packages/convert/src/tdesktop/__fixtures__/simple/key_datas new file mode 100644 index 0000000000000000000000000000000000000000..342588be2c06ada16f4c8620a272099da88f9c4b GIT binary patch literal 388 zcmV-~0ek*bL`EcoYD@qC001EW9ef8X=Sy+~4aBKOHr>inKMqUlfKa*Qd7(jDD)`F) z00AJVX=+~7kD}(MEfiDGO^EI7`*pcgrz6JzW(!0+oD&i*OHgQip^2o5285X52!2^< zP1J+xnm{lT&&HJ=`3l1oOIC6WaWMNzzI`}cDU>${Lo49@Ft>nD03Dq}Ti(P>0+byJ zfKku|Wneg}#Qh#5q5gC3iC)*`9sFP(i5gwAsgamBjJe7hC>8F6zvivN`##DbA`GjN zR#x(?UPsMSWrTDBiqy+PSmt*=SD4Q9hR^;3l&9TuZZMdzd!<(8-D}c^#usQX8Qa#W zPtGf`{9|~X_(NF&qY26gi?%^#%f_|AILWCpndz1e>40YvF~a#`~uL001Bgo@vI|d1(@^)})E%x$)iQ iIzHw+hF!v5#Af0mI+Lb250w3_aXUX--71R)b9G`{k+j?Z literal 0 HcmV?d00001 diff --git a/packages/convert/src/tdesktop/__snapshots__/tdata.test.ts.snap b/packages/convert/src/tdesktop/__snapshots__/tdata.test.ts.snap new file mode 100644 index 00000000..3e51108c --- /dev/null +++ b/packages/convert/src/tdesktop/__snapshots__/tdata.test.ts.snap @@ -0,0 +1,5519 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`tdata > should read multi-account tdata 1`] = ` +{ + "auth0": { + "authKeys": [ + { + "dcId": 1, + "key": Uint8Array [ + 44, + 28, + 216, + 145, + 35, + 120, + 65, + 203, + 197, + 50, + 153, + 251, + 232, + 64, + 220, + 169, + 171, + 232, + 65, + 163, + 230, + 226, + 210, + 250, + 213, + 141, + 64, + 230, + 90, + 134, + 168, + 121, + 215, + 76, + 21, + 104, + 18, + 209, + 195, + 48, + 37, + 146, + 115, + 253, + 26, + 109, + 183, + 77, + 134, + 129, + 51, + 194, + 195, + 100, + 141, + 127, + 26, + 129, + 251, + 186, + 186, + 162, + 247, + 0, + 89, + 221, + 148, + 217, + 86, + 195, + 47, + 71, + 198, + 157, + 47, + 239, + 205, + 106, + 184, + 173, + 66, + 105, + 251, + 1, + 20, + 203, + 48, + 61, + 248, + 90, + 184, + 180, + 174, + 192, + 170, + 39, + 215, + 72, + 215, + 100, + 82, + 130, + 231, + 118, + 171, + 221, + 198, + 190, + 32, + 204, + 94, + 38, + 187, + 226, + 161, + 133, + 198, + 185, + 221, + 135, + 24, + 6, + 105, + 52, + 247, + 219, + 195, + 246, + 185, + 119, + 101, + 109, + 36, + 143, + 191, + 65, + 203, + 216, + 93, + 10, + 88, + 121, + 157, + 152, + 224, + 143, + 103, + 74, + 243, + 99, + 183, + 122, + 198, + 154, + 112, + 85, + 155, + 133, + 96, + 110, + 58, + 169, + 142, + 56, + 197, + 211, + 177, + 56, + 5, + 115, + 60, + 10, + 243, + 133, + 55, + 204, + 16, + 112, + 106, + 141, + 248, + 65, + 113, + 32, + 19, + 199, + 60, + 213, + 27, + 202, + 141, + 154, + 175, + 160, + 233, + 169, + 255, + 51, + 94, + 69, + 6, + 123, + 198, + 222, + 168, + 204, + 28, + 180, + 220, + 27, + 48, + 206, + 45, + 201, + 6, + 39, + 5, + 248, + 181, + 42, + 193, + 104, + 88, + 0, + 231, + 196, + 67, + 102, + 29, + 28, + 253, + 173, + 130, + 218, + 253, + 238, + 215, + 151, + 9, + 4, + 29, + 105, + 119, + 101, + 121, + 171, + 49, + 119, + 216, + 53, + 68, + 48, + 224, + 17, + 115, + 29, + ], + }, + { + "dcId": 2, + "key": Uint8Array [ + 73, + 77, + 244, + 157, + 119, + 147, + 12, + 196, + 245, + 200, + 23, + 94, + 249, + 171, + 93, + 102, + 187, + 25, + 155, + 172, + 1, + 115, + 72, + 228, + 40, + 135, + 83, + 253, + 179, + 49, + 175, + 230, + 185, + 194, + 224, + 112, + 178, + 125, + 77, + 8, + 38, + 143, + 21, + 14, + 134, + 31, + 138, + 169, + 128, + 113, + 1, + 191, + 178, + 12, + 87, + 83, + 8, + 45, + 103, + 118, + 67, + 111, + 20, + 213, + 188, + 26, + 239, + 59, + 8, + 238, + 26, + 179, + 28, + 90, + 210, + 243, + 23, + 141, + 159, + 136, + 61, + 146, + 129, + 13, + 190, + 189, + 241, + 213, + 104, + 201, + 18, + 27, + 202, + 124, + 214, + 60, + 243, + 225, + 238, + 173, + 70, + 255, + 207, + 139, + 148, + 177, + 88, + 227, + 72, + 88, + 173, + 216, + 119, + 231, + 110, + 129, + 155, + 35, + 151, + 121, + 133, + 203, + 37, + 251, + 226, + 0, + 118, + 173, + 15, + 201, + 85, + 101, + 198, + 56, + 142, + 110, + 50, + 21, + 19, + 10, + 35, + 255, + 253, + 215, + 107, + 92, + 28, + 208, + 0, + 51, + 55, + 81, + 48, + 247, + 183, + 24, + 213, + 52, + 94, + 114, + 204, + 198, + 110, + 247, + 102, + 103, + 156, + 13, + 241, + 1, + 89, + 131, + 226, + 142, + 93, + 185, + 83, + 181, + 86, + 67, + 15, + 168, + 39, + 253, + 124, + 203, + 251, + 110, + 102, + 163, + 92, + 231, + 29, + 171, + 62, + 72, + 159, + 233, + 251, + 185, + 9, + 59, + 234, + 172, + 133, + 226, + 112, + 82, + 23, + 151, + 158, + 85, + 66, + 124, + 254, + 138, + 81, + 141, + 223, + 212, + 205, + 107, + 97, + 153, + 126, + 228, + 45, + 179, + 26, + 79, + 26, + 76, + 241, + 194, + 176, + 202, + 153, + 201, + 241, + 43, + 249, + 82, + 101, + 154, + 93, + 161, + 247, + 221, + 244, + 147, + 109, + 45, + 216, + 215, + 218, + 52, + ], + }, + { + "dcId": 4, + "key": Uint8Array [ + 39, + 185, + 106, + 207, + 146, + 254, + 151, + 89, + 137, + 32, + 250, + 152, + 121, + 120, + 109, + 154, + 193, + 40, + 252, + 227, + 224, + 129, + 94, + 106, + 111, + 228, + 92, + 62, + 64, + 83, + 185, + 53, + 153, + 11, + 180, + 147, + 47, + 72, + 72, + 165, + 174, + 94, + 104, + 250, + 90, + 90, + 198, + 227, + 27, + 7, + 72, + 219, + 93, + 224, + 245, + 246, + 234, + 119, + 151, + 169, + 57, + 29, + 199, + 173, + 213, + 37, + 190, + 254, + 143, + 138, + 127, + 51, + 205, + 20, + 40, + 6, + 46, + 21, + 8, + 216, + 28, + 235, + 247, + 66, + 167, + 229, + 189, + 251, + 220, + 146, + 96, + 49, + 1, + 17, + 75, + 194, + 40, + 2, + 48, + 232, + 136, + 213, + 202, + 190, + 114, + 183, + 46, + 6, + 107, + 205, + 107, + 96, + 65, + 79, + 175, + 223, + 77, + 191, + 233, + 62, + 59, + 245, + 56, + 36, + 174, + 138, + 129, + 34, + 216, + 220, + 156, + 231, + 47, + 81, + 159, + 115, + 40, + 250, + 113, + 162, + 238, + 139, + 126, + 179, + 254, + 242, + 103, + 77, + 206, + 191, + 248, + 63, + 60, + 209, + 189, + 116, + 30, + 74, + 160, + 76, + 213, + 227, + 15, + 90, + 253, + 92, + 231, + 250, + 82, + 174, + 76, + 64, + 81, + 224, + 73, + 35, + 253, + 147, + 137, + 236, + 102, + 5, + 135, + 143, + 4, + 57, + 100, + 116, + 83, + 117, + 199, + 42, + 169, + 57, + 43, + 172, + 25, + 86, + 84, + 55, + 187, + 117, + 88, + 195, + 73, + 183, + 232, + 4, + 172, + 18, + 208, + 68, + 69, + 23, + 183, + 195, + 242, + 73, + 104, + 186, + 36, + 103, + 24, + 25, + 105, + 252, + 200, + 15, + 179, + 140, + 145, + 137, + 132, + 40, + 244, + 176, + 206, + 41, + 107, + 103, + 51, + 95, + 161, + 123, + 62, + 129, + 19, + 141, + 81, + 206, + 112, + 71, + 15, + 210, + 93, + 168, + ], + }, + { + "dcId": 5, + "key": Uint8Array [ + 73, + 36, + 12, + 6, + 143, + 43, + 71, + 187, + 119, + 132, + 128, + 73, + 63, + 44, + 111, + 107, + 165, + 125, + 202, + 207, + 232, + 156, + 236, + 81, + 149, + 152, + 105, + 168, + 188, + 58, + 142, + 238, + 182, + 205, + 113, + 166, + 200, + 35, + 21, + 170, + 133, + 186, + 43, + 191, + 211, + 111, + 71, + 142, + 19, + 241, + 182, + 231, + 243, + 167, + 95, + 209, + 99, + 121, + 249, + 2, + 7, + 119, + 96, + 1, + 57, + 240, + 76, + 86, + 2, + 38, + 123, + 55, + 99, + 184, + 103, + 223, + 103, + 193, + 46, + 21, + 233, + 161, + 200, + 30, + 145, + 253, + 44, + 138, + 186, + 95, + 120, + 16, + 189, + 6, + 168, + 143, + 87, + 162, + 170, + 181, + 50, + 165, + 237, + 62, + 193, + 75, + 128, + 236, + 19, + 73, + 96, + 11, + 184, + 177, + 238, + 96, + 90, + 206, + 146, + 114, + 78, + 20, + 177, + 164, + 57, + 158, + 64, + 129, + 147, + 15, + 75, + 159, + 37, + 130, + 233, + 154, + 164, + 80, + 8, + 114, + 188, + 220, + 76, + 167, + 57, + 220, + 129, + 139, + 174, + 113, + 97, + 85, + 105, + 140, + 30, + 156, + 183, + 71, + 142, + 47, + 167, + 170, + 133, + 16, + 119, + 252, + 139, + 189, + 52, + 82, + 40, + 164, + 65, + 178, + 184, + 218, + 30, + 236, + 220, + 5, + 126, + 33, + 177, + 96, + 83, + 158, + 152, + 10, + 90, + 178, + 95, + 143, + 214, + 111, + 7, + 13, + 1, + 128, + 162, + 127, + 44, + 123, + 238, + 251, + 49, + 2, + 234, + 237, + 151, + 203, + 165, + 46, + 219, + 94, + 143, + 21, + 97, + 238, + 171, + 174, + 13, + 115, + 250, + 76, + 193, + 247, + 27, + 77, + 201, + 111, + 98, + 88, + 175, + 46, + 84, + 119, + 96, + 255, + 157, + 109, + 240, + 174, + 54, + 220, + 150, + 135, + 250, + 34, + 157, + 61, + 241, + 231, + 36, + 124, + 195, + 216, + ], + }, + ], + "authKeysToDestroy": [], + "mainDcId": 1, + "userId": Long { + "high": 0, + "low": 1787945512, + "unsigned": false, + }, + }, + "auth1": { + "authKeys": [ + { + "dcId": 1, + "key": Uint8Array [ + 80, + 1, + 192, + 169, + 193, + 35, + 68, + 109, + 84, + 124, + 167, + 123, + 87, + 182, + 232, + 223, + 17, + 56, + 237, + 75, + 170, + 140, + 45, + 62, + 217, + 30, + 109, + 231, + 69, + 9, + 166, + 18, + 71, + 101, + 15, + 122, + 117, + 8, + 30, + 187, + 130, + 160, + 15, + 230, + 26, + 235, + 127, + 32, + 52, + 119, + 56, + 85, + 127, + 15, + 10, + 105, + 129, + 96, + 232, + 42, + 44, + 144, + 56, + 104, + 196, + 69, + 168, + 32, + 235, + 75, + 12, + 42, + 88, + 31, + 38, + 108, + 9, + 235, + 4, + 99, + 203, + 206, + 48, + 173, + 223, + 23, + 152, + 164, + 234, + 254, + 5, + 5, + 201, + 249, + 232, + 102, + 95, + 217, + 253, + 61, + 198, + 154, + 93, + 0, + 93, + 209, + 152, + 229, + 219, + 196, + 186, + 31, + 203, + 8, + 63, + 115, + 238, + 89, + 124, + 82, + 240, + 19, + 247, + 177, + 105, + 72, + 178, + 169, + 197, + 127, + 86, + 223, + 77, + 180, + 32, + 243, + 35, + 85, + 74, + 178, + 90, + 172, + 120, + 43, + 1, + 179, + 28, + 98, + 34, + 118, + 54, + 28, + 106, + 252, + 31, + 128, + 235, + 159, + 174, + 155, + 2, + 141, + 140, + 215, + 122, + 136, + 208, + 112, + 94, + 141, + 218, + 184, + 92, + 220, + 227, + 211, + 200, + 209, + 191, + 189, + 166, + 108, + 26, + 10, + 181, + 222, + 181, + 117, + 232, + 94, + 135, + 238, + 2, + 125, + 182, + 211, + 102, + 143, + 136, + 79, + 21, + 54, + 60, + 183, + 225, + 120, + 102, + 74, + 26, + 248, + 156, + 205, + 5, + 61, + 153, + 229, + 169, + 4, + 116, + 215, + 180, + 21, + 17, + 58, + 66, + 25, + 119, + 87, + 143, + 110, + 139, + 143, + 132, + 76, + 209, + 246, + 93, + 28, + 100, + 49, + 159, + 89, + 226, + 88, + 234, + 27, + 225, + 101, + 143, + 231, + 200, + 214, + 27, + 79, + 51, + 154, + ], + }, + { + "dcId": 2, + "key": Uint8Array [ + 130, + 148, + 91, + 227, + 227, + 77, + 248, + 101, + 245, + 102, + 224, + 127, + 214, + 165, + 64, + 53, + 156, + 169, + 101, + 230, + 237, + 80, + 0, + 6, + 0, + 117, + 92, + 208, + 2, + 167, + 104, + 74, + 40, + 6, + 209, + 36, + 56, + 200, + 160, + 69, + 224, + 116, + 86, + 14, + 73, + 202, + 198, + 197, + 201, + 175, + 254, + 204, + 229, + 25, + 24, + 118, + 52, + 23, + 220, + 191, + 152, + 168, + 97, + 68, + 36, + 246, + 105, + 238, + 203, + 171, + 6, + 70, + 126, + 248, + 61, + 118, + 224, + 36, + 116, + 216, + 4, + 175, + 220, + 14, + 66, + 252, + 32, + 252, + 201, + 41, + 238, + 30, + 56, + 105, + 250, + 238, + 62, + 149, + 146, + 139, + 159, + 240, + 214, + 23, + 186, + 53, + 28, + 39, + 119, + 146, + 62, + 139, + 126, + 163, + 87, + 101, + 226, + 173, + 110, + 202, + 173, + 140, + 231, + 147, + 94, + 168, + 87, + 117, + 71, + 156, + 193, + 160, + 64, + 53, + 187, + 162, + 206, + 132, + 101, + 119, + 108, + 103, + 61, + 203, + 250, + 218, + 137, + 111, + 140, + 177, + 29, + 3, + 95, + 213, + 115, + 191, + 212, + 221, + 103, + 70, + 246, + 182, + 164, + 97, + 158, + 55, + 230, + 230, + 153, + 9, + 153, + 62, + 94, + 43, + 60, + 135, + 20, + 156, + 107, + 133, + 249, + 161, + 81, + 222, + 131, + 8, + 214, + 80, + 252, + 70, + 120, + 70, + 134, + 99, + 67, + 133, + 155, + 134, + 148, + 129, + 211, + 39, + 248, + 240, + 223, + 241, + 221, + 192, + 37, + 251, + 83, + 96, + 104, + 35, + 3, + 188, + 171, + 219, + 152, + 245, + 125, + 15, + 152, + 107, + 108, + 32, + 82, + 109, + 166, + 230, + 127, + 60, + 211, + 28, + 208, + 169, + 165, + 229, + 81, + 15, + 91, + 106, + 155, + 85, + 166, + 203, + 135, + 100, + 226, + 64, + 110, + 133, + 116, + 157, + 56, + 50, + ], + }, + { + "dcId": 5, + "key": Uint8Array [ + 55, + 197, + 142, + 23, + 130, + 175, + 198, + 240, + 86, + 50, + 122, + 158, + 236, + 252, + 5, + 212, + 40, + 211, + 193, + 60, + 106, + 80, + 78, + 26, + 103, + 114, + 162, + 74, + 239, + 118, + 178, + 11, + 212, + 168, + 205, + 109, + 254, + 104, + 211, + 117, + 154, + 120, + 123, + 220, + 82, + 152, + 229, + 148, + 47, + 185, + 174, + 21, + 166, + 15, + 137, + 47, + 174, + 13, + 112, + 191, + 82, + 196, + 15, + 221, + 123, + 20, + 220, + 251, + 157, + 20, + 2, + 132, + 193, + 172, + 32, + 226, + 76, + 171, + 134, + 189, + 75, + 8, + 182, + 191, + 106, + 94, + 196, + 100, + 30, + 132, + 21, + 56, + 247, + 177, + 149, + 163, + 174, + 66, + 190, + 0, + 134, + 74, + 170, + 230, + 48, + 159, + 150, + 143, + 218, + 25, + 80, + 121, + 156, + 207, + 235, + 162, + 222, + 108, + 119, + 137, + 39, + 131, + 139, + 154, + 81, + 185, + 201, + 45, + 102, + 76, + 242, + 193, + 127, + 56, + 57, + 130, + 122, + 140, + 252, + 59, + 36, + 177, + 14, + 13, + 170, + 153, + 227, + 176, + 134, + 91, + 23, + 182, + 226, + 173, + 8, + 204, + 13, + 117, + 108, + 118, + 95, + 51, + 112, + 197, + 218, + 28, + 69, + 95, + 211, + 227, + 228, + 139, + 30, + 6, + 142, + 105, + 230, + 254, + 39, + 0, + 214, + 244, + 216, + 55, + 161, + 94, + 155, + 124, + 106, + 198, + 197, + 168, + 77, + 53, + 53, + 219, + 221, + 24, + 34, + 33, + 65, + 13, + 94, + 126, + 87, + 220, + 193, + 49, + 227, + 15, + 15, + 8, + 108, + 201, + 82, + 43, + 211, + 139, + 225, + 2, + 197, + 142, + 210, + 141, + 59, + 79, + 24, + 119, + 143, + 9, + 255, + 116, + 187, + 226, + 59, + 226, + 220, + 234, + 140, + 5, + 4, + 163, + 24, + 250, + 102, + 210, + 162, + 70, + 25, + 17, + 194, + 78, + 22, + 11, + 101, + 22, + ], + }, + ], + "authKeysToDestroy": [], + "mainDcId": 2, + "userId": Long { + "high": 1, + "low": 1479652362, + "unsigned": false, + }, + }, + "key": { + "active": 1, + "count": 2, + "localKey": Uint8Array [ + 120, + 76, + 23, + 84, + 165, + 8, + 147, + 169, + 22, + 88, + 113, + 223, + 177, + 195, + 146, + 155, + 109, + 145, + 99, + 223, + 104, + 160, + 2, + 130, + 226, + 64, + 17, + 129, + 197, + 118, + 10, + 114, + 253, + 65, + 105, + 81, + 88, + 112, + 155, + 152, + 140, + 176, + 150, + 34, + 144, + 47, + 13, + 33, + 133, + 110, + 105, + 28, + 96, + 36, + 181, + 83, + 205, + 203, + 161, + 95, + 21, + 165, + 102, + 26, + 137, + 6, + 153, + 92, + 134, + 147, + 249, + 24, + 203, + 85, + 137, + 2, + 131, + 47, + 159, + 212, + 3, + 91, + 52, + 156, + 35, + 121, + 24, + 93, + 51, + 161, + 225, + 22, + 152, + 190, + 246, + 74, + 146, + 49, + 184, + 152, + 151, + 188, + 133, + 235, + 75, + 190, + 199, + 26, + 39, + 108, + 60, + 103, + 51, + 229, + 26, + 27, + 34, + 162, + 68, + 121, + 162, + 222, + 228, + 71, + 89, + 139, + 4, + 161, + 213, + 11, + 194, + 173, + 217, + 153, + 63, + 212, + 110, + 244, + 159, + 189, + 146, + 33, + 155, + 38, + 2, + 80, + 144, + 171, + 155, + 210, + 242, + 120, + 226, + 247, + 70, + 116, + 20, + 155, + 155, + 137, + 53, + 8, + 147, + 220, + 189, + 72, + 193, + 96, + 170, + 219, + 81, + 114, + 78, + 212, + 217, + 93, + 211, + 250, + 135, + 177, + 232, + 41, + 131, + 35, + 26, + 77, + 214, + 115, + 2, + 119, + 4, + 167, + 219, + 161, + 21, + 81, + 123, + 82, + 56, + 244, + 36, + 142, + 250, + 12, + 182, + 206, + 109, + 175, + 254, + 138, + 69, + 253, + 177, + 93, + 212, + 250, + 38, + 192, + 141, + 62, + 250, + 173, + 34, + 103, + 95, + 100, + 147, + 217, + 93, + 130, + 119, + 30, + 36, + 101, + 17, + 162, + 166, + 138, + 11, + 189, + 38, + 174, + 254, + 191, + 123, + 160, + 106, + 165, + 74, + 72, + 42, + 226, + 47, + 242, + 214, + 35, + ], + "order": [ + 0, + 1, + ], + "version": 5008003, + }, +} +`; + +exports[`tdata > should read passcode-protected tdata 1`] = ` +{ + "auth": { + "authKeys": [ + { + "dcId": 1, + "key": Uint8Array [ + 44, + 28, + 216, + 145, + 35, + 120, + 65, + 203, + 197, + 50, + 153, + 251, + 232, + 64, + 220, + 169, + 171, + 232, + 65, + 163, + 230, + 226, + 210, + 250, + 213, + 141, + 64, + 230, + 90, + 134, + 168, + 121, + 215, + 76, + 21, + 104, + 18, + 209, + 195, + 48, + 37, + 146, + 115, + 253, + 26, + 109, + 183, + 77, + 134, + 129, + 51, + 194, + 195, + 100, + 141, + 127, + 26, + 129, + 251, + 186, + 186, + 162, + 247, + 0, + 89, + 221, + 148, + 217, + 86, + 195, + 47, + 71, + 198, + 157, + 47, + 239, + 205, + 106, + 184, + 173, + 66, + 105, + 251, + 1, + 20, + 203, + 48, + 61, + 248, + 90, + 184, + 180, + 174, + 192, + 170, + 39, + 215, + 72, + 215, + 100, + 82, + 130, + 231, + 118, + 171, + 221, + 198, + 190, + 32, + 204, + 94, + 38, + 187, + 226, + 161, + 133, + 198, + 185, + 221, + 135, + 24, + 6, + 105, + 52, + 247, + 219, + 195, + 246, + 185, + 119, + 101, + 109, + 36, + 143, + 191, + 65, + 203, + 216, + 93, + 10, + 88, + 121, + 157, + 152, + 224, + 143, + 103, + 74, + 243, + 99, + 183, + 122, + 198, + 154, + 112, + 85, + 155, + 133, + 96, + 110, + 58, + 169, + 142, + 56, + 197, + 211, + 177, + 56, + 5, + 115, + 60, + 10, + 243, + 133, + 55, + 204, + 16, + 112, + 106, + 141, + 248, + 65, + 113, + 32, + 19, + 199, + 60, + 213, + 27, + 202, + 141, + 154, + 175, + 160, + 233, + 169, + 255, + 51, + 94, + 69, + 6, + 123, + 198, + 222, + 168, + 204, + 28, + 180, + 220, + 27, + 48, + 206, + 45, + 201, + 6, + 39, + 5, + 248, + 181, + 42, + 193, + 104, + 88, + 0, + 231, + 196, + 67, + 102, + 29, + 28, + 253, + 173, + 130, + 218, + 253, + 238, + 215, + 151, + 9, + 4, + 29, + 105, + 119, + 101, + 121, + 171, + 49, + 119, + 216, + 53, + 68, + 48, + 224, + 17, + 115, + 29, + ], + }, + { + "dcId": 2, + "key": Uint8Array [ + 73, + 77, + 244, + 157, + 119, + 147, + 12, + 196, + 245, + 200, + 23, + 94, + 249, + 171, + 93, + 102, + 187, + 25, + 155, + 172, + 1, + 115, + 72, + 228, + 40, + 135, + 83, + 253, + 179, + 49, + 175, + 230, + 185, + 194, + 224, + 112, + 178, + 125, + 77, + 8, + 38, + 143, + 21, + 14, + 134, + 31, + 138, + 169, + 128, + 113, + 1, + 191, + 178, + 12, + 87, + 83, + 8, + 45, + 103, + 118, + 67, + 111, + 20, + 213, + 188, + 26, + 239, + 59, + 8, + 238, + 26, + 179, + 28, + 90, + 210, + 243, + 23, + 141, + 159, + 136, + 61, + 146, + 129, + 13, + 190, + 189, + 241, + 213, + 104, + 201, + 18, + 27, + 202, + 124, + 214, + 60, + 243, + 225, + 238, + 173, + 70, + 255, + 207, + 139, + 148, + 177, + 88, + 227, + 72, + 88, + 173, + 216, + 119, + 231, + 110, + 129, + 155, + 35, + 151, + 121, + 133, + 203, + 37, + 251, + 226, + 0, + 118, + 173, + 15, + 201, + 85, + 101, + 198, + 56, + 142, + 110, + 50, + 21, + 19, + 10, + 35, + 255, + 253, + 215, + 107, + 92, + 28, + 208, + 0, + 51, + 55, + 81, + 48, + 247, + 183, + 24, + 213, + 52, + 94, + 114, + 204, + 198, + 110, + 247, + 102, + 103, + 156, + 13, + 241, + 1, + 89, + 131, + 226, + 142, + 93, + 185, + 83, + 181, + 86, + 67, + 15, + 168, + 39, + 253, + 124, + 203, + 251, + 110, + 102, + 163, + 92, + 231, + 29, + 171, + 62, + 72, + 159, + 233, + 251, + 185, + 9, + 59, + 234, + 172, + 133, + 226, + 112, + 82, + 23, + 151, + 158, + 85, + 66, + 124, + 254, + 138, + 81, + 141, + 223, + 212, + 205, + 107, + 97, + 153, + 126, + 228, + 45, + 179, + 26, + 79, + 26, + 76, + 241, + 194, + 176, + 202, + 153, + 201, + 241, + 43, + 249, + 82, + 101, + 154, + 93, + 161, + 247, + 221, + 244, + 147, + 109, + 45, + 216, + 215, + 218, + 52, + ], + }, + { + "dcId": 4, + "key": Uint8Array [ + 39, + 185, + 106, + 207, + 146, + 254, + 151, + 89, + 137, + 32, + 250, + 152, + 121, + 120, + 109, + 154, + 193, + 40, + 252, + 227, + 224, + 129, + 94, + 106, + 111, + 228, + 92, + 62, + 64, + 83, + 185, + 53, + 153, + 11, + 180, + 147, + 47, + 72, + 72, + 165, + 174, + 94, + 104, + 250, + 90, + 90, + 198, + 227, + 27, + 7, + 72, + 219, + 93, + 224, + 245, + 246, + 234, + 119, + 151, + 169, + 57, + 29, + 199, + 173, + 213, + 37, + 190, + 254, + 143, + 138, + 127, + 51, + 205, + 20, + 40, + 6, + 46, + 21, + 8, + 216, + 28, + 235, + 247, + 66, + 167, + 229, + 189, + 251, + 220, + 146, + 96, + 49, + 1, + 17, + 75, + 194, + 40, + 2, + 48, + 232, + 136, + 213, + 202, + 190, + 114, + 183, + 46, + 6, + 107, + 205, + 107, + 96, + 65, + 79, + 175, + 223, + 77, + 191, + 233, + 62, + 59, + 245, + 56, + 36, + 174, + 138, + 129, + 34, + 216, + 220, + 156, + 231, + 47, + 81, + 159, + 115, + 40, + 250, + 113, + 162, + 238, + 139, + 126, + 179, + 254, + 242, + 103, + 77, + 206, + 191, + 248, + 63, + 60, + 209, + 189, + 116, + 30, + 74, + 160, + 76, + 213, + 227, + 15, + 90, + 253, + 92, + 231, + 250, + 82, + 174, + 76, + 64, + 81, + 224, + 73, + 35, + 253, + 147, + 137, + 236, + 102, + 5, + 135, + 143, + 4, + 57, + 100, + 116, + 83, + 117, + 199, + 42, + 169, + 57, + 43, + 172, + 25, + 86, + 84, + 55, + 187, + 117, + 88, + 195, + 73, + 183, + 232, + 4, + 172, + 18, + 208, + 68, + 69, + 23, + 183, + 195, + 242, + 73, + 104, + 186, + 36, + 103, + 24, + 25, + 105, + 252, + 200, + 15, + 179, + 140, + 145, + 137, + 132, + 40, + 244, + 176, + 206, + 41, + 107, + 103, + 51, + 95, + 161, + 123, + 62, + 129, + 19, + 141, + 81, + 206, + 112, + 71, + 15, + 210, + 93, + 168, + ], + }, + { + "dcId": 5, + "key": Uint8Array [ + 73, + 36, + 12, + 6, + 143, + 43, + 71, + 187, + 119, + 132, + 128, + 73, + 63, + 44, + 111, + 107, + 165, + 125, + 202, + 207, + 232, + 156, + 236, + 81, + 149, + 152, + 105, + 168, + 188, + 58, + 142, + 238, + 182, + 205, + 113, + 166, + 200, + 35, + 21, + 170, + 133, + 186, + 43, + 191, + 211, + 111, + 71, + 142, + 19, + 241, + 182, + 231, + 243, + 167, + 95, + 209, + 99, + 121, + 249, + 2, + 7, + 119, + 96, + 1, + 57, + 240, + 76, + 86, + 2, + 38, + 123, + 55, + 99, + 184, + 103, + 223, + 103, + 193, + 46, + 21, + 233, + 161, + 200, + 30, + 145, + 253, + 44, + 138, + 186, + 95, + 120, + 16, + 189, + 6, + 168, + 143, + 87, + 162, + 170, + 181, + 50, + 165, + 237, + 62, + 193, + 75, + 128, + 236, + 19, + 73, + 96, + 11, + 184, + 177, + 238, + 96, + 90, + 206, + 146, + 114, + 78, + 20, + 177, + 164, + 57, + 158, + 64, + 129, + 147, + 15, + 75, + 159, + 37, + 130, + 233, + 154, + 164, + 80, + 8, + 114, + 188, + 220, + 76, + 167, + 57, + 220, + 129, + 139, + 174, + 113, + 97, + 85, + 105, + 140, + 30, + 156, + 183, + 71, + 142, + 47, + 167, + 170, + 133, + 16, + 119, + 252, + 139, + 189, + 52, + 82, + 40, + 164, + 65, + 178, + 184, + 218, + 30, + 236, + 220, + 5, + 126, + 33, + 177, + 96, + 83, + 158, + 152, + 10, + 90, + 178, + 95, + 143, + 214, + 111, + 7, + 13, + 1, + 128, + 162, + 127, + 44, + 123, + 238, + 251, + 49, + 2, + 234, + 237, + 151, + 203, + 165, + 46, + 219, + 94, + 143, + 21, + 97, + 238, + 171, + 174, + 13, + 115, + 250, + 76, + 193, + 247, + 27, + 77, + 201, + 111, + 98, + 88, + 175, + 46, + 84, + 119, + 96, + 255, + 157, + 109, + 240, + 174, + 54, + 220, + 150, + 135, + 250, + 34, + 157, + 61, + 241, + 231, + 36, + 124, + 195, + 216, + ], + }, + ], + "authKeysToDestroy": [], + "mainDcId": 1, + "userId": Long { + "high": 0, + "low": 1787945512, + "unsigned": false, + }, + }, + "key": { + "active": 0, + "count": 1, + "localKey": Uint8Array [ + 120, + 76, + 23, + 84, + 165, + 8, + 147, + 169, + 22, + 88, + 113, + 223, + 177, + 195, + 146, + 155, + 109, + 145, + 99, + 223, + 104, + 160, + 2, + 130, + 226, + 64, + 17, + 129, + 197, + 118, + 10, + 114, + 253, + 65, + 105, + 81, + 88, + 112, + 155, + 152, + 140, + 176, + 150, + 34, + 144, + 47, + 13, + 33, + 133, + 110, + 105, + 28, + 96, + 36, + 181, + 83, + 205, + 203, + 161, + 95, + 21, + 165, + 102, + 26, + 137, + 6, + 153, + 92, + 134, + 147, + 249, + 24, + 203, + 85, + 137, + 2, + 131, + 47, + 159, + 212, + 3, + 91, + 52, + 156, + 35, + 121, + 24, + 93, + 51, + 161, + 225, + 22, + 152, + 190, + 246, + 74, + 146, + 49, + 184, + 152, + 151, + 188, + 133, + 235, + 75, + 190, + 199, + 26, + 39, + 108, + 60, + 103, + 51, + 229, + 26, + 27, + 34, + 162, + 68, + 121, + 162, + 222, + 228, + 71, + 89, + 139, + 4, + 161, + 213, + 11, + 194, + 173, + 217, + 153, + 63, + 212, + 110, + 244, + 159, + 189, + 146, + 33, + 155, + 38, + 2, + 80, + 144, + 171, + 155, + 210, + 242, + 120, + 226, + 247, + 70, + 116, + 20, + 155, + 155, + 137, + 53, + 8, + 147, + 220, + 189, + 72, + 193, + 96, + 170, + 219, + 81, + 114, + 78, + 212, + 217, + 93, + 211, + 250, + 135, + 177, + 232, + 41, + 131, + 35, + 26, + 77, + 214, + 115, + 2, + 119, + 4, + 167, + 219, + 161, + 21, + 81, + 123, + 82, + 56, + 244, + 36, + 142, + 250, + 12, + 182, + 206, + 109, + 175, + 254, + 138, + 69, + 253, + 177, + 93, + 212, + 250, + 38, + 192, + 141, + 62, + 250, + 173, + 34, + 103, + 95, + 100, + 147, + 217, + 93, + 130, + 119, + 30, + 36, + 101, + 17, + 162, + 166, + 138, + 11, + 189, + 38, + 174, + 254, + 191, + 123, + 160, + 106, + 165, + 74, + 72, + 42, + 226, + 47, + 242, + 214, + 35, + ], + "order": [ + 0, + ], + "version": 5008003, + }, +} +`; + +exports[`tdata > should read simple tdata 1`] = ` +{ + "auth": { + "authKeys": [ + { + "dcId": 1, + "key": Uint8Array [ + 44, + 28, + 216, + 145, + 35, + 120, + 65, + 203, + 197, + 50, + 153, + 251, + 232, + 64, + 220, + 169, + 171, + 232, + 65, + 163, + 230, + 226, + 210, + 250, + 213, + 141, + 64, + 230, + 90, + 134, + 168, + 121, + 215, + 76, + 21, + 104, + 18, + 209, + 195, + 48, + 37, + 146, + 115, + 253, + 26, + 109, + 183, + 77, + 134, + 129, + 51, + 194, + 195, + 100, + 141, + 127, + 26, + 129, + 251, + 186, + 186, + 162, + 247, + 0, + 89, + 221, + 148, + 217, + 86, + 195, + 47, + 71, + 198, + 157, + 47, + 239, + 205, + 106, + 184, + 173, + 66, + 105, + 251, + 1, + 20, + 203, + 48, + 61, + 248, + 90, + 184, + 180, + 174, + 192, + 170, + 39, + 215, + 72, + 215, + 100, + 82, + 130, + 231, + 118, + 171, + 221, + 198, + 190, + 32, + 204, + 94, + 38, + 187, + 226, + 161, + 133, + 198, + 185, + 221, + 135, + 24, + 6, + 105, + 52, + 247, + 219, + 195, + 246, + 185, + 119, + 101, + 109, + 36, + 143, + 191, + 65, + 203, + 216, + 93, + 10, + 88, + 121, + 157, + 152, + 224, + 143, + 103, + 74, + 243, + 99, + 183, + 122, + 198, + 154, + 112, + 85, + 155, + 133, + 96, + 110, + 58, + 169, + 142, + 56, + 197, + 211, + 177, + 56, + 5, + 115, + 60, + 10, + 243, + 133, + 55, + 204, + 16, + 112, + 106, + 141, + 248, + 65, + 113, + 32, + 19, + 199, + 60, + 213, + 27, + 202, + 141, + 154, + 175, + 160, + 233, + 169, + 255, + 51, + 94, + 69, + 6, + 123, + 198, + 222, + 168, + 204, + 28, + 180, + 220, + 27, + 48, + 206, + 45, + 201, + 6, + 39, + 5, + 248, + 181, + 42, + 193, + 104, + 88, + 0, + 231, + 196, + 67, + 102, + 29, + 28, + 253, + 173, + 130, + 218, + 253, + 238, + 215, + 151, + 9, + 4, + 29, + 105, + 119, + 101, + 121, + 171, + 49, + 119, + 216, + 53, + 68, + 48, + 224, + 17, + 115, + 29, + ], + }, + { + "dcId": 2, + "key": Uint8Array [ + 73, + 77, + 244, + 157, + 119, + 147, + 12, + 196, + 245, + 200, + 23, + 94, + 249, + 171, + 93, + 102, + 187, + 25, + 155, + 172, + 1, + 115, + 72, + 228, + 40, + 135, + 83, + 253, + 179, + 49, + 175, + 230, + 185, + 194, + 224, + 112, + 178, + 125, + 77, + 8, + 38, + 143, + 21, + 14, + 134, + 31, + 138, + 169, + 128, + 113, + 1, + 191, + 178, + 12, + 87, + 83, + 8, + 45, + 103, + 118, + 67, + 111, + 20, + 213, + 188, + 26, + 239, + 59, + 8, + 238, + 26, + 179, + 28, + 90, + 210, + 243, + 23, + 141, + 159, + 136, + 61, + 146, + 129, + 13, + 190, + 189, + 241, + 213, + 104, + 201, + 18, + 27, + 202, + 124, + 214, + 60, + 243, + 225, + 238, + 173, + 70, + 255, + 207, + 139, + 148, + 177, + 88, + 227, + 72, + 88, + 173, + 216, + 119, + 231, + 110, + 129, + 155, + 35, + 151, + 121, + 133, + 203, + 37, + 251, + 226, + 0, + 118, + 173, + 15, + 201, + 85, + 101, + 198, + 56, + 142, + 110, + 50, + 21, + 19, + 10, + 35, + 255, + 253, + 215, + 107, + 92, + 28, + 208, + 0, + 51, + 55, + 81, + 48, + 247, + 183, + 24, + 213, + 52, + 94, + 114, + 204, + 198, + 110, + 247, + 102, + 103, + 156, + 13, + 241, + 1, + 89, + 131, + 226, + 142, + 93, + 185, + 83, + 181, + 86, + 67, + 15, + 168, + 39, + 253, + 124, + 203, + 251, + 110, + 102, + 163, + 92, + 231, + 29, + 171, + 62, + 72, + 159, + 233, + 251, + 185, + 9, + 59, + 234, + 172, + 133, + 226, + 112, + 82, + 23, + 151, + 158, + 85, + 66, + 124, + 254, + 138, + 81, + 141, + 223, + 212, + 205, + 107, + 97, + 153, + 126, + 228, + 45, + 179, + 26, + 79, + 26, + 76, + 241, + 194, + 176, + 202, + 153, + 201, + 241, + 43, + 249, + 82, + 101, + 154, + 93, + 161, + 247, + 221, + 244, + 147, + 109, + 45, + 216, + 215, + 218, + 52, + ], + }, + { + "dcId": 4, + "key": Uint8Array [ + 39, + 185, + 106, + 207, + 146, + 254, + 151, + 89, + 137, + 32, + 250, + 152, + 121, + 120, + 109, + 154, + 193, + 40, + 252, + 227, + 224, + 129, + 94, + 106, + 111, + 228, + 92, + 62, + 64, + 83, + 185, + 53, + 153, + 11, + 180, + 147, + 47, + 72, + 72, + 165, + 174, + 94, + 104, + 250, + 90, + 90, + 198, + 227, + 27, + 7, + 72, + 219, + 93, + 224, + 245, + 246, + 234, + 119, + 151, + 169, + 57, + 29, + 199, + 173, + 213, + 37, + 190, + 254, + 143, + 138, + 127, + 51, + 205, + 20, + 40, + 6, + 46, + 21, + 8, + 216, + 28, + 235, + 247, + 66, + 167, + 229, + 189, + 251, + 220, + 146, + 96, + 49, + 1, + 17, + 75, + 194, + 40, + 2, + 48, + 232, + 136, + 213, + 202, + 190, + 114, + 183, + 46, + 6, + 107, + 205, + 107, + 96, + 65, + 79, + 175, + 223, + 77, + 191, + 233, + 62, + 59, + 245, + 56, + 36, + 174, + 138, + 129, + 34, + 216, + 220, + 156, + 231, + 47, + 81, + 159, + 115, + 40, + 250, + 113, + 162, + 238, + 139, + 126, + 179, + 254, + 242, + 103, + 77, + 206, + 191, + 248, + 63, + 60, + 209, + 189, + 116, + 30, + 74, + 160, + 76, + 213, + 227, + 15, + 90, + 253, + 92, + 231, + 250, + 82, + 174, + 76, + 64, + 81, + 224, + 73, + 35, + 253, + 147, + 137, + 236, + 102, + 5, + 135, + 143, + 4, + 57, + 100, + 116, + 83, + 117, + 199, + 42, + 169, + 57, + 43, + 172, + 25, + 86, + 84, + 55, + 187, + 117, + 88, + 195, + 73, + 183, + 232, + 4, + 172, + 18, + 208, + 68, + 69, + 23, + 183, + 195, + 242, + 73, + 104, + 186, + 36, + 103, + 24, + 25, + 105, + 252, + 200, + 15, + 179, + 140, + 145, + 137, + 132, + 40, + 244, + 176, + 206, + 41, + 107, + 103, + 51, + 95, + 161, + 123, + 62, + 129, + 19, + 141, + 81, + 206, + 112, + 71, + 15, + 210, + 93, + 168, + ], + }, + { + "dcId": 5, + "key": Uint8Array [ + 73, + 36, + 12, + 6, + 143, + 43, + 71, + 187, + 119, + 132, + 128, + 73, + 63, + 44, + 111, + 107, + 165, + 125, + 202, + 207, + 232, + 156, + 236, + 81, + 149, + 152, + 105, + 168, + 188, + 58, + 142, + 238, + 182, + 205, + 113, + 166, + 200, + 35, + 21, + 170, + 133, + 186, + 43, + 191, + 211, + 111, + 71, + 142, + 19, + 241, + 182, + 231, + 243, + 167, + 95, + 209, + 99, + 121, + 249, + 2, + 7, + 119, + 96, + 1, + 57, + 240, + 76, + 86, + 2, + 38, + 123, + 55, + 99, + 184, + 103, + 223, + 103, + 193, + 46, + 21, + 233, + 161, + 200, + 30, + 145, + 253, + 44, + 138, + 186, + 95, + 120, + 16, + 189, + 6, + 168, + 143, + 87, + 162, + 170, + 181, + 50, + 165, + 237, + 62, + 193, + 75, + 128, + 236, + 19, + 73, + 96, + 11, + 184, + 177, + 238, + 96, + 90, + 206, + 146, + 114, + 78, + 20, + 177, + 164, + 57, + 158, + 64, + 129, + 147, + 15, + 75, + 159, + 37, + 130, + 233, + 154, + 164, + 80, + 8, + 114, + 188, + 220, + 76, + 167, + 57, + 220, + 129, + 139, + 174, + 113, + 97, + 85, + 105, + 140, + 30, + 156, + 183, + 71, + 142, + 47, + 167, + 170, + 133, + 16, + 119, + 252, + 139, + 189, + 52, + 82, + 40, + 164, + 65, + 178, + 184, + 218, + 30, + 236, + 220, + 5, + 126, + 33, + 177, + 96, + 83, + 158, + 152, + 10, + 90, + 178, + 95, + 143, + 214, + 111, + 7, + 13, + 1, + 128, + 162, + 127, + 44, + 123, + 238, + 251, + 49, + 2, + 234, + 237, + 151, + 203, + 165, + 46, + 219, + 94, + 143, + 21, + 97, + 238, + 171, + 174, + 13, + 115, + 250, + 76, + 193, + 247, + 27, + 77, + 201, + 111, + 98, + 88, + 175, + 46, + 84, + 119, + 96, + 255, + 157, + 109, + 240, + 174, + 54, + 220, + 150, + 135, + 250, + 34, + 157, + 61, + 241, + 231, + 36, + 124, + 195, + 216, + ], + }, + ], + "authKeysToDestroy": [], + "mainDcId": 1, + "userId": Long { + "high": 0, + "low": 1787945512, + "unsigned": false, + }, + }, + "key": { + "active": 0, + "count": 1, + "localKey": Uint8Array [ + 120, + 76, + 23, + 84, + 165, + 8, + 147, + 169, + 22, + 88, + 113, + 223, + 177, + 195, + 146, + 155, + 109, + 145, + 99, + 223, + 104, + 160, + 2, + 130, + 226, + 64, + 17, + 129, + 197, + 118, + 10, + 114, + 253, + 65, + 105, + 81, + 88, + 112, + 155, + 152, + 140, + 176, + 150, + 34, + 144, + 47, + 13, + 33, + 133, + 110, + 105, + 28, + 96, + 36, + 181, + 83, + 205, + 203, + 161, + 95, + 21, + 165, + 102, + 26, + 137, + 6, + 153, + 92, + 134, + 147, + 249, + 24, + 203, + 85, + 137, + 2, + 131, + 47, + 159, + 212, + 3, + 91, + 52, + 156, + 35, + 121, + 24, + 93, + 51, + 161, + 225, + 22, + 152, + 190, + 246, + 74, + 146, + 49, + 184, + 152, + 151, + 188, + 133, + 235, + 75, + 190, + 199, + 26, + 39, + 108, + 60, + 103, + 51, + 229, + 26, + 27, + 34, + 162, + 68, + 121, + 162, + 222, + 228, + 71, + 89, + 139, + 4, + 161, + 213, + 11, + 194, + 173, + 217, + 153, + 63, + 212, + 110, + 244, + 159, + 189, + 146, + 33, + 155, + 38, + 2, + 80, + 144, + 171, + 155, + 210, + 242, + 120, + 226, + 247, + 70, + 116, + 20, + 155, + 155, + 137, + 53, + 8, + 147, + 220, + 189, + 72, + 193, + 96, + 170, + 219, + 81, + 114, + 78, + 212, + 217, + 93, + 211, + 250, + 135, + 177, + 232, + 41, + 131, + 35, + 26, + 77, + 214, + 115, + 2, + 119, + 4, + 167, + 219, + 161, + 21, + 81, + 123, + 82, + 56, + 244, + 36, + 142, + 250, + 12, + 182, + 206, + 109, + 175, + 254, + 138, + 69, + 253, + 177, + 93, + 212, + 250, + 38, + 192, + 141, + 62, + 250, + 173, + 34, + 103, + 95, + 100, + 147, + 217, + 93, + 130, + 119, + 30, + 36, + 101, + 17, + 162, + 166, + 138, + 11, + 189, + 38, + 174, + 254, + 191, + 123, + 160, + 106, + 165, + 74, + 72, + 42, + 226, + 47, + 242, + 214, + 35, + ], + "order": [ + 0, + ], + "version": 5008003, + }, +} +`; + +exports[`tdata > should write simple tdata 1`] = ` +Map { + "/key_datas" => Uint8Array [ + 84, + 68, + 70, + 36, + 131, + 106, + 76, + 0, + 0, + 0, + 0, + 32, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 32, + 6, + 118, + 162, + 236, + 13, + 121, + 252, + 251, + 87, + 144, + 55, + 108, + 141, + 157, + 11, + 241, + 79, + 154, + 136, + 119, + 22, + 219, + 113, + 112, + 122, + 172, + 90, + 150, + 156, + 218, + 52, + 225, + 8, + 195, + 254, + 25, + 23, + 101, + 201, + 109, + 87, + 188, + 148, + 184, + 77, + 47, + 73, + 171, + 39, + 91, + 10, + 44, + 235, + 69, + 196, + 231, + 122, + 249, + 171, + 8, + 92, + 54, + 246, + 52, + 191, + 97, + 254, + 177, + 62, + 170, + 137, + 25, + 214, + 148, + 95, + 31, + 23, + 87, + 120, + 154, + 186, + 221, + 32, + 134, + 140, + 179, + 81, + 87, + 196, + 183, + 66, + 84, + 251, + 5, + 174, + 176, + 78, + 80, + 43, + 143, + 206, + 98, + 60, + 10, + 103, + 103, + 193, + 19, + 129, + 33, + 251, + 138, + 122, + 112, + 91, + 164, + 224, + 11, + 41, + 18, + 37, + 89, + 74, + 2, + 56, + 66, + 113, + 58, + 114, + 169, + 246, + 242, + 41, + 81, + 211, + 239, + 137, + 255, + 222, + 156, + 132, + 213, + 174, + 198, + 185, + 166, + 20, + 226, + 139, + 165, + 120, + 66, + 0, + 194, + 92, + 109, + 132, + 104, + 7, + 163, + 140, + 123, + 47, + 179, + 24, + 175, + 42, + 206, + 0, + 204, + 139, + 41, + 132, + 253, + 88, + 38, + 91, + 88, + 246, + 198, + 128, + 182, + 95, + 147, + 175, + 2, + 153, + 239, + 16, + 161, + 83, + 104, + 20, + 213, + 121, + 110, + 124, + 199, + 105, + 203, + 112, + 251, + 217, + 211, + 167, + 223, + 195, + 242, + 84, + 83, + 131, + 242, + 209, + 97, + 94, + 214, + 143, + 6, + 157, + 235, + 68, + 222, + 63, + 94, + 16, + 158, + 26, + 193, + 28, + 84, + 227, + 228, + 1, + 243, + 58, + 1, + 13, + 138, + 172, + 187, + 181, + 221, + 129, + 197, + 150, + 70, + 36, + 173, + 159, + 28, + 149, + 246, + 136, + 63, + 28, + 249, + 178, + 197, + 53, + 217, + 180, + 122, + 229, + 20, + 17, + 137, + 118, + 232, + 147, + 175, + 52, + 66, + 174, + 145, + 143, + 21, + 45, + 72, + 225, + 128, + 74, + 167, + 120, + 13, + 117, + 217, + 167, + 78, + 0, + 0, + 0, + 32, + 10, + 158, + 105, + 198, + 216, + 121, + 105, + 18, + 174, + 214, + 164, + 137, + 230, + 185, + 241, + 221, + 170, + 63, + 200, + 25, + 14, + 192, + 98, + 100, + 30, + 69, + 56, + 61, + 68, + 9, + 92, + 51, + 61, + 62, + 7, + 247, + 74, + 113, + 117, + 187, + 51, + 245, + 89, + 97, + 144, + 111, + 115, + 75, + ], + "/D877F783D5D3EF8Cs" => Uint8Array [ + 84, + 68, + 70, + 36, + 131, + 106, + 76, + 0, + 0, + 0, + 1, + 64, + 71, + 149, + 63, + 211, + 151, + 188, + 117, + 77, + 154, + 161, + 98, + 253, + 57, + 149, + 142, + 35, + 117, + 185, + 155, + 26, + 62, + 142, + 31, + 76, + 110, + 212, + 228, + 161, + 29, + 202, + 73, + 2, + 88, + 55, + 22, + 68, + 63, + 143, + 186, + 251, + 102, + 42, + 120, + 116, + 90, + 150, + 102, + 160, + 176, + 102, + 2, + 165, + 250, + 50, + 4, + 108, + 124, + 112, + 243, + 241, + 159, + 216, + 29, + 193, + 108, + 61, + 158, + 117, + 32, + 106, + 84, + 8, + 1, + 228, + 136, + 127, + 13, + 82, + 112, + 241, + 150, + 181, + 25, + 125, + 35, + 29, + 91, + 231, + 48, + 58, + 161, + 187, + 16, + 188, + 145, + 1, + 249, + 204, + 251, + 222, + 215, + 158, + 125, + 199, + 39, + 248, + 110, + 219, + 20, + 26, + 137, + 179, + 21, + 226, + 69, + 11, + 181, + 58, + 214, + 44, + 139, + 60, + 78, + 96, + 22, + 73, + 3, + 17, + 240, + 250, + 205, + 72, + 28, + 132, + 229, + 158, + 172, + 88, + 244, + 228, + 83, + 65, + 205, + 75, + 76, + 64, + 29, + 251, + 140, + 205, + 237, + 46, + 7, + 136, + 31, + 85, + 50, + 207, + 89, + 246, + 9, + 155, + 46, + 147, + 147, + 19, + 4, + 186, + 74, + 90, + 207, + 96, + 120, + 120, + 132, + 107, + 134, + 167, + 87, + 182, + 18, + 58, + 132, + 99, + 247, + 127, + 79, + 224, + 39, + 123, + 231, + 183, + 213, + 111, + 125, + 181, + 155, + 144, + 165, + 166, + 173, + 223, + 83, + 6, + 195, + 18, + 217, + 74, + 146, + 191, + 121, + 14, + 29, + 135, + 81, + 253, + 180, + 252, + 147, + 37, + 131, + 22, + 203, + 200, + 29, + 65, + 92, + 95, + 28, + 15, + 122, + 191, + 47, + 168, + 156, + 225, + 64, + 31, + 204, + 196, + 252, + 124, + 56, + 58, + 44, + 243, + 209, + 214, + 10, + 214, + 73, + 135, + 181, + 155, + 117, + 183, + 94, + 67, + 217, + 196, + 97, + 110, + 1, + 73, + 121, + 162, + 148, + 8, + 9, + 55, + 203, + 89, + 132, + 97, + 7, + 150, + 225, + 10, + 17, + 138, + 255, + 82, + 240, + 64, + 98, + 119, + 150, + 191, + 47, + 62, + 255, + 54, + 214, + 0, + 178, + 58, + 252, + 42, + 120, + 212, + 244, + 181, + 11, + 207, + 0, + 206, + 253, + 235, + 243, + 23, + 222, + 188, + 165, + 199, + 240, + 98, + 30, + 88, + 211, + 254, + 190, + 122, + 211, + 58, + 86, + 214, + 85, + 43, + 206, + 163, + 135, + 153, + 122, + 109, + 92, + 137, + ], +} +`; diff --git a/packages/convert/src/tdesktop/convert.ts b/packages/convert/src/tdesktop/convert.ts new file mode 100644 index 00000000..0f77c1b6 --- /dev/null +++ b/packages/convert/src/tdesktop/convert.ts @@ -0,0 +1,73 @@ +import { type StringSessionData, readStringSession } from '@mtcute/core/utils.js' +import type { MaybeArray } from '@fuman/utils' +import { Long } from '@mtcute/core' + +import { DC_MAPPING_PROD } from '../dcs.js' + +import type { TdataOptions } from './tdata.js' +import { Tdata } from './tdata.js' +import type { InputTdKeyData } from './types.js' + +export async function convertFromTdata(tdata: Tdata | TdataOptions, accountIdx = 0): Promise { + if (!(tdata instanceof Tdata)) { + tdata = await Tdata.open(tdata) + } + + const auth = await tdata.readMtpAuthorization(accountIdx) + const authKey = auth.authKeys.find(it => it.dcId === auth.mainDcId) + if (!authKey) throw new Error('Failed to find auth key') + + return { + version: 3, + primaryDcs: DC_MAPPING_PROD[auth.mainDcId], + authKey: authKey.key, + self: { + userId: auth.userId.toNumber(), + isBot: false, + isPremium: false, + usernames: [], + }, + } +} + +export async function convertToTdata( + sessions: MaybeArray, + tdata: Tdata | TdataOptions, +): Promise { + if (!Array.isArray(sessions)) { + sessions = [sessions] + } + + if (!(tdata instanceof Tdata)) { + const keyData: InputTdKeyData = { + count: sessions.length, + order: Array.from({ length: sessions.length }, (_, i) => i), + active: 0, + } + tdata = await Tdata.create({ + keyData, + ...tdata, + }) + } + + for (let i = 0; i < sessions.length; i++) { + let session = sessions[i] + + if (typeof session === 'string') { + session = readStringSession(session) + } + + await tdata.writeMtpAuthorization({ + userId: Long.fromNumber(session.self?.userId ?? 0), + mainDcId: session.primaryDcs.main.id, + authKeys: [ + { + dcId: session.primaryDcs.main.id, + key: session.authKey, + }, + ], + authKeysToDestroy: [], + }, i) + await tdata.writeEmptyMapFile(i) + } +} diff --git a/packages/convert/src/tdesktop/docs.md b/packages/convert/src/tdesktop/docs.md new file mode 100644 index 00000000..9593b827 --- /dev/null +++ b/packages/convert/src/tdesktop/docs.md @@ -0,0 +1,55 @@ +## How it works + +### Data name + +TDesktop allows for multiple "data names", which is basically +a prefix for data storage. Default one is `data`, but you can choose +any using `-key` CLI parameter. + +### Local key + +TDesktop uses something called "local key" to encrypt most of the files. +The local key itself is stored in `key_datas`, where `data` is the default +data name. That file can be passcode-protected, in which case you will +need a correct passcode to decrypt it. + +### Encryption + +Without going too deep into details, encryption used is the same +as the one used in MTProto v1 for message encryption (see +[Telegram docs](https://core.telegram.org/mtproto/description_v1#defining-aes-key-and-initialization-vector) +for details). + +There, instead of `auth_key` a local key is used, and instead of +`msg_key` lower 16 bytes of sha1 of the contents are used. + +Before encrypting (and computing sha1), content size is prepended, and +the result is padded. + +### File naming + +To name different files, TDesktop uses 8 lower bytes of md5 hash, +with nibbles switched (i.e. `0xFE => 0xEF`). + +So, for example: + +```typescript +const filename = 'data' +const md5 = crypto.md5(filename) // 8d777f385d3dfec8815d20f7496026dc +const md5Lower = md5.slice(0, 8) // 8d777f385d3dfec8 +const result = swap8(md5Lower).toUpperHex() // D877F783D5D3EF8C +``` + +`D877F783D5D3EF8C` is the folder that is most likely present in your +`tdata` folder, which is derived simply from `data` and is used +for your first account data. + +### Multi accounts + +For second, third, etc. accounts, TDesktop appends `#2`, `#3` etc. +to the base data name respectively. + +### MTProto auth keys + +Auth keys are stored in a file named same as account data folder but with +`s` appended. So, for the first account that would be `D877F783D5D3EF8Cs`. \ No newline at end of file diff --git a/packages/convert/src/tdesktop/index.ts b/packages/convert/src/tdesktop/index.ts new file mode 100644 index 00000000..04809e2b --- /dev/null +++ b/packages/convert/src/tdesktop/index.ts @@ -0,0 +1,6 @@ +import * as qt from './qt-bundle.js' + +export { qt } +export * from './convert.js' +export * from './tdata.js' +export * from './types.js' diff --git a/packages/convert/src/tdesktop/qt-bundle.ts b/packages/convert/src/tdesktop/qt-bundle.ts new file mode 100644 index 00000000..09096c62 --- /dev/null +++ b/packages/convert/src/tdesktop/qt-bundle.ts @@ -0,0 +1,4 @@ +import * as read from './qt-reader.js' +import * as write from './qt-writer.js' + +export { read, write } diff --git a/packages/convert/src/tdesktop/qt-reader.ts b/packages/convert/src/tdesktop/qt-reader.ts new file mode 100644 index 00000000..72a53431 --- /dev/null +++ b/packages/convert/src/tdesktop/qt-reader.ts @@ -0,0 +1,35 @@ +import { Long } from '@mtcute/core' +import { type ISyncReadable, read } from '@fuman/io' +import { u8 } from '@fuman/utils' + +export function readQByteArray(readable: ISyncReadable): Uint8Array { + const length = read.uint32be(readable) + if (length === 0 || length === 0xFFFFFFFF) { + return u8.empty + } + + return read.exactly(readable, length) +} + +export function readLong(readable: ISyncReadable): Long { + const high = read.int32be(readable) + const low = read.int32be(readable) + + return new Long(low, high) +} + +export function readCharArray(readable: ISyncReadable): Uint8Array { + const buf = readQByteArray(readable) + + if (buf.length > 0) { + // drop the last byte, which is always 0 + return buf.subarray(0, buf.length - 1) + } + return buf +} + +const u16Decoder = new TextDecoder('utf-16be') +export function readQString(readable: ISyncReadable): string { + const bytes = readQByteArray(readable) + return u16Decoder.decode(bytes) +} diff --git a/packages/convert/src/tdesktop/qt-writer.ts b/packages/convert/src/tdesktop/qt-writer.ts new file mode 100644 index 00000000..8911d7fe --- /dev/null +++ b/packages/convert/src/tdesktop/qt-writer.ts @@ -0,0 +1,31 @@ +import type { ISyncWritable } from '@fuman/io' +import { write } from '@fuman/io' +import { u8 } from '@fuman/utils' +import type { Long } from '@mtcute/core' + +export function writeQByteArray(into: ISyncWritable, buf: Uint8Array): void { + write.uint32be(into, buf.length) + write.bytes(into, buf) +} + +export function writeLong(into: ISyncWritable, long: Long): void { + write.int32be(into, long.high) + write.int32be(into, long.low) +} + +export function writeCharArray(into: ISyncWritable, buf: Uint8Array): void { + const bytes = u8.alloc(buf.length + 1) + bytes.set(buf) + bytes[buf.length] = 0 + + writeQByteArray(into, bytes) +} + +export function writeQString(into: ISyncWritable, str: string): void { + const length = str.length * 2 + write.uint32be(into, length) + + for (let i = 0; i < length; i++) { + write.uint16be(into, str.charCodeAt(i)) + } +} diff --git a/packages/convert/src/tdesktop/tdata.test.ts b/packages/convert/src/tdesktop/tdata.test.ts new file mode 100644 index 00000000..ec30e7ea --- /dev/null +++ b/packages/convert/src/tdesktop/tdata.test.ts @@ -0,0 +1,106 @@ +import { fileURLToPath } from 'node:url' + +import { describe, expect, it } from 'vitest' +import { Long } from '@mtcute/core' + +import type { INodeFsLike } from '../utils/fs.js' +import { getDefaultCryptoProvider } from '../utils/crypto.js' + +import { Tdata } from './tdata.js' + +class FakeFs implements INodeFsLike { + readonly files = new Map() + + async readFile(path: string): Promise { + return this.files.get(path)! + } + + async writeFile(path: string, data: Uint8Array): Promise { + this.files.set(path, data) + } + + async stat(path: string): Promise<{ size: number, lastModified: number }> { + return { + size: this.files.get(path)!.length, + lastModified: 0, + } + } + + mkdir(): Promise { + return Promise.resolve() + } +} + +describe('tdata', () => { + it('should read simple tdata', async () => { + const tdata = await Tdata.open({ + path: fileURLToPath(new URL('./__fixtures__/simple', import.meta.url)), + }) + + const auth = await tdata.readMtpAuthorization() + + expect({ auth, key: tdata.keyData }).toMatchSnapshot() + }) + + it('should read passcode-protected tdata', async () => { + const tdata = await Tdata.open({ + path: fileURLToPath(new URL('./__fixtures__/passcode', import.meta.url)), + passcode: '123123', + }) + + const auth = await tdata.readMtpAuthorization() + + expect({ auth, key: tdata.keyData }).toMatchSnapshot() + }) + + it('should throw on invalid passcode', async () => { + await expect(Tdata.open({ + path: fileURLToPath(new URL('./__fixtures__/passcode', import.meta.url)), + passcode: '123', + })).rejects.toThrow('Failed to decrypt, invalid password?') + }) + + it('should read multi-account tdata', async () => { + const tdata = await Tdata.open({ + path: fileURLToPath(new URL('./__fixtures__/multiacc', import.meta.url)), + }) + + const auth0 = await tdata.readMtpAuthorization(0) + const auth1 = await tdata.readMtpAuthorization(1) + + expect({ auth0, auth1, key: tdata.keyData }).toMatchSnapshot() + }) + + it('should write simple tdata', async () => { + const fs = new FakeFs() + const crypto = await getDefaultCryptoProvider() + crypto.randomBytes = size => new Uint8Array(size) + + const tdata = await Tdata.create({ + path: '/', + fs, + crypto, + keyData: { + count: 1, + order: [0], + active: 0, + }, + }) + + const key = new Uint8Array(256) + key.fill(1) + await tdata.writeMtpAuthorization({ + userId: Long.fromNumber(12345678), + mainDcId: 2, + authKeys: [ + { + dcId: 2, + key, + }, + ], + authKeysToDestroy: [], + }) + + expect(fs.files).toMatchSnapshot() + }) +}) diff --git a/packages/convert/src/tdesktop/tdata.ts b/packages/convert/src/tdesktop/tdata.ts new file mode 100644 index 00000000..b5075df6 --- /dev/null +++ b/packages/convert/src/tdesktop/tdata.ts @@ -0,0 +1,494 @@ +import { dirname, join } from 'node:path/posix' + +import { Bytes, read, write } from '@fuman/io' +import type { UnsafeMutable } from '@fuman/utils' +import { typed, u8, utf8 } from '@fuman/utils' +import { createAesIgeForMessageOld } from '@mtcute/core/utils.js' +import { Long, MtUnsupportedError } from '@mtcute/core' + +import type { INodeFsLike } from '../utils/fs.js' +import { type IExtendedCryptoProvider, getDefaultCryptoProvider } from '../utils/crypto.js' + +import { readLong, readQByteArray } from './qt-reader.js' +import type { InputTdKeyData, TdAuthKey, TdKeyData, TdMtpAuthorization } from './types.js' +import { writeLong, writeQByteArray } from './qt-writer.js' + +const TDF_MAGIC = /* #__PURE__ */ utf8.encoder.encode('TDF$') +const TDF_VERSION = 5008003 +const MTP_AUTHORIZATION_BLOCK = 0x4B // see https://github.com/telegramdesktop/tdesktop/blob/dev/Telegram/SourceFiles/storage/details/storage_settings_scheme.h +const HEX_ALPHABET = '0123456789ABCDEF' + +function toFilePart(key: Uint8Array): string { + let str = '' + // we need to swap nibbles for whatever reason + for (let i = 0; i < 8; i++) { + const b = key[i] + const low = b & 0x0F + const high = b >> 4 + str += HEX_ALPHABET[low] + HEX_ALPHABET[high] + } + return str +} + +export interface TdataOptions { + /** Full path to the tdata directory */ + path: string + + /** + * File system to use for reading/writing. + * + * @default `import('node:fs/promises')` + */ + fs?: INodeFsLike + + /** + * Crypto functions to use for encryption/decryption. + * + * @default `node:crypto`-based implementation + */ + crypto?: IExtendedCryptoProvider + + /** + * Whether to ignore TDF version mismatch. + * If set to `true`, the version will be ignored and the file will be read as is, + * however the probability of errors is higher. + */ + ignoreVersion?: boolean + + /** + * Whether the host machine has LE processor (default true, try changing in case of errors) + */ + le?: boolean + + /** + * Value of -key cli parameter. + * Defaults to `data` + */ + dataKey?: string + + /** + * Local passcode + */ + passcode?: string +} + +export class Tdata { + private constructor( + readonly options: TdataOptions, + readonly fs: INodeFsLike, + readonly crypto: IExtendedCryptoProvider, + ) {} + + readonly keyData!: TdKeyData + + static async open(options: TdataOptions): Promise { + const fs: INodeFsLike = options.fs ?? (await import('node:fs/promises') as unknown as INodeFsLike) + const crypto: IExtendedCryptoProvider = options.crypto ?? (await getDefaultCryptoProvider()) + await crypto.initialize?.() + + const tdata = new Tdata(options, fs, crypto) + ;(tdata as UnsafeMutable).keyData = await tdata.readKeyData() + + return tdata + } + + static async create(options: TdataOptions & { keyData: InputTdKeyData }): Promise { + const fs: INodeFsLike = options.fs ?? (await import('node:fs/promises') as unknown as INodeFsLike) + const crypto: IExtendedCryptoProvider = options.crypto ?? (await getDefaultCryptoProvider()) + await crypto.initialize?.() + + const tdata = new Tdata(options, fs, crypto) + const keyData: TdKeyData = { + ...options.keyData, + localKey: options.keyData.localKey ?? crypto.randomBytes(256), + version: options.keyData.version ?? TDF_VERSION, + } + ;(tdata as UnsafeMutable).keyData = keyData + + await tdata.writeKeyData(keyData) + + return tdata + } + + #readInt32(buf: Uint8Array): number { + return (this.options.le ?? true) ? read.int32le(buf) : read.int32be(buf) + } + + #writeInt32(buf: Uint8Array, val: number): Uint8Array { + if (this.options.le ?? true) { + write.int32le(buf, val) + } else { + write.int32be(buf, val) + } + + return buf + } + + getDataName(idx: number): string { + let res = this.options.dataKey ?? 'data' + + if (idx > 0) { + res += `#${idx + 1}` + } + + return res + } + + async readFile(filename: string): Promise<[number, Uint8Array]> { + const order: string[] = [] + + const modern = `${filename}s` + if (await this.fs.stat(join(this.options.path, modern))) { + order.push(modern) + } else { + const try0 = `${filename}0` + const try1 = `${filename}1` + + const try0s = await this.fs.stat(join(this.options.path, try0)) + const try1s = await this.fs.stat(join(this.options.path, try1)) + + if (try0s) { + order.push(try0) + + if (try1s) { + order.push(try1) + if (try0s.lastModified < try1s.lastModified) { + order.reverse() + } + } + } else if (try1s) { + order.push(try1) + } + } + + let lastError = 'file not found' + + for (const file of order) { + const data = await this.fs.readFile(join(this.options.path, file)) + const magic = data.subarray(0, 4) + + if (!typed.equal(magic, TDF_MAGIC)) { + lastError = 'invalid magic' + continue + } + + const versionBytes = data.subarray(4, 8) + const version = this.#readInt32(versionBytes) + if (version > TDF_VERSION && !this.options.ignoreVersion) { + lastError = `Unsupported version: ${version}` + continue + } + + const dataSize = data.length - 24 + const bytes = data.subarray(8, dataSize + 8) + + const md5 = await this.crypto.createHash('md5') + await md5.update(bytes) + await md5.update(this.#writeInt32(u8.alloc(4), dataSize)) + await md5.update(versionBytes) + await md5.update(magic) + + const hash = await md5.digest() + if (!typed.equal(hash, data.subarray(dataSize + 8))) { + lastError = 'md5 mismatch' + continue + } + + return [version, bytes] + } + + throw new Error(`failed to read ${filename}, last error: ${lastError}`) + } + + async writeFile( + filename: string, + data: Uint8Array, + mkdir = false, + ): Promise { + filename = join(this.options.path, `${filename}s`) + + const version = this.#writeInt32(u8.alloc(4), TDF_VERSION) + const dataSize = this.#writeInt32(u8.alloc(4), data.length) + const md5 = await this.crypto.createHash('md5') + await md5.update(data) + await md5.update(dataSize) + await md5.update(version) + await md5.update(TDF_MAGIC) + + if (mkdir) { + await this.fs.mkdir(dirname(filename), { recursive: true }) + } + + await this.fs.writeFile( + filename, + u8.concat([TDF_MAGIC, version, data, await md5.digest()]), + ) + } + + async createLocalKey( + salt: Uint8Array, + passcode: string = this.options.passcode ?? '', + ): Promise { + const hasher = await this.crypto.createHash('sha512') + hasher.update(salt) + hasher.update(utf8.encoder.encode(passcode)) + hasher.update(salt) + const hash = await hasher.digest() + + return this.crypto.pbkdf2( + hash, + salt, + passcode === '' ? 1 : 100000, + 256, + 'sha512', + ) + } + + async decryptLocal(encrypted: Uint8Array, key: Uint8Array): Promise { + const encryptedKey = encrypted.subarray(0, 16) + const encryptedData = encrypted.subarray(16) + + const ige = createAesIgeForMessageOld( + this.crypto, + key, + encryptedKey, + false, + ) + const decrypted = ige.decrypt(encryptedData) + + if ( + !typed.equal( + this.crypto.sha1(decrypted).subarray(0, 16), + encryptedKey, + ) + ) { + throw new Error('Failed to decrypt, invalid password?') + } + + const fullLen = encryptedData.length + const dataLen = this.#readInt32(decrypted) + + if ( + dataLen > decrypted.length + || dataLen <= fullLen - 16 + || dataLen < 4 + ) { + throw new Error('Failed to decrypt, invalid data length') + } + + return decrypted.subarray(4, dataLen) + } + + async encryptLocal(data: Uint8Array, key: Uint8Array): Promise { + const dataSize = data.length + 4 + const padding: Uint8Array + = dataSize & 0x0F + ? this.crypto.randomBytes(0x10 - (dataSize & 0x0F)) + : u8.empty + + const toEncrypt = u8.alloc(dataSize + padding.length) + this.#writeInt32(toEncrypt, dataSize) + toEncrypt.set(data, 4) + toEncrypt.set(padding, dataSize) + + const encryptedKey = this.crypto.sha1(toEncrypt).subarray(0, 16) + + const ige = createAesIgeForMessageOld( + this.crypto, + key, + encryptedKey, + false, + ) + const encryptedData = ige.encrypt(toEncrypt) + + return u8.concat2(encryptedKey, encryptedData) + } + + async readKeyData(): Promise { + const [version, data] = await this.readFile(`key_${this.options.dataKey ?? 'data'}`) + const bytes = Bytes.from(data) + + const salt = readQByteArray(bytes) + const keyEncrypted = readQByteArray(bytes) + const infoEncrypted = readQByteArray(bytes) + + const passcodeKey = await this.createLocalKey(salt) + const keyInnerData = await this.decryptLocal(keyEncrypted, passcodeKey) + const infoDecrypted = await this.decryptLocal( + infoEncrypted, + keyInnerData, + ) + const info = Bytes.from(infoDecrypted) + + const localKey = keyInnerData + const count = read.int32be(info) + const order = [...Array(count)].map(() => read.int32be(info)) + const active = read.int32be(info) + + return { + version, + localKey, + count, + order, + active, + } + } + + async writeKeyData(keyData: TdKeyData): Promise { + const info = Bytes.alloc() + write.int32be(info, keyData.count) + keyData.order.forEach(i => write.int32be(info, i)) + write.int32be(info, keyData.active) + const infoDecrypted = info.result() + + const infoEncrypted = await this.encryptLocal(infoDecrypted, keyData.localKey) + + const salt = this.crypto.randomBytes(32) + const passcodeKey = await this.createLocalKey(salt) + + const keyEncrypted = await this.encryptLocal(keyData.localKey, passcodeKey) + + const data = Bytes.alloc() + writeQByteArray(data, salt) + writeQByteArray(data, keyEncrypted) + writeQByteArray(data, infoEncrypted) + + await this.writeFile(`key_${this.options.dataKey ?? 'data'}`, data.result(), true) + } + + async computeDataNameKey(accountIdx: number): Promise { + const md5 = await this.crypto.createHash('md5') + await md5.update(utf8.encoder.encode(this.getDataName(accountIdx))) + const r = await md5.digest() + return r.subarray(0, 8) + } + + async computeDataNameKeyHex(accountIdx: number): Promise { + return toFilePart(await this.computeDataNameKey(accountIdx)) + } + + async readEncryptedFile(filename: string): Promise<[number, Uint8Array]> { + const [version, data] = await this.readFile(filename) + + const encrypted = readQByteArray(Bytes.from(data)) + const decrypted = await this.decryptLocal(encrypted, this.keyData.localKey) + + return [version, decrypted] + } + + async writeEncryptedFile( + filename: string, + data: Uint8Array, + mkdir = false, + ): Promise { + const encryptedInner = await this.encryptLocal(data, this.keyData.localKey) + + const writer = Bytes.alloc(data.length + 4) + writeQByteArray(writer, encryptedInner) + + await this.writeFile(filename, writer.result(), mkdir) + } + + async readMtpAuthorization(accountIdx: number = 0): Promise { + const [, mtpData] = await this.readEncryptedFile( + await this.computeDataNameKeyHex(accountIdx), + ) + + // nb: this is pretty much a hack that relies on the fact that + // most of the time the mtp auth data is in the first setting + // since the settings are not length-prefixed, we can't skip unknown settings, + // as we need to know their type. + // and this is very much tied to the actual tdesktop version, and would be a nightmare to maintain + let bytes = Bytes.from(mtpData) + + const header = read.int32be(bytes) + if (header !== MTP_AUTHORIZATION_BLOCK) { + throw new MtUnsupportedError(`expected first setting to be mtp auth data, got 0x${header.toString(16)}`) + } + + const mtpAuthBlock = readQByteArray(bytes) + + bytes = Bytes.from(mtpAuthBlock) + + const legacyUserId = read.int32be(bytes) + const legacyMainDcId = read.int32be(bytes) + + let userId, mainDcId + if (legacyMainDcId === -1 && legacyMainDcId === -1) { + userId = readLong(bytes) + mainDcId = read.int32be(bytes) + } else { + userId = Long.fromInt(legacyUserId) + mainDcId = legacyMainDcId + } + + function readKeys(target: TdAuthKey[]) { + const count = read.uint32be(bytes) + + for (let i = 0; i < count; i++) { + const dcId = read.int32be(bytes) + const key = read.exactly(bytes, 256) + target.push({ dcId, key }) + } + } + + const authKeys: TdAuthKey[] = [] + const authKeysToDestroy: TdAuthKey[] = [] + + readKeys(authKeys) + readKeys(authKeysToDestroy) + + return { + userId, + mainDcId, + authKeys, + authKeysToDestroy, + } + } + + async writeMtpAuthorization(auth: TdMtpAuthorization, accountIdx = 0): Promise { + const bytes = Bytes.alloc() + + // legacy user id & dc id + write.int32be(bytes, -1) + write.int32be(bytes, -1) + writeLong(bytes, auth.userId) + write.int32be(bytes, auth.mainDcId) + + function writeKeys(keys: TdAuthKey[]) { + write.uint32be(bytes, keys.length) + keys.forEach((k) => { + write.int32be(bytes, k.dcId) + write.bytes(bytes, k.key) + }) + } + + writeKeys(auth.authKeys) + writeKeys(auth.authKeysToDestroy) + + const file = Bytes.alloc() + write.int32be(file, MTP_AUTHORIZATION_BLOCK) + writeQByteArray(file, bytes.result()) + + await this.writeEncryptedFile( + await this.computeDataNameKeyHex(accountIdx), + file.result(), + ) + } + + async writeEmptyMapFile(accountIdx: number): Promise { + // without this file tdesktop will not "see" the account + // however just creating an empty file seems to be enough to make it happy + + const writer = Bytes.alloc() + writeQByteArray(writer, u8.empty) // legacySalt + writeQByteArray(writer, u8.empty) // legacyKeyEncrypted + writeQByteArray(writer, await this.encryptLocal(u8.empty, this.keyData.localKey)) + + await this.writeFile( + join(await this.computeDataNameKeyHex(accountIdx), 'map'), + writer.result(), + true, + ) + } +} diff --git a/packages/convert/src/tdesktop/types.ts b/packages/convert/src/tdesktop/types.ts new file mode 100644 index 00000000..8112783e --- /dev/null +++ b/packages/convert/src/tdesktop/types.ts @@ -0,0 +1,26 @@ +import type { Long } from '@mtcute/core' + +export interface TdAuthKey { + dcId: number + key: Uint8Array +} + +export interface TdMtpAuthorization { + userId: Long + mainDcId: number + authKeys: TdAuthKey[] + authKeysToDestroy: TdAuthKey[] +} + +export interface InputTdKeyData { + localKey?: Uint8Array + version?: number + count: number + order: number[] + active: number +} + +export interface TdKeyData extends InputTdKeyData { + version: number + localKey: Uint8Array +} diff --git a/packages/convert/src/utils/crypto.ts b/packages/convert/src/utils/crypto.ts new file mode 100644 index 00000000..7d8d0336 --- /dev/null +++ b/packages/convert/src/utils/crypto.ts @@ -0,0 +1,29 @@ +import type { MaybePromise } from '@fuman/utils' +import type { ICryptoProvider } from '@mtcute/core/utils.js' + +export interface IExtendedCryptoProvider extends ICryptoProvider { + createHash(algorithm: 'md5' | 'sha512'): MaybePromise<{ + update(data: Uint8Array): MaybePromise + digest(): MaybePromise + }> +} + +export async function getDefaultCryptoProvider(): Promise { + const crypto = /* @vite-ignore */ await import('node:crypto') + const { NodeCryptoProvider } = /* @vite-ignore */ await import('@mtcute/node/utils.js') + + return new (class extends NodeCryptoProvider implements IExtendedCryptoProvider { + createHash(algorithm: 'md5' | 'sha512') { + const hasher = crypto.createHash(algorithm) + + return { + update(data: Uint8Array) { + hasher.update(data) + }, + digest() { + return hasher.digest() as unknown as Uint8Array + }, + } + } + })() +} diff --git a/packages/convert/src/utils/fs.ts b/packages/convert/src/utils/fs.ts new file mode 100644 index 00000000..21ba9741 --- /dev/null +++ b/packages/convert/src/utils/fs.ts @@ -0,0 +1,6 @@ +export interface INodeFsLike { + readFile(path: string): Promise + writeFile(path: string, data: Uint8Array): Promise + mkdir(path: string, options?: { recursive?: boolean }): Promise + stat(path: string): Promise<{ size: number, lastModified: number }> +}