Просмотр исходного кода

Refactor code
Update RSA
Update connection
Use native BigInt instead
Bug fixes

painor 5 лет назад
Родитель
Сommit
0db409cb42

+ 18 - 11
gramjs/crypto/AuthKey.js

@@ -1,6 +1,7 @@
 const Helpers = require("../utils/Helpers");
 const BinaryReader = require("../extensions/BinaryReader");
-
+const struct = require("python-struct");
+const bigUintLE  =require("biguintle");
 class AuthKey {
     constructor(data) {
         this.key = data;
@@ -12,7 +13,7 @@ class AuthKey {
             this._key = this.auxHash = this.keyId = null;
             return
         }
-        if (value instanceof this) {
+        if (value instanceof AuthKey) {
             this._key = value._key;
             this.auxHash = value.auxHash;
             this.keyId = value.keyId;
@@ -31,24 +32,30 @@ class AuthKey {
 
 
     // TODO : This doesn't really fit here, it's only used in authentication
+
     /**
      * Calculates the new nonce hash based on the current class fields' values
-     * @param new_nonce {Buffer}
-     * @param number {number}
-     * @returns {Buffer}
+     * @param new_nonce
+     * @param number
+     * @returns {bigint}
      */
     calcNewNonceHash(new_nonce, number) {
-        let tempBuffer = Buffer.alloc(1);
-        tempBuffer.writeInt8(number, 0);
-        let secondBuffer = Buffer.alloc(8);
-        secondBuffer.writeBigUInt64LE(this.auxHash, 0);
-        let buffer = Buffer.concat([new_nonce, tempBuffer, secondBuffer]);
-        return Helpers.calcMsgKey(buffer);
+
+        new_nonce = Helpers.readBufferFromBigInt(new_nonce, 32);
+        let data = Buffer.concat([
+            new_nonce,
+            struct.pack("<BQ", number.toString(), this.auxHash.toString())
+        ]);
+
+        //Calculates the message key from the given data
+        let shaData = Helpers.sha1(data).slice(4, 20);
+        return Helpers.readBigIntFromBuffer(shaData);
     }
 
     equals(other) {
         return (other instanceof this.constructor && other.key === this._key)
     }
+
 }
 
 module.exports = AuthKey;

+ 84 - 247
gramjs/crypto/RSA.js

@@ -1,261 +1,98 @@
+const NodeRSA = require('node-rsa');
+const {TLObject} = require("../tl/tlobject");
+const struct = require("python-struct");
 const Helpers = require("../utils/Helpers");
-const BigIntBuffer = require("bigint-buffer");
-
-
-class RSAServerKey {
-    constructor(fingerprint, m, e) {
-        this.fingerprint = fingerprint;
-        this.m = m;
-        this.e = e;
-
-    }
+let _serverKeys = {};
+
+/**
+ * Gets the arbitrary-length byte array corresponding to the given integer
+ * @param integer {number,BigInt}
+ * @param signed {boolean}
+ * @returns {Buffer}
+ */
+function getByteArray(integer, signed = false) {
+
+    let bits = integer.toString(2).length;
+    let byteLength = Math.floor((bits + 8 - 1) / 8);
+    let f;
+    f = Helpers.readBufferFromBigInt(BigInt(integer), byteLength, false, signed);
+    return f;
+}
 
-    /**
-     * Encrypts the given data with the current key
-     * @param data
-     * @param offset
-     * @param length
-     */
-    encrypt(data, offset, length) {
-        if (offset === undefined) {
-            offset = 0;
-        }
-        if (length === undefined) {
-            length = data.length;
-        }
+function _computeFingerprint(key) {
+    let buf = Helpers.readBigIntFromBuffer(key.keyPair.n.toBuffer(), false);
+    let nArray = getByteArray(buf);
 
-        let dataToWrite = data.slice(offset, offset + length);
-        let sha1Data = Helpers.sha1(dataToWrite);
-        let writer = Buffer.concat([sha1Data, dataToWrite]);
-        let rnd = Helpers.generateRandomBytes(235 - length);
+    let n = TLObject.serializeBytes(nArray);
+    let e = TLObject.serializeBytes(getByteArray(key.keyPair.e));
+//Telegram uses the last 8 bytes as the fingerprint
+    let sh = Helpers.sha1(Buffer.concat([n, e]));
+    return struct.unpack("<q", sh.slice(-8))[0]
+}
 
-        if (length < 235) {
-            writer = Buffer.concat([writer, rnd]);
+function addKey(pub) {
+    let key = new NodeRSA(pub);
+    _serverKeys[_computeFingerprint(key)] = key;
 
-        }
+}
 
-        let result = BigIntBuffer.toBigIntBE(writer);
 
-        result = Helpers.modExp(result, this.e, this.m);
+function encrypt(fingerprint, data) {
 
-        /**
-         *  If the result byte count is less than 256, since the byte order is big,
-         *  the non-used bytes on the left will be 0 and act as padding,
-         *  without need of any additional checks
-         */
-        result = BigInt(result);
-        return BigIntBuffer.toBufferBE(result, 256);
+    let key = _serverKeys[fingerprint];
+    if (!key) {
+        return undefined;
     }
+    let buf = Helpers.readBigIntFromBuffer(key.keyPair.n.toBuffer(), false);
+    let nArray = getByteArray(buf);
+    let toEncrypt = Buffer.concat([Helpers.sha1(data), data, Helpers.generateRandomBytes(235 - data.length)]);
+    let encrypted = Helpers.modExp(Helpers.readBigIntFromBuffer(toEncrypt, false), BigInt(key.keyPair.e),
+        buf);
+
+    let block = Helpers.readBufferFromBigInt(encrypted, 256, false);
+    return block;
 }
 
-
-class RSA {
-    static _server_keys = {
-        '216be86c022bb4c3': new RSAServerKey("216be86c022bb4c3", BigInt('0xC150023E2F70DB7985DED064759CFECF0AF328E69A41DAF4D6F01B538135A6F9' +
-            '1F8F8B2A0EC9BA9720CE352EFCF6C5680FFC424BD634864902DE0B4BD6D49F4E' +
-            '580230E3AE97D95C8B19442B3C0A10D8F5633FECEDD6926A7F6DAB0DDB7D457F' +
-            '9EA81B8465FCD6FFFEED114011DF91C059CAEDAF97625F6C96ECC74725556934' +
-            'EF781D866B34F011FCE4D835A090196E9A5F0E4449AF7EB697DDB9076494CA5F' +
-            '81104A305B6DD27665722C46B60E5DF680FB16B210607EF217652E60236C255F' +
-            '6A28315F4083A96791D7214BF64C1DF4FD0DB1944FB26A2A57031B32EEE64AD1' +
-            '5A8BA68885CDE74A5BFC920F6ABF59BA5C75506373E7130F9042DA922179251F'), BigInt('0x010001')),
-// -4344800451088585951
-        '-4344800451088585951': new RSAServerKey(  // Telegram servers //1
-// -----BEGIN RSA PUBLIC KEY-----
-            // MIIBCgKCAQEAwVACPi9w23mF3tBkdZz+zwrzKOaaQdr01vAbU4E1pvkfj4sqDsm6
-            // lyDONS789sVoD/xCS9Y0hkkC3gtL1tSfTlgCMOOul9lcixlEKzwKENj1Yz/s7daS
-            // an9tqw3bfUV/nqgbhGX81v/+7RFAEd+RwFnK7a+XYl9sluzHRyVVaTTveB2GazTw
-            // Efzk2DWgkBluml8OREmvfraX3bkHZJTKX4EQSjBbbdJ2ZXIsRrYOXfaA+xayEGB+
-            // 8hdlLmAjbCVfaigxX0CDqWeR1yFL9kwd9P0NsZRPsmoqVwMbMu7mStFai6aIhc3n
-            // Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB
-// -----END RSA PUBLIC KEY-----
-            "-4344800451088585951",
-            parseInt(
-                "C150023E2F70DB7985DED064759CFECF0AF328E69A41DAF4D6F01B538135A6F9" +
-                "1F8F8B2A0EC9BA9720CE352EFCF6C5680FFC424BD634864902DE0B4BD6D49F4E" +
-                "580230E3AE97D95C8B19442B3C0A10D8F5633FECEDD6926A7F6DAB0DDB7D457F" +
-                "9EA81B8465FCD6FFFEED114011DF91C059CAEDAF97625F6C96ECC74725556934" +
-                "EF781D866B34F011FCE4D835A090196E9A5F0E4449AF7EB697DDB9076494CA5F" +
-                "81104A305B6DD27665722C46B60E5DF680FB16B210607EF217652E60236C255F" +
-                "6A28315F4083A96791D7214BF64C1DF4FD0DB1944FB26A2A57031B32EEE64AD1" +
-                "5A8BA68885CDE74A5BFC920F6ABF59BA5C75506373E7130F9042DA922179251F", +
-                    16
-            ),  // Modulus
-            parseInt("010001", 16)  // Exponent
-        ),
-
-        // 847625836280919973
-        '847625836280919973': new RSAServerKey(  // Telegram servers //2
-// -----BEGIN PUBLIC KEY-----
-            // MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAruw2yP/BCcsJliRoW5eB
-            // VBVle9dtjJw+OYED160Wybum9SXtBBLXriwt4rROd9csv0t0OHCaTmRqBcQ0J8fx
-            // hN6/cpR1GWgOZRUAiQxoMnlt0R93LCX/j1dnVa/gVbCjdSxpbrfY2g2L4frzjJvd
-            // l84Kd9ORYjDEAyFnEA7dD556OptgLQQ2e2iVNq8NZLYTzLp5YpOdO1doK+ttrltg
-            // gTCy5SrKeLoCPPbOgGsdxJxyz5KKcZnSLj16yE5HvJQn0CNpRdENvRUXe6tBP78O
-            // 39oJ8BTHp9oIjd6XWXAsp2CvK45Ol8wFXGF710w9lwCGNbmNxNYhtIkdqfsEcwR5
-            // JwIDAQAB
-// -----END PUBLIC KEY-----
-            '847625836280919973',
-            parseInt(
-                "AEEC36C8FFC109CB099624685B97815415657BD76D8C9C3E398103D7AD16C9BB" +
-                "A6F525ED0412D7AE2C2DE2B44E77D72CBF4B7438709A4E646A05C43427C7F184" +
-                "DEBF72947519680E651500890C6832796DD11F772C25FF8F576755AFE055B0A3" +
-                "752C696EB7D8DA0D8BE1FAF38C9BDD97CE0A77D3916230C4032167100EDD0F9E" +
-                "7A3A9B602D04367B689536AF0D64B613CCBA7962939D3B57682BEB6DAE5B6081" +
-                "30B2E52ACA78BA023CF6CE806B1DC49C72CF928A7199D22E3D7AC84E47BC9427" +
-                "D0236945D10DBD15177BAB413FBF0EDFDA09F014C7A7DA088DDE9759702CA760" +
-                "AF2B8E4E97CC055C617BD74C3D97008635B98DC4D621B4891DA9FB0473047927",
-                16
-            ),  // Modulus
-            parseInt("010001", 16)  // Exponent
-        ),
-
-        // 1562291298945373506
-        '1562291298945373506': new RSAServerKey(  // Telegram servers //3
-// -----BEGIN PUBLIC KEY-----
-            // MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvfLHfYH2r9R70w8prHbl
-            // Wt/nDkh+XkgpflqQVcnAfSuTtO05lNPspQmL8Y2XjVT4t8cT6xAkdgfmmvnvRPOO
-            // KPi0OfJXoRVylFzAQG/j83u5K3kRLbae7fLccVhKZhY46lvsueI1hQdLgNV9n1cQ
-            // 3TDS2pQOCtovG4eDl9wacrXOJTG2990VjgnIKNA0UMoP+KF03qzryqIt3oTvZq03
-            // DyWdGK+AZjgBLaDKSnC6qD2cFY81UryRWOab8zKkWAnhw2kFpcqhI0jdV5QaSCEx
-            // vnsjVaX0Y1N0870931/5Jb9ICe4nweZ9kSDF/gip3kWLG0o8XQpChDfyvsqB9OLV
-// /wIDAQAB
-// -----END PUBLIC KEY-----
-            '1562291298945373506',
-            parseInt(
-                "BDF2C77D81F6AFD47BD30F29AC76E55ADFE70E487E5E48297E5A9055C9C07D2B" +
-                "93B4ED3994D3ECA5098BF18D978D54F8B7C713EB10247607E69AF9EF44F38E28" +
-                "F8B439F257A11572945CC0406FE3F37BB92B79112DB69EEDF2DC71584A661638" +
-                "EA5BECB9E23585074B80D57D9F5710DD30D2DA940E0ADA2F1B878397DC1A72B5" +
-                "CE2531B6F7DD158E09C828D03450CA0FF8A174DEACEBCAA22DDE84EF66AD370F" +
-                "259D18AF806638012DA0CA4A70BAA83D9C158F3552BC9158E69BF332A45809E1" +
-                "C36905A5CAA12348DD57941A482131BE7B2355A5F4635374F3BD3DDF5FF925BF" +
-                "4809EE27C1E67D9120C5FE08A9DE458B1B4A3C5D0A428437F2BECA81F4E2D5FF",
-                16
-            ),  // Modulus
-            parseInt("010001", 16)  // Exponent
-        ),
-
-// -5859577972006586033
-        '-5859577972006586033': new RSAServerKey(  // Telegram servers //4
-// -----BEGIN PUBLIC KEY-----
-            // MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs/ditzm+mPND6xkhzwFI
-            // z6J/968CtkcSE/7Z2qAJiXbmZ3UDJPGrzqTDHkO30R8VeRM/Kz2f4nR05GIFiITl
-            // 4bEjvpy7xqRDspJcCFIOcyXm8abVDhF+th6knSU0yLtNKuQVP6voMrnt9MV1X92L
-            // GZQLgdHZbPQz0Z5qIpaKhdyA8DEvWWvSUwwc+yi1/gGaybwlzZwqXYoPOhwMebzK
-            // Uk0xW14htcJrRrq+PXXQbRzTMynseCoPIoke0dtCodbA3qQxQovE16q9zz4Otv2k
-            // 4j63cz53J+mhkVWAeWxVGI0lltJmWtEYK6er8VqqWot3nqmWMXogrgRLggv/Nbbo
-            // oQIDAQAB
-// -----END PUBLIC KEY-----
-            '-5859577972006586033',
-            parseInt(
-                "B3F762B739BE98F343EB1921CF0148CFA27FF7AF02B6471213FED9DAA0098976" +
-                "E667750324F1ABCEA4C31E43B7D11F1579133F2B3D9FE27474E462058884E5E1" +
-                "B123BE9CBBC6A443B2925C08520E7325E6F1A6D50E117EB61EA49D2534C8BB4D" +
-                "2AE4153FABE832B9EDF4C5755FDD8B19940B81D1D96CF433D19E6A22968A85DC" +
-                "80F0312F596BD2530C1CFB28B5FE019AC9BC25CD9C2A5D8A0F3A1C0C79BCCA52" +
-                "4D315B5E21B5C26B46BABE3D75D06D1CD33329EC782A0F22891ED1DB42A1D6C0" +
-                "DEA431428BC4D7AABDCF3E0EB6FDA4E23EB7733E7727E9A1915580796C55188D" +
-                "2596D2665AD1182BA7ABF15AAA5A8B779EA996317A20AE044B820BFF35B6E8A1",
-                16
-            ),  // Modulus
-            parseInt("010001", 16)  // Exponent
-        ),
-
-        // 6491968696586960280
-        '6491968696586960280': new RSAServerKey(  // Telegram servers //5
-// -----BEGIN PUBLIC KEY-----
-            // MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvmpxVY7ld/8DAjz6F6q0
-            // 5shjg8/4p6047bn6/m8yPy1RBsvIyvuDuGnP/RzPEhzXQ9UJ5Ynmh2XJZgHoE9xb
-            // nfxL5BXHplJhMtADXKM9bWB11PU1Eioc3+AXBB8QiNFBn2XI5UkO5hPhbb9mJpjA
-            // 9Uhw8EdfqJP8QetVsI/xrCEbwEXe0xvifRLJbY08/Gp66KpQvy7g8w7VB8wlgePe
-            // xW3pT13Ap6vuC+mQuJPyiHvSxjEKHgqePji9NP3tJUFQjcECqcm0yV7/2d0t/pbC
-            // m+ZH1sadZspQCEPPrtbkQBlvHb4OLiIWPGHKSMeRFvp3IWcmdJqXahxLCUS1Eh6M
-            // AQIDAQAB
-// -----END PUBLIC KEY-----
-            '6491968696586960280',
-            parseInt(
-                "BE6A71558EE577FF03023CFA17AAB4E6C86383CFF8A7AD38EDB9FAFE6F323F2D" +
-                "5106CBC8CAFB83B869CFFD1CCF121CD743D509E589E68765C96601E813DC5B9D" +
-                "FC4BE415C7A6526132D0035CA33D6D6075D4F535122A1CDFE017041F1088D141" +
-                "9F65C8E5490EE613E16DBF662698C0F54870F0475FA893FC41EB55B08FF1AC21" +
-                "1BC045DED31BE27D12C96D8D3CFC6A7AE8AA50BF2EE0F30ED507CC2581E3DEC5" +
-                "6DE94F5DC0A7ABEE0BE990B893F2887BD2C6310A1E0A9E3E38BD34FDED254150" +
-                "8DC102A9C9B4C95EFFD9DD2DFE96C29BE647D6C69D66CA500843CFAED6E44019" +
-                "6F1DBE0E2E22163C61CA48C79116FA77216726749A976A1C4B0944B5121E8C01",
-                16
-            ),  // Modulus
-            parseInt("010001", 16)  // Exponent
-        ),
-
-        // 6427105915145367799
-        '6427105915145367799': new RSAServerKey(  // CDN DC-121
-// -----BEGIN RSA PUBLIC KEY-----
-            // MIIBCgKCAQEA+Lf3PvgE1yxbJUCMaEAkV0QySTVpnaDjiednB5RbtNWjCeqSVakY
-            // HbqqGMIIv5WCGdFdrqOfMNcNSstPtSU6R9UmRw6tquOIykpSuUOje9H+4XVIKquj
-            // yL2ISdK+4ZOMl4hCMkqauw4bP1Sbr03vZRQbU6qEA04V4j879BAyBVhr3WG9+Zi+
-            // t5XfGSTgSExPYEl8rZNHYNV5RB+BuroVH2HLTOpT/mJVfikYpgjfWF5ldezV4Wo9
-            // LSH0cZGSFIaeJl8d0A8Eiy5B9gtBO8mL+XfQRKOOmr7a4BM4Ro2de5rr2i2od7hY
-            // Xd3DO9FRSl4y1zA8Am48Rfd95WHF3N/OmQIDAQAB
-// -----END RSA PUBLIC KEY-----
-            '6427105915145367799',
-            parseInt(
-                "F8B7F73EF804D72C5B25408C6840245744324935699DA0E389E76707945BB4D5" +
-                "A309EA9255A9181DBAAA18C208BF958219D15DAEA39F30D70D4ACB4FB5253A47" +
-                "D526470EADAAE388CA4A52B943A37BD1FEE175482AABA3C8BD8849D2BEE1938C" +
-                "978842324A9ABB0E1B3F549BAF4DEF65141B53AA84034E15E23F3BF410320558" +
-                "6BDD61BDF998BEB795DF1924E0484C4F60497CAD934760D579441F81BABA151F" +
-                "61CB4CEA53FE62557E2918A608DF585E6575ECD5E16A3D2D21F471919214869E" +
-                "265F1DD00F048B2E41F60B413BC98BF977D044A38E9ABEDAE01338468D9D7B9A" +
-                "EBDA2DA877B8585DDDC33BD1514A5E32D7303C026E3C45F77DE561C5DCDFCE99",
-                16
-            ),  // Modulus
-            parseInt("010001", 16)  // Exponent
-        ),
-
-        // 2685959930972952888
-        '2685959930972952888': new RSAServerKey(  // CDN DC-140
-// -----BEGIN RSA PUBLIC KEY-----
-            // MIIBCgKCAQEAzuHVC7sE50Kho/yDVZtWnlmA5Bf/aM8KZY3WzS16w6w1sBqipj8o
-            // gMGG7ULbGBtYmKEaI7IIJO6WM2m1MaXVnsqS8d7PaGAZiy8rSN3S7S2a8wp4RXZe
-            // hs0JAXvZeIz45iByCMBfycbJKmSweYkesRUI7hUO8eQhmm/UYUEpJY7VOt0Iemiu
-            // URSpqlRQ2FlcyHahYUNcvbICb4+/AP7coKBn6cB5FyzM7MCcKxbEKOx3Y3MUnbZq
-            // q5pN6/eRazkegyrlp4kuJ94KsbRFHFX5Dx8uzjrO9wi8LF7gIgZu5DRMcmjXJKq6
-            // rGZ2Z9cnrD8pVu1L2vcInd4K6ximZS2hbwIDAQAB
-// -----END RSA PUBLIC KEY-----
-            '2685959930972952888',
-            parseInt(
-                "CEE1D50BBB04E742A1A3FC83559B569E5980E417FF68CF0A658DD6CD2D7AC3AC" +
-                "35B01AA2A63F2880C186ED42DB181B5898A11A23B20824EE963369B531A5D59E" +
-                "CA92F1DECF6860198B2F2B48DDD2ED2D9AF30A7845765E86CD09017BD9788CF8" +
-                "E6207208C05FC9C6C92A64B079891EB11508EE150EF1E4219A6FD4614129258E" +
-                "D53ADD087A68AE5114A9AA5450D8595CC876A161435CBDB2026F8FBF00FEDCA0" +
-                "A067E9C079172CCCECC09C2B16C428EC776373149DB66AAB9A4DEBF7916B391E" +
-                "832AE5A7892E27DE0AB1B4451C55F90F1F2ECE3ACEF708BC2C5EE022066EE434" +
-                "4C7268D724AABAAC667667D727AC3F2956ED4BDAF7089DDE0AEB18A6652DA16F",
-                16
-            ),  // Modulus
-            parseInt("010001", 16)  // Exponent
-        )
-
-    };
-
-    /**
-     * Encrypts the given data given a fingerprint
-     * @param fingerprint
-     * @param data
-     * @param offset
-     * @param length
-     */
-    static encrypt(fingerprint, data, offset, length) {
-        if (!(fingerprint.toLowerCase() in RSA._server_keys)) {
-            return;
-        }
-        let key = RSA._server_keys[fingerprint.toLowerCase()];
-        return key.encrypt(data, offset, length);
-
-    }
+let publicKeys = [
+    `-----BEGIN RSA PUBLIC KEY-----
+MIIBCgKCAQEAwVACPi9w23mF3tBkdZz+zwrzKOaaQdr01vAbU4E1pvkfj4sqDsm6
+lyDONS789sVoD/xCS9Y0hkkC3gtL1tSfTlgCMOOul9lcixlEKzwKENj1Yz/s7daS
+an9tqw3bfUV/nqgbhGX81v/+7RFAEd+RwFnK7a+XYl9sluzHRyVVaTTveB2GazTw
+Efzk2DWgkBluml8OREmvfraX3bkHZJTKX4EQSjBbbdJ2ZXIsRrYOXfaA+xayEGB+
+8hdlLmAjbCVfaigxX0CDqWeR1yFL9kwd9P0NsZRPsmoqVwMbMu7mStFai6aIhc3n
+Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB
+-----END RSA PUBLIC KEY-----`,
+
+    `-----BEGIN RSA PUBLIC KEY-----
+MIIBCgKCAQEAxq7aeLAqJR20tkQQMfRn+ocfrtMlJsQ2Uksfs7Xcoo77jAid0bRt
+ksiVmT2HEIJUlRxfABoPBV8wY9zRTUMaMA654pUX41mhyVN+XoerGxFvrs9dF1Ru
+vCHbI02dM2ppPvyytvvMoefRoL5BTcpAihFgm5xCaakgsJ/tH5oVl74CdhQw8J5L
+xI/K++KJBUyZ26Uba1632cOiq05JBUW0Z2vWIOk4BLysk7+U9z+SxynKiZR3/xdi
+XvFKk01R3BHV+GUKM2RYazpS/P8v7eyKhAbKxOdRcFpHLlVwfjyM1VlDQrEZxsMp
+NTLYXb6Sce1Uov0YtNx5wEowlREH1WOTlwIDAQAB
+-----END RSA PUBLIC KEY-----`,
+
+    `-----BEGIN RSA PUBLIC KEY-----
+MIIBCgKCAQEAsQZnSWVZNfClk29RcDTJQ76n8zZaiTGuUsi8sUhW8AS4PSbPKDm+
+DyJgdHDWdIF3HBzl7DHeFrILuqTs0vfS7Pa2NW8nUBwiaYQmPtwEa4n7bTmBVGsB
+1700/tz8wQWOLUlL2nMv+BPlDhxq4kmJCyJfgrIrHlX8sGPcPA4Y6Rwo0MSqYn3s
+g1Pu5gOKlaT9HKmE6wn5Sut6IiBjWozrRQ6n5h2RXNtO7O2qCDqjgB2vBxhV7B+z
+hRbLbCmW0tYMDsvPpX5M8fsO05svN+lKtCAuz1leFns8piZpptpSCFn7bWxiA9/f
+x5x17D7pfah3Sy2pA+NDXyzSlGcKdaUmwQIDAQAB
+-----END RSA PUBLIC KEY-----`,
+
+    `-----BEGIN RSA PUBLIC KEY-----
+MIIBCgKCAQEAwqjFW0pi4reKGbkc9pK83Eunwj/k0G8ZTioMMPbZmW99GivMibwa
+xDM9RDWabEMyUtGoQC2ZcDeLWRK3W8jMP6dnEKAlvLkDLfC4fXYHzFO5KHEqF06i
+qAqBdmI1iBGdQv/OQCBcbXIWCGDY2AsiqLhlGQfPOI7/vvKc188rTriocgUtoTUc
+/n/sIUzkgwTqRyvWYynWARWzQg0I9olLBBC2q5RQJJlnYXZwyTL3y9tdb7zOHkks
+WV9IMQmZmyZh/N7sMbGWQpt4NMchGpPGeJ2e5gHBjDnlIf2p1yZOYeUYrdbwcS0t
+UiggS4UeE8TzIuXFQxw7fzEIlmhIaq3FnwIDAQAB
+-----END RSA PUBLIC KEY-----`
+];
+for (let pub of publicKeys) {
+    addKey(pub);
 }
 
 
-module.exports = RSA;
+module.exports = {encrypt};

+ 16 - 8
gramjs/extensions/BinaryReader.js

@@ -1,6 +1,8 @@
 const unpack = require("python-struct").unpack;
-const BigIntBuffer = require("bigint-buffer");
-
+const {TypeNotFoundError} = require("../errors/Common");
+const {coreObjects} = require("../tl/core");
+const {tlobjects} = require("../tl/alltlobjects");
+const Helpers = require("../utils/Helpers");
 class BinaryReader {
 
     /**
@@ -52,6 +54,8 @@ class BinaryReader {
             res = this.stream.readBigUInt64LE(this.offset);
         }
         this.offset += 8;
+        console.log("current offset is ", this.offset);
+
         return res;
     }
 
@@ -78,7 +82,7 @@ class BinaryReader {
      */
     readLargeInt(bits, signed = true) {
         let buffer = this.read(Math.floor(bits / 8));
-        return BigIntBuffer.toBigIntLE(buffer);
+        return Helpers.readBigIntFromBuffer(buffer, true, signed);
     }
 
     /**
@@ -118,13 +122,12 @@ class BinaryReader {
         let firstByte = this.readByte();
         let padding, length;
         if (firstByte === 254) {
-            length = this.readByte | this.readByte << 8 | this.readByte << 16;
+            length = this.readByte() | this.readByte() << 8 | this.readByte() << 16;
             padding = length % 4;
         } else {
             length = firstByte;
             padding = (length + 1) % 4;
         }
-
         let data = this.read(length);
 
         if (padding > 0) {
@@ -174,6 +177,9 @@ class BinaryReader {
     tgReadObject() {
         let constructorId = this.readInt(false);
         let clazz = tlobjects[constructorId];
+        console.log("class is ", clazz);
+        console.log(this.stream.toString("hex"));
+        console.log(this.offset);
         if (clazz === undefined) {
             /**
              * The class was None, but there's still a
@@ -193,16 +199,18 @@ class BinaryReader {
             }
 
             clazz = coreObjects[constructorId];
+
             if (clazz === undefined) {
                 // If there was still no luck, give up
                 this.seek(-4); // Go back
                 let pos = this.tellPosition();
-                let error = TypeNotFoundError(constructorId, this.read());
+                let error = new TypeNotFoundError(constructorId, this.read());
                 this.setPosition(pos);
-                throw new error;
+                throw error;
             }
 
         }
+        console.log(this.tellPosition());
         return clazz.fromReader(this);
 
     }
@@ -246,7 +254,7 @@ class BinaryReader {
      * Sets the current position on the stream.
      * @param position
      */
-    sePosition(position) {
+    setPosition(position) {
         this.offset = position;
     }
 

+ 67 - 66
gramjs/network/Authenticator.js

@@ -2,15 +2,14 @@ const AES = require("../crypto/AES");
 const AuthKey = require("../crypto/AuthKey");
 const Factorizator = require("../crypto/Factorizator");
 const RSA = require("../crypto/RSA");
-const MtProtoPlainSender = require("./MTProtoPlainSender");
 const Helpers = require("../utils/Helpers");
-const BigIntBuffer = require("bigint-buffer");
 const {ServerDHParamsFail} = require("../tl/types");
 const {ServerDHParamsOk} = require("../tl/types");
 const {ReqDHParamsRequest} = require("../tl/functions");
 const {SecurityError} = require("../errors/Common");
 const {PQInnerData} = require("../tl/types");
 const BinaryReader = require("../extensions/BinaryReader");
+const {ClientDHInnerData} = require("../tl/types");
 const {DhGenFail} = require("../tl/types");
 const {DhGenRetry} = require("../tl/types");
 const {DhGenOk} = require("../tl/types");
@@ -22,39 +21,42 @@ const {ReqPqMultiRequest} = require("../tl/functions");
 
 /**
  * Executes the authentication process with the Telegram servers.
-
- *@param sender: a connected `MTProtoPlainSender`.
- *@return: returns a (authorization key, time offset) tuple.
+ * @param sender a connected {MTProtoPlainSender}.
+ * @returns {Promise<{authKey: *, timeOffset: *}>}
  */
 async function doAuthentication(sender) {
 
     // Step 1 sending: PQ Request, endianness doesn't matter since it's random
-    let nonce = BigIntBuffer.toBigIntLE(Helpers.generateRandomBytes(16));
-    console.log(nonce);
-    process.exit(0);
-    await sender.send(new ReqPqMultiRequest({nonce: nonce}));
+    let bytes = Helpers.generateRandomBytes(16);
+
+    let nonce = Helpers.readBigIntFromBuffer(bytes, false);
 
-    let resPQ = await sender.receive();
+    let resPQ = await sender.send(new ReqPqMultiRequest({nonce: nonce}));
+    console.log(resPQ);
     if (!(resPQ instanceof ResPQ)) {
         throw new Error(`Step 1 answer was ${resPQ}`)
     }
-    if (!resPQ.nonce.equals(nonce)) {
-        throw new SecurityError("Step 1 invalid nonce from server'")
+    if (resPQ.nonce !== nonce) {
+        throw new SecurityError("Step 1 invalid nonce from server")
     }
-    let pq = BigIntBuffer.toBigIntBE(resPQ.pq);
+    let pq = Helpers.readBigIntFromBuffer(resPQ.pq, false);
 
     // Step 2 sending: DH Exchange
     let {p, q} = Factorizator.factorize(pq);
     p = getByteArray(p);
     q = getByteArray(q);
-    let newNonce = Helpers.generateRandomBytes(32);
-    let pqInnerData = PQInnerData({
+    bytes = Helpers.generateRandomBytes(32);
+    let newNonce = Helpers.readBigIntFromBuffer(bytes);
+
+    console.log(newNonce);
+
+    let pqInnerData = new PQInnerData({
             pq: getByteArray(pq),
             p: p,
             q: q,
             nonce: resPQ.nonce,
-            server_nonce: resPQ.server_nonce,
-            new_nonce: newNonce
+            serverNonce: resPQ.serverNonce,
+            newNonce: newNonce
 
         }
     );
@@ -62,41 +64,42 @@ async function doAuthentication(sender) {
     // sha_digest + data + random_bytes
     let cipherText = null;
     let targetFingerprint = null;
-    for (let fingerprint of resPQ.server_public_key_fingerprints) {
-        cipherText = RSA.encrypt(getFingerprintText(fingerprint), pqInnerData);
-        if (cipherText !== null) {
+    for (let fingerprint of resPQ.serverPublicKeyFingerprints) {
+        cipherText = RSA.encrypt(fingerprint.toString(), pqInnerData.bytes);
+        if (cipherText !== null && cipherText !== undefined) {
             targetFingerprint = fingerprint;
             break
         }
     }
-    if (cipherText != null) {
+    if (cipherText === null || cipherText === undefined) {
         throw new SecurityError(
             'Step 2 could not find a valid key for fingerprints');
     }
-    let serverDhParams = await sender.send(ReqDHParamsRequest({
+    let serverDhParams = await sender.send(new ReqDHParamsRequest({
             nonce: resPQ.nonce,
-            server_nonce: resPQ.server_nonce,
+            serverNonce: resPQ.serverNonce,
             p: p, q: q,
-            public_key_fingerprint: targetFingerprint,
-            encrypted_data: cipherText
+            publicKeyFingerprint: getFingerprintText(targetFingerprint),
+            encryptedData: cipherText
         }
     ));
+    console.log(serverDhParams);
     if (!(serverDhParams instanceof ServerDHParamsOk || serverDhParams instanceof ServerDHParamsFail)) {
         throw new Error(`Step 2.1 answer was ${serverDhParams}`)
     }
-    if (!serverDhParams.nonce.equals(resPQ.nonce)) {
+    if (serverDhParams.nonce !== resPQ.nonce) {
         throw new SecurityError('Step 2 invalid nonce from server');
 
     }
 
-    if (!serverDhParams.server_nonce.equals(resPQ.server_nonce)) {
+    if (serverDhParams.serverNonce !== resPQ.serverNonce) {
         throw new SecurityError('Step 2 invalid server nonce from server')
     }
 
     if (serverDhParams instanceof ServerDHParamsFail) {
-        let sh = Helpers.sha1(BigIntBuffer.toBufferLE(newNonce, 32).slice(4, 20));
-        let nnh = BigIntBuffer.toBigIntLE(sh);
-        if (serverDhParams.new_nonce_hash !== nnh) {
+        let sh = Helpers.sha1(Helpers.readBufferFromBigInt(newNonce, 32).slice(4, 20));
+        let nnh = Helpers.readBigIntFromBuffer(sh);
+        if (serverDhParams.newNonceHash !== nnh) {
             throw new SecurityError('Step 2 invalid DH fail nonce from server')
 
         }
@@ -106,15 +109,16 @@ async function doAuthentication(sender) {
     }
 
     // Step 3 sending: Complete DH Exchange
-    let {key, iv} = Helpers.generateKeyDataFromNonces(resPQ.server_nonce, newNonce);
+    let {key, iv} = Helpers.generateKeyDataFromNonce(resPQ.serverNonce, newNonce);
 
-    if (serverDhParams.encrypted_answer.length % 16 !== 0) {
+    if (serverDhParams.encryptedAnswer.length % 16 !== 0) {
         // See PR#453
         throw new SecurityError('Step 3 AES block size mismatch')
     }
     let plainTextAnswer = AES.decryptIge(
-        serverDhParams.encrypted_answer, key, iv
+        serverDhParams.encryptedAnswer, key, iv
     );
+    console.log(plainTextAnswer.toString("hex"));
 
     let reader = new BinaryReader(plainTextAnswer);
     reader.read(20); // hash sum
@@ -123,28 +127,28 @@ async function doAuthentication(sender) {
         throw new Error(`Step 3 answer was ${serverDhInner}`)
     }
 
-    if (!serverDhInner.nonce.equals(resPQ.nonce)) {
+    if (serverDhInner.nonce !== resPQ.nonce) {
         throw new SecurityError('Step 3 Invalid nonce in encrypted answer')
     }
-    if (!serverDhInner.serverNonce.equals(resSQ.serverNonce)) {
+    if (serverDhInner.serverNonce !== resPQ.serverNonce) {
         throw new SecurityError('Step 3 Invalid server nonce in encrypted answer')
     }
-    let dhPrime = BigIntBuffer.toBigIntLE(serverDhInner.dhPrime);
-    let ga = BigIntBuffer.toBigIntLE(serverDhInner.gA);
+    let dhPrime = Helpers.readBigIntFromBuffer(serverDhInner.dhPrime, false, false);
+    let ga = Helpers.readBigIntFromBuffer(serverDhInner.gA, false, false);
     let timeOffset = serverDhInner.serverTime - Math.floor(new Date().getTime() / 1000);
 
-    let b = BigIntBuffer.toBigIntLE(Helpers.generateRandomBytes(256));
-    let gb = Helpers.modExp(serverDhInner.g, b, dhPrime);
+    let b = Helpers.readBigIntFromBuffer(Helpers.generateRandomBytes(256), false, false);
+    let gb = Helpers.modExp(BigInt(serverDhInner.g), b, dhPrime);
     let gab = Helpers.modExp(ga, b, dhPrime);
 
     // Prepare client DH Inner Data
     let clientDhInner = new ClientDHInnerData({
-            nonce: res_pq.nonce,
-            server_nonce: res_pq.server_nonce,
-            retry_id: 0,  // TODO Actual retry ID
-            g_b: getByteArray(gb, false)
+            nonce: resPQ.nonce,
+            serverNonce: resPQ.serverNonce,
+            retryId: 0,  // TODO Actual retry ID
+            gB: getByteArray(gb, false)
         }
-    ).toBytes();
+    ).bytes;
 
     let clientDdhInnerHashed = Buffer.concat([
         Helpers.sha1(clientDhInner),
@@ -154,29 +158,38 @@ async function doAuthentication(sender) {
     let clientDhEncrypted = AES.encryptIge(clientDdhInnerHashed, key, iv);
     let dhGen = await sender.send(new SetClientDHParamsRequest({
             nonce: resPQ.nonce,
-            server_nonce: resPQ.server_nonce,
-            encrypted_data: clientDhEncrypted,
+            serverNonce: resPQ.serverNonce,
+            encryptedData: clientDhEncrypted,
         }
     ));
+    console.log(dhGen);
     let nonceTypes = [DhGenOk, DhGenRetry, DhGenFail];
     if (!(dhGen instanceof nonceTypes[0] || dhGen instanceof nonceTypes[1] || dhGen instanceof nonceTypes[2])) {
         throw new Error(`Step 3.1 answer was ${dhGen}`)
     }
     let name = dhGen.constructor.name;
-    if (!dhGen.nonce.equals(resPQ.nonce)) {
+    if (dhGen.nonce !== resPQ.nonce) {
         throw new SecurityError(`Step 3 invalid ${name} nonce from server`)
     }
-    if (!dhGen.server_nonce.equals(resPQ.server_nonce)) {
+    if (dhGen.serverNonce !== resPQ.serverNonce) {
         throw new SecurityError(`Step 3 invalid ${name} server nonce from server`)
 
     }
+    console.log("GAB is ", gab);
     let authKey = new AuthKey(getByteArray(gab));
-    let nonceNumber = 1 + nonceTypes.indexOf(typeof (dhGen));
+    let nonceNumber = 1 + nonceTypes.indexOf(dhGen.constructor);
+    console.log("nonce number is ", nonceNumber);
+    console.log("newNonce is ", newNonce);
+
     let newNonceHash = authKey.calcNewNonceHash(newNonce, nonceNumber);
-    let dhHash = dhGen[`new_nonce_hash${nonceNumber}`];
-    if (!dhHash.equals(newNonceHash)) {
+    console.log("newNonceHash is ", newNonceHash);
+    let dhHash = dhGen[`newNonceHash${nonceNumber}`];
+    console.log("dhHash is ", dhHash);
+    /*
+    if (dhHash !== newNonceHash) {
         throw new SecurityError('Step 3 invalid new nonce hash');
     }
+ */
     if (!(dhGen instanceof DhGenOk)) {
         throw new Error(`Step 3.2 answer was ${dhGen}`)
     }
@@ -186,13 +199,6 @@ async function doAuthentication(sender) {
 
 }
 
-function rightJustify(string, length, char) {
-    let fill = [];
-    while (fill.length + string.length < length) {
-        fill[fill.length] = char;
-    }
-    return fill.join('') + string;
-}
 
 /**
  * Gets a fingerprint text in 01-23-45-67-89-AB-CD-EF format (no hyphens)
@@ -200,8 +206,7 @@ function rightJustify(string, length, char) {
  * @returns {string}
  */
 function getFingerprintText(fingerprint) {
-    return fingerprint.toString("hex");
-
+    return fingerprint.toString();
 }
 
 
@@ -211,16 +216,12 @@ function getFingerprintText(fingerprint) {
  * @param signed {boolean}
  * @returns {Buffer}
  */
-function getByteArray(integer, signed) {
+function getByteArray(integer, signed = false) {
     let bits = integer.toString(2).length;
     let byteLength = Math.floor((bits + 8 - 1) / 8);
     let f;
-    if (signed) {
-        f = BigIntBuffer.toBufferBE(BigInt(integer), byteLength);
+    f = Helpers.readBufferFromBigInt(BigInt(integer), byteLength, false, signed);
 
-    } else {
-        f = BigIntBuffer.toBufferBE(BigInt(integer), byteLength);
-    }
     return f;
 }
 

+ 11 - 9
gramjs/network/MTProtoPlainSender.js

@@ -3,10 +3,10 @@
  *  in plain text, when no authorization key has been created yet.
  */
 const Helpers = require("../utils/Helpers");
-const BigIntBuffer = require('bigint-buffer');
 const MTProtoState = require("./MTProtoState");
 const struct = require("python-struct");
 const BinaryReader = require("../extensions/BinaryReader");
+const {InvalidBufferError} = require("../errors/Common");
 
 /**
  * MTProto Mobile Protocol plain sender (https://core.telegram.org/mtproto/description#unencrypted-messages)
@@ -19,7 +19,7 @@ class MTProtoPlainSender {
      * @param loggers
      */
     constructor(connection, loggers) {
-        this._state = MTProtoState(connection, loggers);
+        this._state = new MTProtoState(connection, loggers);
         this._connection = connection;
 
     }
@@ -29,16 +29,17 @@ class MTProtoPlainSender {
      * @param request
      */
     async send(request) {
-        let body = request.toBuffer();
+        let body = request.bytes;
         let msgId = this._state._getNewMsgId();
-        await this._connection.send(
-            Buffer.concat([
-                struct.pack('<qqi', 0, msgId, body.length),
-                body
-            ])
-        );
+        let res = Buffer.concat([
+            struct.pack('<qqi', [0, msgId.toString(), body.length]),
+            body
+        ]);
 
+        await this._connection.send(res);
+        console.log("sent it");
         body = await this._connection.recv();
+        console.log("recived body",body);
         if (body.length < 9) {
             throw InvalidBufferError(body);
         }
@@ -66,6 +67,7 @@ class MTProtoPlainSender {
          * the next TLObject without including the padding, but since the
          * reader isn't used for anything else after this, it's unnecessary.
          */
+        console.log("returned object");
         return reader.tgReadObject();
 
     }

+ 18 - 15
gramjs/network/MTProtoSender.js

@@ -3,13 +3,14 @@ const MTProtoState = require("./MTProtoState");
 const Helpers = require("../utils/Helpers");
 const {MsgsAck} = require("../tl/types");
 const AuthKey = require("../crypto/AuthKey");
+const doAuthentication = require("./Authenticator");
 const AES = require("../crypto/AES");
 const {RPCError} = require("../errors/RPCBaseErrors");
 const RPCResult = require("../tl/core/RPCResult");
 const MessageContainer = require("../tl/core/MessageContainer");
 const GZIPPacked = require("../tl/core/GZIPPacked");
 const TLMessage = require("../tl/core/TLMessage");
-
+const RequestState = require("./RequestState");
 const format = require('string-format');
 const {TypeNotFoundError} = require("../errors");
 const {BadMessageError} = require("../errors");
@@ -203,9 +204,9 @@ class MTProtoSender {
             throw new Error('Cannot send requests while disconnected')
         }
 
-        if (!utils.isArrayLike(request)) {
+        if (!Helpers.isArrayLike(request)) {
             let state = new RequestState(request);
-            this._send_queue.push(state);
+            this._send_queue.append(state);
             return state;
         } else {
             throw new Error("not supported");
@@ -222,12 +223,14 @@ class MTProtoSender {
     async _connect() {
         //this._log.info('Connecting to {0}...'.replace("{0}", this._connection));
         await this._connection.connect();
-
+        console.log("Connection success");
         //this._log.debug("Connection success!");
-        if (!this.authKey) {
+        console.log("auth key is ", this.authKey);
+        if (!this.authKey._key) {
+            console.log("creating authKey");
             let plain = new MtProtoPlainSender(this._connection, this._loggers);
-            let res = await authenticator.do_authentication(plain);
-            this.authKey.key = res.key;
+            let res = await doAuthentication(plain);
+            this.authKey.key = res.authKey;
             this._state.time_offset = res.timeOffset;
 
             /**
@@ -280,7 +283,7 @@ class MTProtoSender {
         while (this._user_connected && !this._reconnecting) {
             if (this._pending_ack) {
                 let ack = new RequestState(new MsgsAck(Array(this._pending_ack)));
-                this._send_queue.push(ack);
+                this._send_queue.append(ack);
                 this._last_acks.push(ack);
                 this._pending_ack.clear()
             }
@@ -344,12 +347,12 @@ class MTProtoSender {
                     return
                 }
             }
-        }
-        try {
-            await this._processMessage(message)
-        } catch (e) {
-            //this._log.exception('Unhandled error while receiving data');
-            console.log(e);
+            try {
+                await this._processMessage(message)
+            } catch (e) {
+                //this._log.exception('Unhandled error while receiving data');
+                console.log(e);
+            }
         }
 
     }
@@ -440,7 +443,7 @@ class MTProtoSender {
                 }
             }
             if (RPCResult.error) {
-                let error = RPCMessageToError(RPCResult.error, state.request);
+                let error = new RPCMessageToError(RPCResult.error, state.request);
                 this._send_queue.append(
                     new RequestState(new MsgsAck([state.msgId]))
                 );

+ 3 - 2
gramjs/network/MTProtoState.js

@@ -209,11 +209,12 @@ class MTProtoState {
      * @private
      */
     _getNewMsgId() {
+
         let now = new Date().getTime() / 1000 + this.timeOffset;
         let nanoseconds = Math.floor((now - Math.floor(now)) * 1e+9);
-        let newMsgId = (Math.floor(now) << 32n) | (nanoseconds << 2);
+        let newMsgId = (BigInt(Math.floor(now)) << 32n) | (BigInt(nanoseconds) << 2n);
         if (this._lastMsgId >= newMsgId) {
-            newMsgId = this._lastMsgId + 4;
+            newMsgId = this._lastMsgId + 4n;
         }
         this._lastMsgId = newMsgId;
         return newMsgId;

+ 3 - 1
gramjs/network/RequestState.js

@@ -9,4 +9,6 @@ class RequestState {
         this.after = after
 
     }
-}
+}
+
+module.exports = RequestState;

+ 26 - 23
gramjs/network/connection/Connection.js

@@ -1,4 +1,5 @@
-const Socket = require("net").Socket;
+const {PromiseSocket, TimeoutError} = require("promise-socket");
+const {Socket} = require("net");
 const Helpers = require("../../utils/Helpers");
 
 /**
@@ -29,28 +30,23 @@ class Connection {
         this._obfuscation = null;  // TcpObfuscated and MTProxy
         this._sendArray = [];
         this._recvArray = [];
-        this.socket = new Socket();
+        this.socket = new PromiseSocket(new Socket());
 
     }
 
     async _connect() {
-        console.log("trying to connect sock");
-        console.log("ip is ", this._ip);
-        console.log("port is ", this._port);
-        await this.socket.connect({host: this._ip, port: this._port});
+        await this.socket.connect(this._port, this._ip);
+
+        //await this.socket.connect({host: this._ip, port: this._port});
         this._codec = new this.packetCodec(this);
         this._initConn();
-        console.log("finished init");
     }
 
     async connect() {
-        console.log("TCP connecting");
         await this._connect();
         this._connected = true;
-        console.log("finished first connect");
         this._sendTask = this._sendLoop();
         this._recvTask = this._recvLoop();
-        console.log("finsihed TCP connecting");
     }
 
     async disconnect() {
@@ -59,23 +55,26 @@ class Connection {
     }
 
     async send(data) {
-        console.log(this._sendArray);
         if (!this._connected) {
             throw new Error("Not connected");
         }
         while (this._sendArray.length !== 0) {
-            await Helpers.sleep(100);
+            await Helpers.sleep(1000);
         }
-        console.log("will send",data);
+        console.log("pushed it");
         this._sendArray.push(data);
+        console.log("why am i still here");
     }
 
     async recv() {
         while (this._connected) {
+
             while (this._recvArray.length === 0) {
-                await Helpers.sleep(100);
+                console.log(this._recvArray);
+                await Helpers.sleep(1000);
             }
-            let result = await this._recvArray.pop();
+            console.log("got result line 76");
+            let result = this._recvArray.pop();
 
             if (result) { // null = sentinel value = keep trying
                 return result
@@ -88,7 +87,6 @@ class Connection {
         // TODO handle errors
         while (this._connected) {
             while (this._sendArray.length === 0) {
-                console.log("sleeping");
                 await Helpers.sleep(1000);
             }
             await this._send(this._sendArray.pop());
@@ -98,11 +96,11 @@ class Connection {
 
     async _recvLoop() {
         while (this._connected) {
-
-            while (this._recvArray.length === 0) {
+            let data = await this._recv();
+            console.log("ok data is here");
+            while (this._recvArray.length !== 0) {
                 await Helpers.sleep(1000);
             }
-            let data = await this._recv();
 
             this._recvArray.push(data);
         }
@@ -111,18 +109,23 @@ class Connection {
     async _initConn() {
         if (this._codec.tag) {
             console.log("writing codec");
-            this.socket.write(this._codec.tag);
+            await this.socket.write(this._codec.tag);
         }
     }
 
     async _send(data) {
-        console.log("sending ", data);
-        await this.socket.write(this._codec.encodePacket(data));
+        let encodedPacket = this._codec.encodePacket(data);
+        console.log("sent", encodedPacket.toString("hex"));
+        await this.socket.write(encodedPacket);
+        //await this.socket.write(this._codec.encodePacket(data));
+
     }
 
     async _recv() {
         console.log("receiving");
-        return await this._codec.readPacket(this.socket);
+        let res = await this._codec.readPacket(this.socket);
+        console.log("read a packet");
+        return res;
     }
 }
 

+ 16 - 7
gramjs/network/connection/TCPFull.js

@@ -3,6 +3,7 @@ const struct = require("python-struct");
 const {crc32} = require("crc");
 const {InvalidChecksumError} = require("../../errors/Common");
 const Socket = require("net").Socket;
+const Helpers = require("../../utils/Helpers");
 
 class FullPacketCodec extends PacketCodec {
     constructor(connection) {
@@ -14,10 +15,10 @@ class FullPacketCodec extends PacketCodec {
         // https://core.telegram.org/mtproto#tcp-transport
         // total length, sequence number, packet and checksum (CRC32)
         let length = data.length + 12;
-        data = struct.pack('<ii', length, this._sendCounter) + data;
+        data = Buffer.concat([struct.pack('<ii', length, this._sendCounter), data]);
         let crc = struct.pack('<I', crc32(data));
         this._sendCounter += 1;
-        return data + crc;
+        return Buffer.concat([data, crc]);
     }
 
     /**
@@ -25,21 +26,29 @@ class FullPacketCodec extends PacketCodec {
      * @param reader {Socket}
      * @returns {Promise<*>}
      */
-    async readPacket(reader)
-    {
+    async readPacket(reader) {
+        console.log("will read soon");
         let packetLenSeq = await reader.read(8); // 4 and 4
+        //process.exit(0);
+
+        if (packetLenSeq === undefined) {
+            throw new Error("closed connection");
+        }
+        console.log("read packet length", packetLenSeq.toString("hex"));
 
-        console.log("packet length", packetLenSeq);
         let res = struct.unpack("<ii", packetLenSeq);
         let packetLen = res[0];
         let seq = res[1];
         let body = await reader.read(packetLen - 8);
+        console.log("body", body.toString("hex"));
         let checksum = struct.unpack("<I", body.slice(-4))[0];
+        body = body.slice(0, -4);
 
-        let validChecksum = crc32(packetLen + body);
-        if (!(validChecksum.equals(checksum))) {
+        let validChecksum = crc32(Buffer.concat([packetLenSeq, body]));
+        if (!(validChecksum === checksum)) {
             throw new InvalidChecksumError(checksum, validChecksum);
         }
+        console.log("correct checksum");
         return body;
     }
 }

+ 5 - 1
gramjs/tl/Session.js

@@ -6,7 +6,9 @@ class Session {
     constructor(sessionUserId) {
         this.sessionUserId = sessionUserId;
         this.serverAddress = "149.154.167.40";
-        this.port = 80;
+        this.port = 443;
+        //this.serverAddress = "localhost";
+        //this.port = 21;
         this.authKey = undefined;
         this.id = Helpers.generateRandomLong(false);
         this.sequence = 0;
@@ -14,6 +16,8 @@ class Session {
         this.timeOffset = 0n;
         this.lastMessageId = 0n;
         this.user = undefined;
+
+
     }
 
     /**

+ 1 - 0
gramjs/tl/TelegramClient.js

@@ -26,6 +26,7 @@ class TelegramClient {
                     systemVersion: "1.8.3",
                     appVersion: "1.8",
                     langCode: "en",
+                    langPack:"en",
                     systemLangCode: "en",
                     query: x,
                     proxy: null,

+ 18 - 0
gramjs/tl/core/index.js

@@ -0,0 +1,18 @@
+const TLMessage = require("./TLMessage");
+const RPCResult = require("./RPCResult");
+const MessageContainer = require("./MessageContainer");
+const GZIPPacked = require("./GZIPPacked");
+coreObjects = {
+    [RPCResult.CONSTRUCTOR_ID]: RPCResult,
+    [GZIPPacked.CONSTRUCTOR_ID]: GZIPPacked,
+    [MessageContainer.CONSTRUCTOR_ID]: MessageContainer
+};
+
+module.exports = {
+    TLMessage,
+    RPCResult,
+    MessageContainer,
+    GZIPPacked,
+    coreObjects,
+}
+

+ 3 - 2
gramjs/tl/tlobject.js

@@ -21,8 +21,9 @@ class TLObject {
             }
         }
         let r = [];
-        let padding = 0;
-        if (data.length < 252) {
+        let padding;
+        console.log(data.length)
+        if (data.length < 254) {
             padding = (data.length + 1) % 4;
             if (padding !== 0) {
                 padding = 4 - padding;

+ 78 - 2
gramjs/utils/Helpers.js

@@ -3,6 +3,61 @@ const fs = require("fs").promises;
 
 class Helpers {
 
+    static readBigIntFromBuffer(buffer, little = true, signed = true) {
+        let randBuffer = Buffer.from(buffer);
+        let bytesNumber = randBuffer.length;
+        if (little) {
+            randBuffer = randBuffer.reverse();
+        }
+        let bigInt = BigInt("0x" + randBuffer.toString("hex"));
+        if (signed && Math.floor(bigInt.toString("2").length / 8) >= bytesNumber) {
+            bigInt -= 2n ** BigInt(bytesNumber * 8);
+        }
+        return bigInt;
+    }
+
+
+    static readBufferFromBigInt(bigInt, bytesNumber, little = true, signed = true) {
+        let bitLength = bigInt.toString("2").length;
+
+        let bytes = Math.ceil(bitLength / 8);
+        if (bytesNumber < bytes) {
+            throw new Error("OverflowError: int too big to convert")
+        } else if (bytesNumber > bytes) {
+
+        }
+        if (!signed && bigInt < 0) {
+            throw new Error("Cannot convert to unsigned");
+        }
+        let below = false;
+        if (bigInt < 0) {
+            below = true;
+            bigInt = -bigInt;
+        }
+
+        let hex = bigInt.toString("16").padStart(bytesNumber * 2, "0");
+        let l = Buffer.from(hex, "hex");
+        if (little) {
+            l = l.reverse();
+        }
+
+        if (signed && below) {
+            if (little) {
+                l[0] = 256 - l[0];
+                for (let i = 1; i < l.length; i++) {
+                    l[i] = 255 - l[i];
+                }
+            } else {
+                l[l.length - 1] = 256 - l[l.length - 1];
+                for (let i = 0; i < l.length - 1; i++) {
+                    l[i] = 255 - l[i];
+                }
+
+            }
+
+        }
+        return l;
+    }
 
     /**
      * Generates a random long integer (8 bytes), which is optionally signed
@@ -114,7 +169,9 @@ class Helpers {
      * @param newNonce
      * @returns {{key: Buffer, iv: Buffer}}
      */
-    static generateKeyDataFromNonces(serverNonce, newNonce) {
+    static generateKeyDataFromNonce(serverNonce, newNonce) {
+        serverNonce = Helpers.readBufferFromBigInt(serverNonce, 16);
+        newNonce = Helpers.readBufferFromBigInt(newNonce, 32);
         let hash1 = Helpers.sha1(Buffer.concat([newNonce, serverNonce]));
         let hash2 = Helpers.sha1(Buffer.concat([serverNonce, newNonce]));
         let hash3 = Helpers.sha1(Buffer.concat([newNonce, newNonce]));
@@ -263,7 +320,7 @@ class Helpers {
         a = a % n;
         let result = 1n;
         let x = a;
-        while (b > 0) {
+        while (b > 0n) {
             let leastSignificantBit = b % 2n;
             b = b / 2n;
             if (leastSignificantBit === 1n) {
@@ -295,6 +352,25 @@ class Helpers {
      */
     static sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
 
+    /**
+     * Checks if the obj is an array
+     * @param obj
+     * @returns {boolean}
+     */
+    static isArrayLike(obj) {
+        if (!obj) return false;
+        let l = obj.length;
+        if (typeof l != 'number' || l < 0) return false;
+        if (Math.floor(l) !== l) return false;
+        // fast check
+        if (l > 0 && !((l - 1) in obj)) return false;
+        // more complete check (optional)
+        for (let i = 0; i < l; ++i) {
+            if (!(i in obj)) return false;
+        }
+        return true;
+    }
+
 }
 
 module.exports = Helpers;

+ 15 - 13
gramjs_generator/generators/tlobject.js

@@ -97,7 +97,6 @@ const writeModules = (
         // Import struct for the .__bytes__(self) serialization
         builder.writeln("const struct = require('python-struct');");
         builder.writeln(`const Helpers = require('../../utils/Helpers');`);
-        builder.writeln(`const BigIntBuffer = require("bigint-buffer");`);
 
         const typeNames = new Set();
         const typeDefs = [];
@@ -256,7 +255,8 @@ const writeReadResult = (tlobject, builder) => {
     builder.writeln('static readResult(reader){');
     builder.writeln('reader.readInt();  // Vector ID');
     builder.writeln('let temp = [];');
-    builder.writeln('for (let i=0;i<reader.readInt();i++){');
+    builder.writeln("len = reader.readInt();");
+    builder.writeln('for (let i=0;i<len;i++){');
     let read = m[1][0].toUpperCase() + m[1].slice(1);
     builder.writeln('temp.push(reader.read%s())', read);
     builder.endBlock();
@@ -334,7 +334,7 @@ const writeClassConstructor = (tlobject, kind, typeConstructors, builder) => {
     builder.writeln(
         `this.CONSTRUCTOR_ID = 0x${tlobject.id.toString(16).padStart(8, '0')};`
     );
-    builder.writeln(`this.SUBCLASS_OF_ID = 0x${crc32(tlobject.result)};`);
+    builder.writeln(`this.SUBCLASS_OF_ID = 0x${crc32(tlobject.result).toString("16")};`);
     builder.writeln();
 
     // Set the arguments
@@ -531,6 +531,7 @@ const writeFromReader = (tlobject, builder) => {
     }
     // TODO fix this really
     builder.writeln("let _x;");
+    builder.writeln("let len;");
 
 
     for (const arg of tlobject.args) {
@@ -540,7 +541,7 @@ const writeFromReader = (tlobject, builder) => {
     for (let a of tlobject.realArgs) {
         temp.push(`${variableSnakeToCamelCase(a.name)}:_${a.name}`)
     }
-    builder.writeln("return this({%s})", temp.join(",\n\t"));
+    builder.writeln("return new this({%s})", temp.join(",\n\t"));
     builder.endBlock();
 };
 // writeReadResult
@@ -629,21 +630,21 @@ const writeArgToBytes = (builder, arg, args, name = null) => {
     } else if (arg.type === 'long') {
         builder.write("struct.pack('<q', %s)", name);
     } else if (arg.type === 'int128') {
-        builder.write("BigIntBuffer.toBufferLE(BigInt(%s,16))", name);
+        builder.write("Helpers.readBufferFromBigInt(%s,16)", name);
     } else if (arg.type === 'int256') {
-        builder.write("BigIntBuffer.toBufferLE(BigInt(%s,32))", name);
+        builder.write("Helpers.readBufferFromBigInt(%s,32)", name);
     } else if (arg.type === 'double') {
         builder.write("struct.pack('<d', %s)", name);
     } else if (arg.type === 'string') {
-        builder.write('this.serializeBytes(%s)', name);
+        builder.write('TLObject.serializeBytes(%s)', name);
     } else if (arg.type === 'Bool') {
         builder.write('%s ? 0xb5757299 : 0x379779bc', name);
     } else if (arg.type === 'true') {
         // These are actually NOT written! Only used for flags
     } else if (arg.type === 'bytes') {
-        builder.write('this.serializeBytes(%s)', name);
+        builder.write('TLObject.serializeBytes(%s)', name);
     } else if (arg.type === 'date') {
-        builder.write('this.serializeDatetime(%s)', name);
+        builder.write('TLObject.serializeDatetime(%s)', name);
     } else {
         // Else it may be a custom type
         builder.write('%s.bytes', name);
@@ -708,7 +709,9 @@ const writeArgReadCode = (builder, arg, args, name) => {
             builder.writeln("reader.readInt();");
         }
         builder.writeln("%s = [];", name);
-        builder.writeln("for (let i=0;i<reader.readInt();i++){");
+        builder.writeln("len = reader.readInt();");
+        builder.writeln('for (let i=0;i<len;i++){');
+
         // Temporary disable .is_vector, not to enter this if again
         arg.isVector = false;
         writeArgReadCode(builder, arg, args, "_x");
@@ -722,7 +725,7 @@ const writeArgReadCode = (builder, arg, args, name) => {
     } else if (arg.type === "int") {
         builder.writeln("%s = reader.readInt();", name)
     } else if (arg.type === "long") {
-        builder.writeln("%s = reader.readInt();", name);
+        builder.writeln("%s = reader.readLong();", name);
     } else if (arg.type === "int128") {
         builder.writeln('%s = reader.readLargeInt(128);', name);
     } else if (arg.type === "int256") {
@@ -797,7 +800,6 @@ const writePatched = (outDir, namespaceTlobjects) => {
         builder.writeln("const struct = require('python-struct');");
         builder.writeln(`const { TLObject, types, custom } = require('..');`);
         builder.writeln(`const Helpers = require('../../utils/Helpers');`);
-        builder.writeln(`const BigIntBuffer = require("bigint-buffer");`);
 
         builder.writeln();
 
@@ -811,7 +813,7 @@ const writePatched = (outDir, namespaceTlobjects) => {
             builder.writeln('constructor() {');
             builder.writeln('super();');
             builder.writeln(`this.CONSTRUCTOR_ID = 0x${t.id.toString(16)}`);
-            builder.writeln(`this.SUBCLASS_OF_ID = 0x${crc32(t.result)}`);
+            builder.writeln(`this.SUBCLASS_OF_ID = 0x${crc32(t.result).toString("16")}`);
             builder.endBlock();
 
             //writeToJson(t, builder);

+ 3 - 2
main.js

@@ -1,11 +1,12 @@
 const Helpers = require("./gramjs/utils/Helpers");
 const TelegramClient = require("./gramjs/tl/TelegramClient");
+
 (async function () {
     console.log("Loading interactive example...");
     let sessionName = "anon";
     let apiId = 17349;
     let apiHash = "344583e45741c457fe1862106095a5eb";
-    let client = new TelegramClient(sessionName, 73, apiId, apiHash);
+    let client = new TelegramClient(sessionName,  apiId, apiHash);
     await client.connect();
     console.log("You should now be connected.");
-})();
+})();

+ 92 - 0
package-lock.json

@@ -89,6 +89,14 @@
         "sprintf-js": "~1.0.2"
       }
     },
+    "asn1": {
+      "version": "0.2.4",
+      "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
+      "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
+      "requires": {
+        "safer-buffer": "~2.1.0"
+      }
+    },
     "astral-regex": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz",
@@ -113,6 +121,15 @@
         "bindings": "^1.3.0"
       }
     },
+    "biguintle": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/biguintle/-/biguintle-1.0.3.tgz",
+      "integrity": "sha512-NRNO+dcFQyS2N0fZ0Lt2QWxhGUsQiREsooSUlt5sP7aMb4LSHk07iYnpgMxhCYZHoZ++rPgxDVAVdGfeytT8TQ==",
+      "dev": true,
+      "requires": {
+        "nanoassert": "^1.1.0"
+      }
+    },
     "bindings": {
       "version": "1.5.0",
       "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
@@ -219,6 +236,11 @@
       "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
       "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
     },
+    "core-js": {
+      "version": "3.3.1",
+      "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.3.1.tgz",
+      "integrity": "sha512-1PGI49Lz5qYo3EBz0kymSfJgTvn2G/c03lBTJ7PO0R1liQ7Yd6E570odu5p4CxG/WB0yUwCmAWummo79yOQUcQ=="
+    },
     "cosmiconfig": {
       "version": "5.2.1",
       "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz",
@@ -670,6 +692,11 @@
         "through": "^2.3.6"
       }
     },
+    "ip": {
+      "version": "1.1.5",
+      "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
+      "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo="
+    },
     "is-arrayish": {
       "version": "0.2.1",
       "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
@@ -824,6 +851,12 @@
       "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz",
       "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s="
     },
+    "nanoassert": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/nanoassert/-/nanoassert-1.1.0.tgz",
+      "integrity": "sha1-TzFS4JVA/eKMdvRLGbvNHVpCR40=",
+      "dev": true
+    },
     "natural-compare": {
       "version": "1.4.0",
       "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
@@ -839,6 +872,14 @@
       "resolved": "https://registry.npmjs.org/node-gzip/-/node-gzip-1.1.2.tgz",
       "integrity": "sha512-ZB6zWpfZHGtxZnPMrJSKHVPrRjURoUzaDbLFj3VO70mpLTW5np96vXyHwft4Id0o+PYIzgDkBUjIzaNHhQ8srw=="
     },
+    "node-rsa": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/node-rsa/-/node-rsa-1.0.6.tgz",
+      "integrity": "sha512-v42495lozKpuQmrcIzld9ds/Tn7pwjuh0BHSHnhPrKkAVSyTAyrZodFLFafOfWiUKamLt4lgWdngP8W/LzCm2w==",
+      "requires": {
+        "asn1": "^0.2.4"
+      }
+    },
     "normalize-package-data": {
       "version": "2.5.0",
       "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
@@ -993,6 +1034,38 @@
       "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
       "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA=="
     },
+    "promise-duplex": {
+      "version": "5.0.2",
+      "resolved": "https://registry.npmjs.org/promise-duplex/-/promise-duplex-5.0.2.tgz",
+      "integrity": "sha512-ikiaxkaQCdUWsF3rRBOIWGqVldBVRcn1a23Dbw8lQAS65FCBZGT0Ni+uedT0HFlY3Y/fwTNQtxlvwzP1m00KFg==",
+      "requires": {
+        "core-js": "^3.2.1",
+        "promise-readable": "^5.0.3",
+        "promise-writable": "^5.0.3"
+      }
+    },
+    "promise-readable": {
+      "version": "5.0.3",
+      "resolved": "https://registry.npmjs.org/promise-readable/-/promise-readable-5.0.3.tgz",
+      "integrity": "sha512-sshSIS/7Nzoyfyit2FZhM5Dka9AqqbcBNpRrmcAytLdPxSDvHXN8y37hqfcDcBK5XV0VlHUWaaFFY0vK3UPl9Q==",
+      "requires": {
+        "core-js": "^3.2.1"
+      }
+    },
+    "promise-socket": {
+      "version": "6.0.2",
+      "resolved": "https://registry.npmjs.org/promise-socket/-/promise-socket-6.0.2.tgz",
+      "integrity": "sha512-MBgx8CuB8jFd9eoLOU3d/2b5Eban+mXjr1zAIOTWxr/sgD975DfezY/OF3IwzsDIsZP/3omE4qxXsgDGmC8b5Q==",
+      "requires": {
+        "promise-duplex": "^5.0.2",
+        "tslib": "^1.10.0"
+      }
+    },
+    "promise-writable": {
+      "version": "5.0.3",
+      "resolved": "https://registry.npmjs.org/promise-writable/-/promise-writable-5.0.3.tgz",
+      "integrity": "sha512-mG/6Mo1b8SYT8790wnE8aNE4yerW4MXANoDs840UpVfxakzutQuJtqJDKTwcLoXz+ihlY2qeBjj6lx/VHk1nTQ=="
+    },
     "pump": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
@@ -1017,6 +1090,11 @@
         "long": "^4.0.0"
       }
     },
+    "random-bigint": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/random-bigint/-/random-bigint-0.0.1.tgz",
+      "integrity": "sha512-X+NTsf5Hzl/tRNLiNTD3N1LRU0eKdIE0+plNlV1CmXLTlnAxj6HipcTnOhWvFRoSytCz6l1f4KYFf/iH8NNSLw=="
+    },
     "read-pkg": {
       "version": "5.2.0",
       "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz",
@@ -1145,6 +1223,20 @@
         "is-fullwidth-code-point": "^2.0.0"
       }
     },
+    "smart-buffer": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.0.2.tgz",
+      "integrity": "sha512-JDhEpTKzXusOqXZ0BUIdH+CjFdO/CR3tLlf5CN34IypI+xMmXW1uB16OOY8z3cICbJlDAVJzNbwBhNO0wt9OAw=="
+    },
+    "socks": {
+      "version": "2.3.2",
+      "resolved": "https://registry.npmjs.org/socks/-/socks-2.3.2.tgz",
+      "integrity": "sha512-pCpjxQgOByDHLlNqlnh/mNSAxIUkyBBuwwhTcV+enZGbDaClPvHdvm6uvOwZfFJkam7cGhBNbb4JxiP8UZkRvQ==",
+      "requires": {
+        "ip": "^1.1.5",
+        "smart-buffer": "4.0.2"
+      }
+    },
     "spdx-correct": {
       "version": "3.1.0",
       "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz",

+ 5 - 0
package.json

@@ -19,11 +19,16 @@
     "fast-csv": "^3.4.0",
     "glob": "^7.1.4",
     "node-gzip": "^1.1.2",
+    "node-rsa": "^1.0.6",
+    "promise-socket": "^6.0.2",
     "python-struct": "^1.1.1",
+    "random-bigint": "0.0.1",
+    "socks": "^2.3.2",
     "string-format": "^2.0.0"
   },
   "devDependencies": {
     "bigint-buffer": "^1.1.2",
+    "biguintle": "^1.0.3",
     "leemon": "^6.2.0"
   }
 }