As we all know, we can store a set of boolean values (Yes or No, True of False) in a integer (signed or unsigned). For example, you can define constants which are power of two,
define('ATTRIB_1', 1);
define('ATTRIB_2', 2);
define('ATTRIB_3', 4);
define('ATTRIB_4', 8);
/* ..... */
A 32-bit integer can have 32 boolean values and 64-bit integer can have 64 boolean values. To check a state (integer) has somewhat attributes, you can do a logic and (&) operation, e.g.
function check($x) {
return $x & ATTRIB_1;
}
A state can be combined, so you can do $x = $x | ATTRIB_1 or $x = ATTRIB_1 + ATTRIB_2 but using or (|) is preferred, because you will plus will not work as expected when the value contains that particular set bit unless you know it does not, e.g. constants definitions.
We can then first convert the integer to capital letters, using ‘A’ to ‘Z’ only.
function convertTo26($x) {
$r = "";
while ($x) {
$r = chr(($x - 1) % 26 + 65).$r;
$x = (int)(($x - 1)/ 26);
}
return $r;
If you can limit the number of set bits, for example, if there are only 16 maximum flags, so you can limit this to 16-bit integer only, using & 0xFFFF.
We can also add a check, to verify easily the number in the string. We can count the number of set bits (For more information, please visit this C++ function).
function getCounter($i) {
$i = $i - (($i >> 1) & 0x55555555);
$i = ($i & 0x33333333) + (($i >> 2) & 0x33333333);
$i = ($i + ($i >> 4)) & 0x0f0f0f0f;
$i = $i + ($i >> 8);
$i = $i + ($i >> 16);
return $i & 0x3f;
}
If we limit the part of number representation to 5 digits, we can pad the ‘X’ because the 16-bit integer, the first number can only go up to ‘C’.
function getModuleString($x) {
$x = $x & 0xFFFF;
$y = convertTo26(getCounter($x)).convertTo26($x);
return str_pad($y, 5, "X", STR_PAD_LEFT);
}
Now, to decode the string to number, we can use a function to convert ‘A’…’Z’ string to number.
function convertTo10($x) {
$len = strlen($x);
$r = 0;
for ($i = 0; $i < $len; $i ++) {
$r = $r * 26 + ord(strtoupper($x[$i])) - 64;
}
return $r;
}
But we have to skip the ‘X’ in the front, because it is used only for padding purposes. And then we extract the checksum. The rest of the string denote a integer, check the number of set bits to see it is equal to the checksum.
function getLic($x) {
$len = strlen($x);
$i = 0;
while (($i < $len) && (($x[$i] == 'X') || ($x[$i] == 'x'))) $i++;
if ($i == $len) return false;
$c = $x[$i];
$s = substr($x, $i + 1);
$cc = convertTo10($c);
$ss = convertTo10($s);
if (getCounter($ss) == $cc) {
return $ss;
}
return -1;// Invalid license key
}
We can print the values to verify the correctness.
for ($i = 0; $i < 100; $i ++) {
$x = getModuleString($i);
echo $i." = ".$x." = ".getLic($x)."
";
}
And
for ($i = 0; $i < 100; $i ++) {
$x = getModuleString($i);
echo $i." = ".$x."
";
}
This will print out:
0 = XXXXX 1 = XXXAA 2 = XXXAB 3 = XXXBC 4 = XXXAD 5 = XXXBE 6 = XXXBF 7 = XXXCG 8 = XXXAH 9 = XXXBI 10 = XXXBJ 11 = XXXCK 12 = XXXBL 13 = XXXCM 14 = XXXCN 15 = XXXDO 16 = XXXAP 17 = XXXBQ 18 = XXXBR 19 = XXXCS 20 = XXXBT 21 = XXXCU 22 = XXXCV 23 = XXXDW 24 = XXXBX 25 = XXXCY 26 = XXXCZ 27 = XXDAA 28 = XXCAB 29 = XXDAC 30 = XXDAD 31 = XXEAE 32 = XXAAF 33 = XXBAG /* ... */
So we can append this string into a key (e.g. License key) and decode the key string in the client side of the software. Based on the number (set of booleans), we can control the functionalities of the software.
This is OK if the license verification is done at server side because it doesn’t matter that the string is decrypted. The key is readonly so the users can’t do much regarding to the key string.
This serves the way to store a integer (hide it) in a license key string.
–EOF (The Ultimate Computing & Technology Blog) —
740 wordsLast Post: C/C++ Coding Exercise - Unique Paths II - Dynamic Programming with Obstacles - Leetcode Online Judge - DP with Constraints
Next Post: Output a String to Console (BBG-DOS) using 6502 Assembly for 8-bit Famicom Clone BBG - Tutorial 4