UNPKG

@merqva/telegram-passport

Version:

Decrypt/Parse incoming Telegram Passport data

74 lines (73 loc) 3.51 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.TelegramPassport = void 0; const crypto_1 = require("crypto"); const constants_1 = require("./constants"); class TelegramPassport { constructor(privateKey) { this.privateKey = Buffer.from(privateKey); } decryptData(data, secret, hash) { const _data = typeof data === 'string' ? Buffer.from(data, 'base64') : data; const _secret = typeof secret === 'string' ? Buffer.from(secret, 'base64') : secret; const _hash = typeof hash === 'string' ? Buffer.from(hash, 'base64') : hash; const hasher = (0, crypto_1.createHash)('sha512'); hasher.update(Buffer.concat([_secret, _hash])); const digest = hasher.digest(); const key = digest.slice(0, 32); const iv = digest.slice(32, 48); const decipher = (0, crypto_1.createDecipheriv)('aes-256-cbc', key, iv); decipher.setAutoPadding(false); const dataPadded = Buffer.concat([ decipher.update(_data), decipher.final(), ]); const integrityHasher = (0, crypto_1.createHash)('sha256'); integrityHasher.update(dataPadded); const dataHash = integrityHasher.digest(); if (!_hash.equals(dataHash)) { throw new Error(constants_1.ErrorMessages.ERR_DATA_INTEGRITY_CHECK_FAILED); } return dataPadded.slice(dataPadded[0], dataPadded.byteLength); } decryptPassportCredentials(encryptedCredentials) { const secret = Buffer.from(encryptedCredentials.secret, 'base64'); const decryptedSecret = (0, crypto_1.privateDecrypt)({ key: this.privateKey, padding: crypto_1.constants.RSA_PKCS1_OAEP_PADDING, }, secret); const _data = this.decryptData(encryptedCredentials.data, decryptedSecret, encryptedCredentials.hash); return JSON.parse(_data.toString()); } decryptPassportData(passportData) { const credentials = this.decryptPassportCredentials(passportData.credentials); const fields = { nonce: credentials.nonce }; for (const element of passportData.data) { if (element.type === 'phone_number' || element.type === 'email') { fields[element.type] = element[element.type]; } else { fields[element.type] = {}; const secureValue = credentials.secure_data[element.type]; for (const [key, value] of Object.entries(element)) { if (key !== 'type' && key !== 'hash') { if (key === 'data') { const data = this.decryptData(element[key], secureValue[key].secret, secureValue[key].data_hash); fields[element.type][key] = JSON.parse(data.toString()); } else { if (Array.isArray(value)) { fields[element.type][key] = value.map((passportFile, index) => (Object.assign(Object.assign({}, passportFile), secureValue[key][index]))); } else { fields[element.type][key] = Object.assign(Object.assign({}, value), secureValue[key]); } } } } } } return fields; } } exports.TelegramPassport = TelegramPassport;