Hi
Im very dissapointed with this addon i tought it will be very similar to downloads on other xf site.
See:
View attachment 5276
Their shop generates random serial/lic number. Thats perfect.
I checked rm marketplace db and i did not found any unique keys for purchases.
View attachment 5273
Unique lic key is important for future validation digital goods validation which can be super easy.
Here are my ideas...
To improve this addon three things are required:
1) generating of license key for digital goods
2) licence validate from client-side
3) proxy digital goods downloads to inject lic_key automatically
And this should be very easy.
Here are my ideas.
#1 -> generate uniq lic_key
#2 -> lic validation:
digital_goods side:
#3 -> proxy download resource and inject lic_key
Hope this helps.
This could be massive addon for XF then.
Thank you
Best regards
Im very dissapointed with this addon i tought it will be very similar to downloads on other xf site.
See:
View attachment 5276
Their shop generates random serial/lic number. Thats perfect.
I checked rm marketplace db and i did not found any unique keys for purchases.
View attachment 5273
Unique lic key is important for future validation digital goods validation which can be super easy.
Here are my ideas...
To improve this addon three things are required:
1) generating of license key for digital goods
2) licence validate from client-side
3) proxy digital goods downloads to inject lic_key automatically
And this should be very easy.
Here are my ideas.
#1 -> generate uniq lic_key
uniq_lic.php
PHP:
<?php
function uniq_serial($data = null) {
$data = $data ?? random_bytes(13);
assert(strlen($data) == 13);
$data[2] = chr(ord($data[2]) & 0x0f | 0x40);
$data[6] = chr(ord($data[6]) & 0x3f | 0x80);
return vsprintf('%s-%s-%s-%s-%s', str_split(bin2hex($data), 5));
}
$purchase_lic_key = uniq_serial();
// store here lic key to db $purchase_lic_key
echo 'Unique purchase serial: ' . strtoupper($purchase_lic_key);
// output:
// Unique purchase serial: B21C4-B09DF-A997A-CDD8F-62E63
#2 -> lic validation:
validate_lic_server.php
PHP:
<?php
// key validation, side: host (xf instance)
// eg. usage:
// validate_lic_server.php?lic=B21C4-B09DF-A997A-CDD8F-62E63
$validation_salt='xenforo'; //configured by user
$fake_salt='f4k3enc'; //configured by user
// break if no key to check
if(!isset($_GET['lic']) or empty($_GET['lic'])){
exit();
}
$lic_key=$_GET['lic'];
function encrypt($data, $password){
$iv = substr(sha1(mt_rand()), 0, 16);
$password = sha1($password);
$salt = sha1(mt_rand());
$saltWithPassword = hash('sha256', $password.$salt);
$encrypted = openssl_encrypt(
"$data", 'aes-256-cbc', "$saltWithPassword", null, $iv
);
$msg_encrypted_bundle = "$iv:$salt:$encrypted";
return $msg_encrypted_bundle;
}
// first read db and check
// if $lic_key not found:
// exit();
// if found and expired:
// // return fake response
// $fake_lic=random_bytes(29);
// echo encrypt($fake_lic, $fake_salt)
// exit();
//if found and not expired:
echo encrypt($lic_key, $validation_salt);
exit();
// output is different each time for same lic_key, eg.:
// 8464e744b1b8b3ac:ef1fff98eeff36a6b407ede555d3eb3b96746dbe:+QcRcXX3eoyNxPENkyz/n1+/5ECRDm4VvIololjg7hQ=
// 106fe114e92e3e28:3ed9626f06cdb2892b10eb93134565802efd3ca4:qfUxlN6b4VLZh+fs88KWlIFY+S9Go+IuN7OV8OHmJfM=
// 7e638e19b5182dd5:dc96cc5b8fb17063c7201e7b3e930daf6a41dcec:cYVTq7JW21jzBQ0DuhR6kUOlGaNsNYWqAYBXK1rNODM=
// ...
//
// go to client side now...
//
// $auth_param=urlencode('106fe114e92e3e28:3ed9626f06cdb2892b10eb93134565802efd3ca4:qfUxlN6b4VLZh+fs88KWlIFY+S9Go+IuN7OV8OHmJfM=');
// echo $auth_param;
//
// usage:
// validate_lic_client.php?auth=106fe114e92e3e28%3A3ed9626f06cdb2892b10eb93134565802efd3ca4%3AqfUxlN6b4VLZh%2Bfs88KWlIFY%2BS9Go%2BIuN7OV8OHmJfM%3D
digital_goods side:
validate_lic_client.php
PHP:
<?php
// key validation, client side: digital goods anti-piracy snippet
// eg. usage:
// validate_lic_client.php?auth=106fe114e92e3e28:3ed9626f06cdb2892b10eb93134565802efd3ca4:qfUxlN6b4VLZh+fs88KWlIFY+S9Go+IuN7OV8OHmJfM=
$validation_salt='xenforo'; //configured by user
// break if no key to check
if(!isset($_GET['auth']) or empty($_GET['auth'])){
exit();
}
$auth_key=$_GET['auth'];
function decrypt($msg_encrypted_bundle, $password){
$password = sha1($password);
$components = explode( ':', $msg_encrypted_bundle );
$iv = $components[0];
$salt = hash('sha256', $password.$components[1]);
$encrypted_msg = $components[2];
$decrypted_msg = openssl_decrypt(
$encrypted_msg, 'aes-256-cbc', $salt, null, $iv
);
if ( $decrypted_msg === false )
return false;
return $decrypted_msg;
}
$d = decrypt($auth_key,$validation_salt);
echo $d;
// output:
// B21C4-B09DF-A997A-CDD8F-62E63
// eg. usage:
// validate_lic_client.php?lic=B21C4-B09DF-A997A-CDD8F-62E63&auth=106fe114e92e3e28:3ed9626f06cdb2892b10eb93134565802efd3ca4:qfUxlN6b4VLZh+fs88KWlIFY+S9Go+IuN7OV8OHmJfM=
echo '<br>';
if(!isset($_GET['lic']) or empty($_GET['lic'])){
exit();
}
$lic_key=$_GET['lic'];
if($lic_key = $d){
echo 'Decrypted auth and lic_key are same.';
} else {
echo 'Auth_key does not match lic_key';
// anti-piracy rules here...
}
// output:
// B21C4-B09DF-A997A-CDD8F-62E63
// Decrypted auth and lic_key are same.
#3 -> proxy download resource and inject lic_key
purchase_proxy.php
PHP:
<?php
$path_to_input_file="internal_data/attachment/resource_file.exe";
$FIND_CONTENT = "__TEMPLATE____AUTH_CONTENT_REPLACE____";
$REPLACE_CONTENT = "GENUINE->B21C4-B09DF-A997A-CDD8F-62E63";
$cmd_xxd=shell_exec('command -v xxd');
$cmd_sed=shell_exec('command -v sed');
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . basename($proxy_src_file) . '"');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($proxy_src_file)); // content size must not change after injecting lic_key
// inject lic_key and output content on-the-fly
if (!empty($cmd_sed)){
if (!empty($cmd_xxd)){
echo shell_exec("xxd " . $path_to_input_file . " | sed \"0,/" . $FIND_CONTENT . "/s//" . $REPLACE_CONTENT . "/\" | xxd -r");
} else {
// when no xxd command found in shell, then fallback to sed command only, however this may cause binary files gets corrupted
echo shell_exec("sed \"0,/" . $FIND_CONTENT . "/s//" . $REPLACE_CONTENT . "/\" " . $path_to_input_file);
}
}
die();
// make sure to die
Hope this helps.
This could be massive addon for XF then.
Thank you
Best regards