@merqva/telegram-passport
Version:
Decrypt/Parse incoming Telegram Passport data
74 lines (73 loc) • 3.51 kB
JavaScript
;
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;