Create Tracktion Marketplace key file via php

Hi Jules,

 

is it possible to create the key file for the tracktion marketplace module with a php script? 

I peeked at the code of the main() function of TracktionMarketplaceKeyGeneration and it looks like it just creates amd encrypts a XML file with the RSA class, so these tasks should be possible with php using  phpseclib and a random XML library.

Before I refresh my dusty knowledge of php and get my hands dirty, is there something I missing here? Having this as PHP script would allow me to use my shared web hoster for this - as you mentioned somewhere I try to avoid the pain of setting up a own server.

Thanks!

Personally, I'd suggest building a little server-side command line exe that generates the key, and invoke that from php. That's how we do it in the tracktion server. Most web hosts allow you to run CGI exes.

1 Like

Damn, just got a reply from my hoster that I need a virtual server package for this. 

I'll give PHP a quick chance and if I don't come up with something that works, I'll consider upgrading my webhosting...

Anyway, is there an option to disable the Machine ID property? I don't want to limit a licence to a users machine (so he can simply copy his licence file on his laptop and take my stuff on the road).

 

If you don't want to use the machine number, you could just return a constant one - you can override the method that generates it.

Ah great!

All right, just for other people who would be interested, I hacked this little PHP snippet together - really copy and pasty, but it seems to work (I bypassed the machine ID stuff):


<?php
/** PHP script that creates an unlock file for the Tracktion Marketplace Status. */
/** Variables */
$PRODUCT_ID = "YOUR PRODUCT";
$EMAIL = "YOUR EMAIL";
$USER = "YOUR NAME";
$DATE = date("j M Y g:i:sa");
$MACHINE = "BYPASS";
$TIME = dec2hex(round(microtime(true)*1000));

$PRIVATE_KEY_PART_1 = "742ccf57e16f84bb"; // These are stupid 64bit keys for developing, but it should run with big keys too...
$PRIVATE_KEY_PART_2 = "ae4337057c0e3f6f";

header('Content-Description: File Transfer');
header('Content-Type: text/plain');
header('Content-Disposition: attachment; filename='.$PRODUCT_ID.'.licence');
header('Content-Transfer-Encoding: UTF-8');
header('Expires: 0');
        
/** Helper Functions */
function dec2hex($number)
{
    $hexvalues = array('0','1','2','3','4','5','6','7',
               '8','9','a','b','c','d','e','f');
    $hexval = '';
     while($number != '0')
     {
        $hexval = $hexvalues[bcmod($number,'16')].$hexval;
        $number = bcdiv($number,'16',0);
    }
    return $hexval;
}

include ('Math/BigInteger.php');  // get this from: phpseclib.sourceforge.net
function applyToValue ($message, $key_part1, $key_part2)
{
    $result = new Math_BigInteger();
    $zero  = new Math_BigInteger();
    $value = new Math_BigInteger (strrev ($message), 256);
    $part1 = new Math_BigInteger ($key_part1, 16);
    $part2 = new Math_BigInteger ($key_part2, 16);
    while (! $value->equals ($zero))
    {
        $result = $result->multiply ($part2);
        list ($value, $remainder) = $value->divide ($part2);
        $result = $result->add ($remainder->modPow ($part1, $part2));
    }
    return $result->toHex();
}

// Create the comment section
echo "Keyfile for ", $PRODUCT_ID, "\n";
echo "User: ", $USER, "\n";
echo "Email: ", $EMAIL, "\n";
echo "Machine numbers: ", "\n";
echo "Created: ", $DATE, "\n";
echo "\n";
// Create the XML 
$dom = new DOMDocument("1.0", "utf-8");
$root = $dom->createElement("key");
$dom->appendChild($root);
$root->setAttribute("user", $USER);
$root->setAttribute("email", $EMAIL);
$root->setAttribute("mach", $MACHINE);
$root->setAttribute("app", $PRODUCT_ID);
$root->setAttribute("date", $TIME);
$XML_STRING = $dom->saveXML();
$ENCRYPTED_XML = "#" . applyToValue($XML_STRING, $PRIVATE_KEY_PART_1, $PRIVATE_KEY_PART_2);
$XML_DATA = chunk_split($ENCRYPTED_XML, 70);
echo $XML_DATA;
?>

This is the TracktionMarketplaceStatus subclass:

 


class Unlocker: public TracktionMarketplaceStatus
{
public:
    Unlocker():
        state(String::empty)
    {}
    String getMarketplaceProductID()
    {
        return PRODUCT_ID;
    }
    RSAKey getPublicKey() override
    {
        return RSAKey(PUBLIC_KEY);
    }
    String getState() override
    {
        return state;
    };
    StringArray getLocalMachineIDs() override
    {
        StringArray sa;
        sa.add("BYPASS");
        return sa;
    };
    void saveState(const String &s) override
    {
        state = s;
    }
private:
    String state;
};

This is all far from being finished, but it may be a good starting point for other people who want to use the module on their web host.

 

1 Like