UNPKG

telegram-mtproto

Version:
485 lines (395 loc) 13.1 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.rshift32 = exports.strDecToHex = undefined; exports.generateNonce = generateNonce; exports.bytesToString = bytesToString; exports.stringToChars = stringToChars; exports.bytesToHex = bytesToHex; exports.bytesFromHex = bytesFromHex; exports.bytesCmp = bytesCmp; exports.bytesXor = bytesXor; exports.bytesToWords = bytesToWords; exports.bytesFromWords = bytesFromWords; exports.bytesFromLeemonBigInt = bytesFromLeemonBigInt; exports.bytesToArrayBuffer = bytesToArrayBuffer; exports.convertToArrayBuffer = convertToArrayBuffer; exports.convertToUint8Array = convertToUint8Array; exports.convertToByteArray = convertToByteArray; exports.bytesFromArrayBuffer = bytesFromArrayBuffer; exports.bufferConcat = bufferConcat; exports.longToInts = longToInts; exports.longToBytes = longToBytes; exports.lshift32 = lshift32; exports.intToUint = intToUint; exports.uintToInt = uintToInt; exports.sha1HashSync = sha1HashSync; exports.sha1BytesSync = sha1BytesSync; exports.sha256HashSync = sha256HashSync; exports.rsaEncrypt = rsaEncrypt; exports.aesEncryptSync = aesEncryptSync; exports.aesDecryptSync = aesDecryptSync; exports.gzipUncompress = gzipUncompress; exports.nextRandomInt = nextRandomInt; exports.pqPrimeFactorization = pqPrimeFactorization; exports.pqPrimeLeemon = pqPrimeLeemon; exports.bytesModPow = bytesModPow; var _rusha = require('rusha'); var _rusha2 = _interopRequireDefault(_rusha); var _nodeCryptojsAes = require('@goodmind/node-cryptojs-aes'); var CryptoJSlib = _interopRequireWildcard(_nodeCryptojsAes); var _inflate = require('pako/lib/inflate'); var _secureRandom = require('./service/secure-random'); var _secureRandom2 = _interopRequireDefault(_secureRandom); var _leemon = require('./vendor/leemon'); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var { CryptoJS } = CryptoJSlib; var rushaInstance = new _rusha2.default(1024 * 1024); function generateNonce() { var nonce = new Array(16); for (var i = 0; i < 16; i++) { nonce[i] = nextRandomInt(0xFF); }return nonce; } function bytesToString(bytes) { var ln = bytes.length; var temp = new Array(ln); for (var i = 0; i < ln; ++i) { temp[i] = String.fromCharCode(bytes[i]); }var result = temp.join(''); return result; } function stringToChars(str) { var ln = str.length; var result = Array(ln); for (var i = 0; i < ln; ++i) { result[i] = str.charCodeAt(i); }return result; } var strDecToHex = exports.strDecToHex = str => (0, _leemon.bigInt2str)((0, _leemon.str2bigInt)(str, 10, 0), 16).toLowerCase(); function bytesToHex(bytes = []) { var arr = []; for (var i = 0; i < bytes.length; i++) { arr.push((bytes[i] < 16 ? '0' : '') + (bytes[i] || 0).toString(16)); } return arr.join(''); } function bytesFromHex(hexString) { var len = hexString.length; var start = 0; var bytes = []; if (hexString.length % 2) { bytes.push(parseInt(hexString.charAt(0), 16)); start++; } for (var i = start; i < len; i += 2) { bytes.push(parseInt(hexString.substr(i, 2), 16)); } return bytes; } function bytesCmp(bytes1, bytes2) { var len = bytes1.length; if (len !== bytes2.length) { return false; } for (var i = 0; i < len; i++) { if (bytes1[i] !== bytes2[i]) return false; } return true; } function bytesXor(bytes1, bytes2) { var len = bytes1.length; var bytes = []; for (var i = 0; i < len; ++i) { bytes[i] = bytes1[i] ^ bytes2[i]; } return bytes; } function bytesToWords(bytes) { if (bytes instanceof ArrayBuffer) { bytes = new Uint8Array(bytes); } var len = bytes.length; var words = []; var i = void 0; for (i = 0; i < len; i++) { words[i >>> 2] |= bytes[i] << 24 - i % 4 * 8; } return new CryptoJS.lib.WordArray.init(words, len); } function bytesFromWords(wordArray) { var words = wordArray.words; var sigBytes = wordArray.sigBytes; var bytes = []; for (var i = 0; i < sigBytes; i++) { bytes.push(words[i >>> 2] >>> 24 - i % 4 * 8 & 0xff); } return bytes; } function bytesFromLeemonBigInt(bigInt) { var str = (0, _leemon.bigInt2str)(bigInt, 16); return bytesFromHex(str); } function bytesToArrayBuffer(b) { return new Uint8Array(b).buffer; } function convertToArrayBuffer(bytes) { // Be careful with converting subarrays!! if (bytes instanceof ArrayBuffer) { return bytes; } if (bytes instanceof Uint8Array) { //$FlowIssue if (bytes.buffer.byteLength == bytes.length * bytes.BYTES_PER_ELEMENT) return bytes.buffer; } return bytesToArrayBuffer(bytes); } function convertToUint8Array(bytes) { if (bytes instanceof Uint8Array) return bytes; if (Array.isArray(bytes)) return new Uint8Array(bytes); if (bytes instanceof ArrayBuffer) return new Uint8Array(bytes); throw new TypeError(`convertToUint8Array mismatch! ${bytes}`); } function convertToByteArray(bytes) { if (Array.isArray(bytes)) return bytes; var bytesUint8 = convertToUint8Array(bytes); var ln = bytesUint8.length; if (ln === 0) { return []; } var newBytes = new Array(ln); newBytes[0] = 0; for (var i = 0; i < ln; i++) { newBytes[i] = bytesUint8[i]; }return newBytes; } function bytesFromArrayBuffer(buffer) { var byteView = new Uint8Array(buffer); var bytes = Array.from(byteView); return bytes; } function bufferConcat(buffer1, buffer2) { var set1 = void 0, set2 = void 0, l1 = void 0, l2 = void 0; if (buffer1 instanceof ArrayBuffer) { l1 = buffer1.byteLength; set1 = new Uint8Array(buffer1); } else { l1 = buffer1.length; set1 = buffer1; } if (buffer2 instanceof ArrayBuffer) { l2 = buffer2.byteLength; set2 = new Uint8Array(buffer2); } else { l2 = buffer2.length; set2 = buffer2; } var tmp = new Uint8Array(l1 + l2); tmp.set(set1, 0); tmp.set(set2, l1); return tmp.buffer; } // const dividerBig = bigint(0x100000000) var dividerLem = (0, _leemon.str2bigInt)('100000000', 16, 4); // const printTimers = (timeL, timeB, a, b, n) => setTimeout( // () => console.log(`Timer L ${timeL} B ${timeB}`, ...a, ...b, n || ''), // 100) function longToInts(sLong) { var lemNum = (0, _leemon.str2bigInt)(sLong, 10, 6); var div = new Array(lemNum.length); var rem = new Array(lemNum.length); (0, _leemon.divide_)(lemNum, dividerLem, div, rem); var resL = [ //$FlowIssue ~~(0, _leemon.bigInt2str)(div, 10), //$FlowIssue ~~(0, _leemon.bigInt2str)(rem, 10)]; return resL; } function longToBytes(sLong) { return bytesFromWords({ words: longToInts(sLong), sigBytes: 8 }).reverse(); } function lshift32(high, low) { var highNum = (0, _leemon.str2bigInt)(high.toString(), 10, 6); var nLow = (0, _leemon.str2bigInt)(low.toString(), 10, 6); (0, _leemon.leftShift_)(highNum, 32); (0, _leemon.add_)(highNum, nLow); var res = (0, _leemon.bigInt2str)(highNum, 10); return res; } var rshift32 = exports.rshift32 = str => { var num = (0, _leemon.str2bigInt)(str, 10, 6); (0, _leemon.rightShift_)(num, 32); return (0, _leemon.bigInt2str)(num, 10); }; function intToUint(val) { //$FlowIssue var result = ~~val; if (result < 0) result = result + 0x100000000; return result; } var middle = 0x100000000 / 2 - 1; function uintToInt(val) { if (val > middle) val = val - 0x100000000; return val; } function sha1HashSync(bytes) { // console.log(dT(), 'SHA-1 hash start', bytes.byteLength || bytes.length) var hashBytes = rushaInstance.rawDigest(bytes).buffer; // console.log(dT(), 'SHA-1 hash finish') return hashBytes; } function sha1BytesSync(bytes) { return bytesFromArrayBuffer(sha1HashSync(bytes)); } function sha256HashSync(bytes) { // console.log(dT(), 'SHA-2 hash start', bytes.byteLength || bytes.length) var hashWords = CryptoJS.SHA256(bytesToWords(bytes)); // console.log(dT(), 'SHA-2 hash finish') var hashBytes = bytesFromWords(hashWords); return hashBytes; } function rsaEncrypt(publicKey, bytes) { var newBytes = addPadding(bytes, 255); var N = (0, _leemon.str2bigInt)(publicKey.modulus, 16, 256); var E = (0, _leemon.str2bigInt)(publicKey.exponent, 16, 256); var X = (0, _leemon.str2bigInt)(bytesToHex(newBytes), 16, 256); var encryptedBigInt = (0, _leemon.powMod)(X, E, N), encryptedBytes = bytesFromHex((0, _leemon.bigInt2str)(encryptedBigInt, 16)); return encryptedBytes; } var addPadding = (bytes, blockSize = 16, zeroes = false) => { var len = void 0; if (bytes instanceof ArrayBuffer) { len = bytes.byteLength; } else { len = bytes.length; } var result = bytes; var needPadding = blockSize - len % blockSize; if (needPadding > 0 && needPadding < blockSize) { var padding = new Array(needPadding); if (zeroes) { for (var i = 0; i < needPadding; i++) { padding[i] = 0; } } else (0, _secureRandom2.default)(padding); if (bytes instanceof ArrayBuffer) { result = bufferConcat(bytes, padding); } else result = bytes.concat(padding); } return result; }; function aesEncryptSync(bytes, keyBytes, ivBytes) { // console.log(dT(), 'AES encrypt start', len/*, bytesToHex(keyBytes), bytesToHex(ivBytes)*/)aesEncryptSync var newBytes = addPadding(bytes); var encryptedWords = CryptoJS.AES.encrypt(bytesToWords(newBytes), bytesToWords(keyBytes), { iv: bytesToWords(ivBytes), padding: CryptoJS.pad.NoPadding, mode: CryptoJS.mode.IGE }).ciphertext; var encryptedBytes = bytesFromWords(encryptedWords); // console.log(dT(), 'AES encrypt finish') return encryptedBytes; } function aesDecryptSync(encryptedBytes, keyBytes, ivBytes) { // console.log(dT(), 'AES decrypt start', encryptedBytes.length) var decryptedWords = CryptoJS.AES.decrypt({ ciphertext: bytesToWords(encryptedBytes) }, bytesToWords(keyBytes), { iv: bytesToWords(ivBytes), padding: CryptoJS.pad.NoPadding, mode: CryptoJS.mode.IGE }); var bytes = bytesFromWords(decryptedWords); // console.log(dT(), 'AES decrypt finish') return bytes; } function gzipUncompress(bytes) { // console.log('Gzip uncompress start') var result = (0, _inflate.inflate)(bytes); // console.log('Gzip uncompress finish') return result; } function nextRandomInt(maxValue) { return Math.floor(Math.random() * maxValue); } function pqPrimeFactorization(pqBytes) { var minSize = Math.ceil(64 / _leemon.bpe) + 1; // const what = new BigInteger(pqBytes) var hex = bytesToHex(pqBytes); var lWhat = (0, _leemon.str2bigInt)(hex, 16, minSize); var result = pqPrimeLeemon(lWhat); return result; } function pqPrimeLeemon(what) { var minLen = Math.ceil(64 / _leemon.bpe) + 1; var it = 0; var q = void 0, lim = void 0; var a = new Array(minLen); var b = new Array(minLen); var c = new Array(minLen); var g = new Array(minLen); var z = new Array(minLen); var x = new Array(minLen); var y = new Array(minLen); for (var i = 0; i < 3; i++) { q = (nextRandomInt(128) & 15) + 17; (0, _leemon.copyInt_)(x, nextRandomInt(1000000000) + 1); (0, _leemon.copy_)(y, x); lim = 1 << i + 18; for (var j = 1; j < lim; j++) { ++it; (0, _leemon.copy_)(a, x); (0, _leemon.copy_)(b, x); (0, _leemon.copyInt_)(c, q); while (!(0, _leemon.isZero)(b)) { if (b[0] & 1) { (0, _leemon.add_)(c, a); if ((0, _leemon.greater)(c, what)) { (0, _leemon.sub_)(c, what); } } (0, _leemon.add_)(a, a); if ((0, _leemon.greater)(a, what)) { (0, _leemon.sub_)(a, what); } (0, _leemon.rightShift_)(b, 1); } (0, _leemon.copy_)(x, c); if ((0, _leemon.greater)(x, y)) { (0, _leemon.copy_)(z, x); (0, _leemon.sub_)(z, y); } else { (0, _leemon.copy_)(z, y); (0, _leemon.sub_)(z, x); } (0, _leemon.eGCD_)(z, what, g, a, b); if (!(0, _leemon.equalsInt)(g, 1)) { break; } if ((j & j - 1) === 0) { (0, _leemon.copy_)(y, x); } } if ((0, _leemon.greater)(g, _leemon.one)) { break; } } (0, _leemon.divide_)(what, g, x, y); var [P, Q] = (0, _leemon.greater)(g, x) ? [x, g] : [g, x]; // console.log(dT(), 'done', bigInt2str(what, 10), bigInt2str(P, 10), bigInt2str(Q, 10)) return [bytesFromLeemonBigInt(P), bytesFromLeemonBigInt(Q), it]; } function bytesModPow(x, y, m) { var xBigInt = (0, _leemon.str2bigInt)(bytesToHex(x), 16); var yBigInt = (0, _leemon.str2bigInt)(bytesToHex(y), 16); var mBigInt = (0, _leemon.str2bigInt)(bytesToHex(m), 16); var resBigInt = (0, _leemon.powMod)(xBigInt, yBigInt, mBigInt); return bytesFromHex((0, _leemon.bigInt2str)(resBigInt, 16)); } //# sourceMappingURL=bin.js.map