HISE Logo Forum
    • Categories
    • Register
    • Login

    build failed with copy protection enabled

    Scheduled Pinned Locked Moved Bug Reports
    15 Posts 5 Posters 1.2k Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • ustkU
      ustk @Christoph Hart
      last edited by ustk

      @christoph-hart Much clearer, thanks! I'll see if I can get on with the productCheckFunction once the first bit works

      Can't help pressing F5 in the forum...

      Christoph HartC 1 Reply Last reply Reply Quote 0
      • Christoph HartC
        Christoph Hart @ustk
        last edited by

        @ustk You don't need to define that function, the default will just compare the product name against the one in your key file (I removed the version number as default check), so unless you want some custom checks (eg. invalidate license key files with version upgrades, etc), leave that one alone :)

        ustkU 1 Reply Last reply Reply Quote 1
        • ustkU
          ustk @Christoph Hart
          last edited by

          @christoph-hart Ok so I get weird things... Maybe you could just add a minimal project in the tutorial repo?

          Can't help pressing F5 in the forum...

          1 Reply Last reply Reply Quote 3
          • Matt_SFM
            Matt_SF
            last edited by

            @Christoph-Hart would be nice indeed ! +1 🙂

            Develop branch
            Win10 & VS17 / Ventura & Xcode 14. 3

            1 Reply Last reply Reply Quote 0
            • ustkU
              ustk @Christoph Hart
              last edited by

              @Christoph-Hart So I finally got the unlocker to work. I'm not yet ready to create the file server side, so for now I fake it in Hise using a dummy license file.
              Though something seems weird with the license system, but chances are it is me not understanding.

              When a license file is created, it is created from the RSA pair (that is the same for all instances/installation).
              So what prevent anyone to share the file? I don't imagine it is the non-crypted part, but the crypted part that should contain customer info. But how do you decrypt it? I tried several thing including online tools using the RSA pair with no luck...

              Can't help pressing F5 in the forum...

              Christoph HartC 1 Reply Last reply Reply Quote 0
              • Christoph HartC
                Christoph Hart @ustk
                last edited by

                @ustk The license file embeds a machine identification so it can only be used on the system that created the file. Your responsibility on the server side is to write a method that takes this information and returns a key file. We're using it in the current project and the activation function looks more or less like this:

                inline function activationAttempt()
                {	
                	local parameters = {};
                	
                	parameters.email = Content.getComponent("emailInput").get("text");
                	parameters.machineID = FileSystem.getSystemId();
                	parameters.version = Engine.getVersion();
                	parameters.OS = Engine.getOS();
                	parameters.productID = "Our Funky Product";
                	parameters.serial = Content.getComponent("serialInput").get("text");
                	
                        // Your server must implement this function and either return an error string or the encrypted key file using the same RSA key as embedded into the plugin
                	Server.callWithPOST("activate", parameters, onServerActivate);
                	
                	return false;
                }
                
                function onServerActivate(status, obj)
                {
                	if(status != 200)
                	{
                               // obj is an error string
                		Console.print(obj);
                	}
                	else
                	{
                                // obj is the key file content
                		unlocked = ul.writeKeyFile(obj);
                		
                		if(unlocked)
                		{
                			Console.print("Nice");
                		}
                		else
                		{
                			Console.print("SUPER CRITICAL ERROR. WHY");
                		}
                	}
                }
                

                The beauty of this is you don't need to decrypt anything manually, this is done all by the system (the public RSA key for decrypting the content gets mangled into the plugin binary).

                ustkU 1 Reply Last reply Reply Quote 1
                • ustkU
                  ustk @Christoph Hart
                  last edited by ustk

                  @Christoph-Hart Easier than I thought, so it is already working :)
                  Well, still the server side to to create the license file, which is not a small rock to move...

                  Can't help pressing F5 in the forum...

                  Christoph HartC 1 Reply Last reply Reply Quote 0
                  • Christoph HartC
                    Christoph Hart @ustk
                    last edited by Christoph Hart

                    @ustk I've posted a PHP snipped on the JUCE forum which you can use as starting point:

                    <?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;
                    ?>
                    

                    But if anyone is motivated to do a .js version (or whatever server language is the cool kid as we speak), it might be better than this ugly hack.

                    ustkU 1 Reply Last reply Reply Quote 2
                    • ustkU
                      ustk @Christoph Hart
                      last edited by

                      @Christoph-Hart Yeah thanks, I remember you posted this on the Juces forum, thanks!

                      Can't help pressing F5 in the forum...

                      1 Reply Last reply Reply Quote 0
                      • P
                        parabuh
                        last edited by

                        Hey, any of you managed to write working code in node?

                        I'm not good in backend but I made something like this

                        import {create} from 'xmlbuilder2'
                        import bigInt from 'big-integer'
                        
                        const PRODUCT_ID = "PRODUCT NAME"
                        const EMAIL = "user@example.com"
                        const USER = "user"
                        const MACHINE = "XXXXXXX"
                        
                        
                        class RSAKey {
                            constructor(key) {
                                const keys = key.split(',');
                        
                                this.k1 = this.toHex(keys[0])
                                this.k2 = this.toHex(keys[1])
                            }
                        
                            toHex(str) {
                                let result = '';
                                for (let i = 0; i < str.length; i++) {
                                    result += str.charCodeAt(i).toString(16);
                                }
                                return result;
                            }
                        
                            applyToValue(message) {
                        
                                let result = bigInt.zero
                                const zero = bigInt.zero
                                const value = bigInt(message, 256)
                                const key1 = bigInt(this.k1)
                                const key2 = bigInt(this.k2)
                        
                                result = key2.multiply(result);
                                const {quotient, remainder} = value.divmod(key2)
                                result = result.add(remainder.modPow(key1, key2))
                        
                                return result.toString(16);
                            }
                        }
                        
                        const root = create({version: '1.0'})
                            .ele('key')
                            .att("user", USER)
                            .att("email", EMAIL)
                            .att("mach", MACHINE)
                            .att("app", PRODUCT_ID)
                        
                        
                        const xml = root.end()
                        
                        const rsa = new RSAKey('2c69e2b65085061fc4ecc0f48523d1cf8ae55e1ea2aa111cef8d766273d5850539914c0e48ce199904611ec7a6eff1bf167f5aa70bf05e03213945a3538b81fd,6f08b6c7c94c8f4f6c4fe2634cd98c86db3d6b4c96a92ac856e1a7f62195cc8e6b17a6c7c50ee2b8bfb59e7e3dffd752917d328e52019f337488beac3f545b5f');
                        
                        const result = rsa.applyToValue(rsa.toHex(xml))
                        console.log(result)
                        
                        process.exit(0)
                        

                        Everything seems be ok and I can generate key but is much shorten than this fake one generated in hise.

                        Christoph HartC 1 Reply Last reply Reply Quote 0
                        • Christoph HartC
                          Christoph Hart @parabuh
                          last edited by

                          @parabuh Have you compared the output with the PHP snippet I posted above? I don't know node.js but I think if you just recreate the PHP thingie you should be able to compare and match the outputs of those two.

                          It obviously depends on the external libraries for big integers and XML creation that you use and how they handle bit order and whatnot.

                          1 Reply Last reply Reply Quote 0
                          • S
                            Sawer
                            last edited by

                            Hello @ustk
                            How is this whole method works?
                            Just want to understand the RSA using a dummy License in the plugin.
                            I'm trying to create just a a demo to get an understanding of how this whole thing works, but there's no documentation and as well as I'm not getting fulfilling inputs here in the forum.
                            Seems like this method is more effective than the simple copy protection.
                            Any help is appreciated

                            1 Reply Last reply Reply Quote 0
                            • ustkU ustk referenced this topic on
                            • First post
                              Last post

                            23

                            Online

                            1.7k

                            Users

                            11.8k

                            Topics

                            102.5k

                            Posts