Skip to content

Instantly share code, notes, and snippets.

@liath
Last active March 20, 2020 23:47
Show Gist options
  • Save liath/7fa52509b7f754b65d6525bd5096d8c2 to your computer and use it in GitHub Desktop.
Save liath/7fa52509b7f754b65d6525bd5096d8c2 to your computer and use it in GitHub Desktop.
Emulating C-style integer maths in javascript
/* eslint no-console:0, func-names:0 */
// JS ints are signed, which isn't useful here. Unfortunately,
// this means << can flip the sign bit and give a negative
// number which throws everything off. Luckily, we know how to
// handle this. The below is an unsigned leftshift implementation.
const ls = (input, shift) => ((input << shift) >>> 1) * 2;
// Integer casts that drop overflowing data (Just like grandma used to make)
const u8 = i => (i << 24) >>> 24;
const u16 = i => (i << 16) >>> 16;
const u32 = i => i >>> 0;
// JS is kind enough to convert into 32bit ints for us when we use any bitwise operations
const compress = function compress(input, rounds) {
const lu = ['0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'I', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S',
'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
let num = input;
const builder = (new Array(rounds)).fill(' ');
let index;
for (let i = 0; i < rounds; i += 1) {
index = u32(num % 0x23);
num = Math.floor(num / 0x23);
builder[i] = lu[index];
}
return builder.join('');
};
const getHashCode = function getHashCode(host) {
let num = u32(0x1505);
let num2 = u32(0x1505);
for (let i = 0; i < host.length; i += 1) {
num = u32((ls(num, 5) + num) ^ host[i++].charCodeAt(0));
if (i < host.length) {
num2 = u32((ls(num2, 5) + num2) ^ host[i].charCodeAt(0));
}
}
return u32(num + u32(num2 * 0x5d588b65));
};
const getAuth = function getAuth(hostname) {
let loSID = getHashCode(hostname);
let hiSID = u16(getHashCode(`${hostname}|`));
const num1 = u32(loSID % 2);
const num2 = u32(hiSID % 2);
loSID = u32(ls(num2, 31) + (loSID >>> 1));
hiSID = u32(ls(num1, 15) + (hiSID >>> 1));
hiSID = u32(0x30000172 + ls(hiSID, 10));
const a = u32(hiSID % 1024);
const b = u16(hiSID >>> 26);
const d = u32((ls(hiSID, 6) >>> 16));
// Set this to fixed value for debugging purpoises. (sic)
// const first = u16(0x1337);
const first = u16(Math.floor((Math.random() * 65535)));
const fourth = u16(loSID);
const fifth = u16(loSID >>> 16);
const second = u16(ls(b, 27) + ls(d, 10) + a);
const third = u16((ls(b, 27) + ls(d, 10) + a) >>> 16);
const buffer = new Array(12);
buffer[1] = u8(first >>> 8);
buffer[0] = u8(ls(buffer[1], 8) ^ first);
buffer[3] = u8(second >>> 8);
buffer[2] = u8(ls(buffer[3], 8) ^ second);
buffer[5] = u8(third >>> 8);
buffer[4] = u8(ls(buffer[5], 8) ^ third);
buffer[7] = u8(fourth >>> 8);
buffer[6] = u8(ls(buffer[7], 8) ^ fourth);
buffer[9] = u8(fifth >>> 8);
buffer[8] = u8(ls(buffer[9], 8) ^ fifth);
buffer[10] = u8((first >>> 4) ^ 65535);
buffer[11] = 0;
let index;
for (index = 0; index < 11; index += 1) {
buffer[11] = u8(buffer[11] + buffer[index]);
}
for (index = 1; index < 6; index += 1) {
const int = index * 2;
buffer[int] = u8(buffer[int] ^ buffer[0]);
buffer[int + 1] = u8(buffer[int + 1] ^ buffer[1]);
}
const buffera = (new Array(12)).fill(0);
for (index = 0; index < 12; index += 1) {
buffera[index] = u8(buffer[index] >>> 3);
buffer[index] = u8(ls(buffer[index], 5));
}
buffer[0] = u8(buffer[0] + buffera[7]);
buffer[1] = u8(buffer[1] + buffera[0]);
buffer[2] = u8(buffer[2] + buffera[1]);
buffer[3] = u8(buffer[3] + buffera[2]);
buffer[4] = u8(buffer[4] + buffera[11]);
buffer[5] = u8(buffer[5] + buffera[4]);
buffer[6] = u8(buffer[6] + buffera[5]);
buffer[7] = u8(buffer[7] + buffera[6]);
buffer[8] = u8(buffer[8] + buffera[3]);
buffer[9] = u8(buffer[9] + buffera[8]);
buffer[10] = u8(buffer[10] + buffera[9]);
buffer[11] = u8(buffer[11] + buffera[10]);
const auth = `${
compress(u32(
ls(buffer[3], 24) +
ls(buffer[2], 16) +
ls(buffer[1], 8) +
buffer[0]), 7)
}-${
compress(u32(
ls(buffer[7], 24) +
ls(buffer[6], 16) +
ls(buffer[5], 8) +
buffer[4]), 7)
}-${
compress(u32(
ls(buffer[11], 24) +
ls(buffer[10], 16) +
ls(buffer[9], 8) +
buffer[8]), 7)
}`;
const sid = `${compress(hiSID, 7)}-${compress(loSID, 7)}`;
return {auth, sid};
};
const keygen = function keygen(hostname) {
const major = [
1048335, 1048334, 1048333, 1048332, 1048331, 1048330, 1048329, 1048328,
1048327, 1048326, 1048325, 1048324, 1048323, 1048322, 1048321, 1048320
][Math.floor(Math.random() * 16)];
return `Serial:${
(ls(major, 1) ^ major)
}\nProduct Code: ${
compress(major, 5)
}-XA${
compress(major << 1, 5)
}\nMachine Name: ${
hostname
}\nAuth Code: ${
getAuth(hostname).auth
}\n`;
};
const hostname = 'Tilt'.toUpperCase();
console.log(keygen(hostname));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment