196 lines
6.2 KiB
HTML
196 lines
6.2 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<title>Proxifier keygen</title>
|
|
</head>
|
|
<body>
|
|
<div>
|
|
<label for="product">Product:</label>
|
|
<select id="product">
|
|
<option value="0">Proxifier Standard Edition</option>
|
|
<option value="1">Proxifier Portable Edition</option>
|
|
<option value="2">Proxifier for Mac</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div>
|
|
<label for="exp-year">Exp. year:</label>
|
|
<input type="number" min="2000" value="2077" id="exp-year" />
|
|
</div>
|
|
|
|
<div>
|
|
<label for="exp-month">Exp. month:</label>
|
|
<input type="number" min="1" max="12" value="12" id="exp-month" />
|
|
</div>
|
|
|
|
<div>
|
|
<label for="fourth">4th part:</label>
|
|
<input
|
|
maxlength="5"
|
|
pattern="[0-9A-Z]+"
|
|
id="fourth"
|
|
placeholder="random"
|
|
value="SORRY"
|
|
/>
|
|
</div>
|
|
|
|
<button onclick="updateKey()">Generate</button>
|
|
|
|
<hr />
|
|
|
|
<p
|
|
style="text-align: center; font-weight: bold; font-size: 1.4em"
|
|
id="key"
|
|
></p>
|
|
</body>
|
|
<script>
|
|
const keyEl = document.querySelector('#key')
|
|
const productEl = document.querySelector('#product')
|
|
const expYearEl = document.querySelector('#exp-year')
|
|
const expMonthEl = document.querySelector('#exp-month')
|
|
const fourthEl = document.querySelector('#fourth')
|
|
|
|
window.onload = updateKey
|
|
productEl.onchange = updateKey
|
|
expYearEl.onchange = updateKey
|
|
expMonthEl.onchange = updateKey
|
|
fourthEl.onchange = updateKey
|
|
|
|
function updateKey() {
|
|
const expiry =
|
|
(parseInt(expYearEl.value) - 2000) * 12 +
|
|
(parseInt(expMonthEl.value) - 1)
|
|
keyEl.innerText = generateKey(
|
|
parseInt(productEl.value),
|
|
fourthEl.value,
|
|
expiry
|
|
)
|
|
}
|
|
|
|
// below is based on
|
|
// https://github.com/thedroidgeek/proxifier-keygen/blob/master/ProxifierKeygen/Keygen.cs
|
|
function randRange(from, to) {
|
|
return from + Math.round(Math.random() * (to - from))
|
|
}
|
|
|
|
function compileString(str) {
|
|
let result = 0
|
|
for (let i = str.length - 1; i >= 0; i--) {
|
|
result *= 32
|
|
const c = str[i]
|
|
|
|
if (c === 'W') {
|
|
continue
|
|
}
|
|
|
|
if (c === 'X') {
|
|
result += 24
|
|
} else if (c === 'Y') {
|
|
result += 1
|
|
} else if (c === 'Z') {
|
|
result += 18
|
|
} else if (c <= 57) {
|
|
// '0' to '9'
|
|
result += c.charCodeAt(0) - 48
|
|
} // 'A' to 'V'
|
|
else {
|
|
result += c.charCodeAt(0) - 55
|
|
}
|
|
}
|
|
return result >>> 0
|
|
}
|
|
|
|
function decompileString(value, length) {
|
|
value >>>= 0
|
|
let result = ''
|
|
for (let i = 0; i < length; i++) {
|
|
const tmp = value % 32
|
|
value = Math.trunc(value / 32)
|
|
|
|
if (tmp === 0) {
|
|
result += 'W'
|
|
} else if (tmp === 24) {
|
|
result += 'X'
|
|
} else if (tmp === 1) {
|
|
result += 'Y'
|
|
} else if (tmp === 18) {
|
|
result += 'Z'
|
|
} else if (tmp <= 9) {
|
|
result += String.fromCharCode(tmp + 48)
|
|
} else {
|
|
result += String.fromCharCode(tmp + 55)
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
function crc32LikeThingy(data) {
|
|
data = new Uint8Array(data)
|
|
let result = -1
|
|
for (let i = 0; i < 12; i++) {
|
|
result ^= data[i] << 24
|
|
for (let j = 0; j < 8; j++) {
|
|
if (result < 0) {
|
|
result <<= 1
|
|
result ^= 0x4c11db7
|
|
} else {
|
|
result <<= 1
|
|
}
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
function chunk(str, size) {
|
|
let chunks = []
|
|
let pos = 0
|
|
while (pos < str.length) {
|
|
chunks.push(str.substr(pos, size))
|
|
pos += size
|
|
}
|
|
return chunks
|
|
}
|
|
|
|
function generateKey(
|
|
product = 0,
|
|
fourthKeyPart = '',
|
|
expirationDate = 0
|
|
) {
|
|
const charset = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
|
const param1 =
|
|
randRange(
|
|
0x2580,
|
|
0xffff
|
|
) /* < 0x2580 ==> outdated key message */ +
|
|
(product << 21)
|
|
const param2 =
|
|
randRange(0, 0xffff) +
|
|
(expirationDate << 16) /* 0 ==> no expiration */
|
|
|
|
while (fourthKeyPart.length < 5) {
|
|
fourthKeyPart += charset[randRange(0, charset.length - 1)]
|
|
}
|
|
|
|
const param3 = compileString(fourthKeyPart)
|
|
const data = new ArrayBuffer(12)
|
|
const intArr = new Int32Array(data)
|
|
intArr[0] = param1
|
|
intArr[1] = param2
|
|
intArr[2] = param3
|
|
const value1 = crc32LikeThingy(data) & 0x1ffffff
|
|
const value2 = value1 ^ (value1 << 7)
|
|
const value3 = param1 ^ value2 ^ 0x12345678
|
|
const value4 = param2 ^ value2 ^ 0x87654321
|
|
let key = decompileString(value3, 7)
|
|
key += decompileString(value4, 7)
|
|
key += key[2] // 15th char becomes 3rd
|
|
key += fourthKeyPart
|
|
key += decompileString(value1, 5)
|
|
// 3rd char doesn't affect the key check, as long as it's not a 'Y' ==> Proxifier v2 key (outdated)
|
|
let rndChar = charset[randRange(0, charset.Length - 1)]
|
|
if (rndChar === 'Y') rndChar = 'Z'
|
|
return chunk(key, 5).join('-')
|
|
}
|
|
</script>
|
|
</html>
|