steam-appticket
Version:
Decrypts and parses Steam app tickets
80 lines • 6.78 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseEncryptedAppTicket = void 0;
const hashing_1 = require("@doctormckay/stdlib/hashing");
const steam_crypto_1 = __importDefault(require("@doctormckay/steam-crypto"));
const load_1 = __importDefault(require("../protobuf-generated/load"));
const parseAppTicket_1 = require("./parseAppTicket");
/**
*
* @param {Buffer} ticket - The raw encrypted appticket
* @param {Buffer|string} encryptionKey - The app's encryption key, either raw hex or a Buffer
* @returns {DecodedEncryptedAppTicket|null}
*/
function parseEncryptedAppTicket(ticket, encryptionKey) {
try {
let outer = load_1.default.EncryptedAppTicket.decode(ticket);
let key = typeof encryptionKey === 'string' ? Buffer.from(encryptionKey, 'hex') : encryptionKey;
let decrypted = steam_crypto_1.default.symmetricDecrypt(outer.encrypted_ticket, key);
if ((0, hashing_1.crc32)(decrypted) != outer.crc_encryptedticket) {
return null;
}
// the beginning is the user-supplied data
let userData = decrypted.slice(0, outer.cb_encrypteduserdata);
let ownershipTicketLength = decrypted.readUInt32LE(outer.cb_encrypteduserdata);
// @ts-ignore
let ownershipTicket = (0, parseAppTicket_1.parseAppTicket)(decrypted.slice(outer.cb_encrypteduserdata, outer.cb_encrypteduserdata + ownershipTicketLength), true);
if (ownershipTicket) {
ownershipTicket.userData = userData;
}
let remainderOffset = 0;
if (outer.ticket_version_no == 2) {
remainderOffset += 8 + 8 + 4;
let readOffset = outer.cb_encrypteduserdata + ownershipTicketLength;
// @ts-ignore
ownershipTicket.unknown2 = decrypted.readBigUint64LE(readOffset).toString();
readOffset += 8;
// @ts-ignore
ownershipTicket.unknown3 = decrypted.readBigUint64LE(readOffset).toString();
readOffset += 8;
// @ts-ignore
ownershipTicket.unknown4 = decrypted.readUInt32LE(readOffset);
}
let remainder = decrypted.slice(outer.cb_encrypteduserdata + ownershipTicketLength + remainderOffset);
if (remainder.length >= 8 + 20) {
// salted sha1 hash
let dataToHash = decrypted.slice(0, outer.cb_encrypteduserdata + ownershipTicketLength + remainderOffset);
let salt = remainder.slice(0, 8);
let hash = remainder.slice(8, 28);
remainder = remainder.slice(28);
if (!hash.equals((0, hashing_1.sha1)(Buffer.concat([dataToHash, salt]), 'buffer'))) {
return null;
}
if (ownershipTicket) {
// @ts-ignore
ownershipTicket.unknown1 = remainder.readUInt32LE(0);
}
}
[
'ownershipTicketExpires',
'isExpired',
'hasValidSignature',
'isValid',
'unknown1',
'unknown2',
'unknown3',
'unknown4'
].forEach((key) => {
delete ownershipTicket[key];
});
return ownershipTicket;
}
catch (ex) {
return null;
}
}
exports.parseEncryptedAppTicket = parseEncryptedAppTicket;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFyc2VFbmNyeXB0ZWRBcHBUaWNrZXQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29tcG9uZW50cy9wYXJzZUVuY3J5cHRlZEFwcFRpY2tldC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSx5REFBd0Q7QUFDeEQsNkVBQW9EO0FBRXBELHNFQUFnRDtBQUNoRCxxREFBZ0Q7QUFJaEQ7Ozs7O0dBS0c7QUFDSCxTQUFnQix1QkFBdUIsQ0FBQyxNQUFjLEVBQUUsYUFBNEI7SUFDbkYsSUFBSTtRQUNILElBQUksS0FBSyxHQUFHLGNBQU0sQ0FBQyxrQkFBa0IsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUEyQixDQUFDO1FBQy9FLElBQUksR0FBRyxHQUFHLE9BQU8sYUFBYSxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxhQUFhLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLGFBQWEsQ0FBQztRQUNoRyxJQUFJLFNBQVMsR0FBRyxzQkFBVyxDQUFDLGdCQUFnQixDQUFDLEtBQUssQ0FBQyxnQkFBZ0IsRUFBRSxHQUFHLENBQUMsQ0FBQztRQUUxRSxJQUFJLElBQUEsZUFBSyxFQUFDLFNBQVMsQ0FBQyxJQUFJLEtBQUssQ0FBQyxtQkFBbUIsRUFBRTtZQUNsRCxPQUFPLElBQUksQ0FBQztTQUNaO1FBRUQsMENBQTBDO1FBQzFDLElBQUksUUFBUSxHQUFHLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO1FBQzlELElBQUkscUJBQXFCLEdBQUcsU0FBUyxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsb0JBQW9CLENBQUMsQ0FBQztRQUMvRSxhQUFhO1FBQ2IsSUFBSSxlQUFlLEdBQTZCLElBQUEsK0JBQWMsRUFBQyxTQUFTLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxvQkFBb0IsRUFBRSxLQUFLLENBQUMsb0JBQW9CLEdBQUcscUJBQXFCLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUN0SyxJQUFJLGVBQWUsRUFBRTtZQUNwQixlQUFlLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQztTQUNwQztRQUVELElBQUksZUFBZSxHQUFHLENBQUMsQ0FBQztRQUN4QixJQUFJLEtBQUssQ0FBQyxpQkFBaUIsSUFBSSxDQUFDLEVBQUU7WUFDakMsZUFBZSxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQzdCLElBQUksVUFBVSxHQUFHLEtBQUssQ0FBQyxvQkFBb0IsR0FBRyxxQkFBcUIsQ0FBQztZQUNwRSxhQUFhO1lBQ2IsZUFBZSxDQUFDLFFBQVEsR0FBRyxTQUFTLENBQUMsZUFBZSxDQUFDLFVBQVUsQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQzVFLFVBQVUsSUFBSSxDQUFDLENBQUM7WUFDaEIsYUFBYTtZQUNiLGVBQWUsQ0FBQyxRQUFRLEdBQUcsU0FBUyxDQUFDLGVBQWUsQ0FBQyxVQUFVLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUM1RSxVQUFVLElBQUksQ0FBQyxDQUFDO1lBQ2hCLGFBQWE7WUFDYixlQUFlLENBQUMsUUFBUSxHQUFHLFNBQVMsQ0FBQyxZQUFZLENBQUMsVUFBVSxDQUFDLENBQUM7U0FDOUQ7UUFFRCxJQUFJLFNBQVMsR0FBRyxTQUFTLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxvQkFBb0IsR0FBRyxxQkFBcUIsR0FBRyxlQUFlLENBQUMsQ0FBQztRQUN0RyxJQUFJLFNBQVMsQ0FBQyxNQUFNLElBQUksQ0FBQyxHQUFHLEVBQUUsRUFBRTtZQUMvQixtQkFBbUI7WUFDbkIsSUFBSSxVQUFVLEdBQUcsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLG9CQUFvQixHQUFHLHFCQUFxQixHQUFHLGVBQWUsQ0FBQyxDQUFDO1lBQzFHLElBQUksSUFBSSxHQUFHLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQ2pDLElBQUksSUFBSSxHQUFHLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1lBQ2xDLFNBQVMsR0FBRyxTQUFTLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBRWhDLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUEsY0FBSSxFQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxVQUFVLEVBQUUsSUFBSSxDQUFDLENBQUMsRUFBRSxRQUFRLENBQUMsQ0FBQyxFQUFFO2dCQUNwRSxPQUFPLElBQUksQ0FBQzthQUNaO1lBRUQsSUFBSSxlQUFlLEVBQUU7Z0JBQ3BCLGFBQWE7Z0JBQ2IsZUFBZSxDQUFDLFFBQVEsR0FBRyxTQUFTLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDO2FBQ3JEO1NBQ0Q7UUFFRDtZQUNDLHdCQUF3QjtZQUN4QixXQUFXO1lBQ1gsbUJBQW1CO1lBQ25CLFNBQVM7WUFDVCxVQUFVO1lBQ1YsVUFBVTtZQUNWLFVBQVU7WUFDVixVQUFVO1NBQ1YsQ0FBQyxPQUFPLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRTtZQUNqQixPQUFPLGVBQWUsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUM3QixDQUFDLENBQUMsQ0FBQztRQUVILE9BQU8sZUFBZSxDQUFDO0tBQ3ZCO0lBQUMsT0FBTyxFQUFFLEVBQUU7UUFDWixPQUFPLElBQUksQ0FBQztLQUNaO0FBQ0YsQ0FBQztBQXBFRCwwREFvRUMifQ==