Blowfish - on a string
-
@Lindon I do not have the time right now but I'll check this evening.
But what I can say already is that the RSA encryption is made of a public and a private key, meaning the encryption has to be made externally (online), otherwise it makes no sense to have both encryption and decryption from within the same app.This is why Christoph implemented it for the unlocker system
-
@ustk yes I understand the encryption and decryption have to be done in different applications (neither needs to be an on-line service) .
In fact if you read thru Urs comments closely you will see that he recommends AGAINST on-line based solutions as one of the things that is a single point of failure that hackers look for straight away and can work around easily...
-
@ustk said in Blowfish - on a string:
@Lindon I do not have the time right now but I'll check this evening.
But what I can say already is that the RSA encryption is made of a public and a private key, meaning the encryption has to be made externally (online), otherwise it makes no sense to have both encryption and decryption from within the same app.This is why Christoph implemented it for the unlocker system
Hey @ustk - did you get any chance to look at this?
-
I'm not sure how that's included in the binary but it will still be there in plain text somewhere I assume
The RSA Key is mangled before it's embedded into the binary. This makes it a little bit harder to crack, but I wouldn't count on it saving your protection.
But there is absolutely no point in adding a RSA protection on the scripting layer because the weak point is the plainly readable script code, not the encryption algorithm.
-
@Christoph-Hart said in Blowfish - on a string:
I'm not sure how that's included in the binary but it will still be there in plain text somewhere I assume
The RSA Key is mangled before it's embedded into the binary. This makes it a little bit harder to crack, but I wouldn't count on it saving your protection.
But there is absolutely no point in adding a RSA protection on the scripting layer because the weak point is the plainly readable script code, not the encryption algorithm.
sigh - once more with feeling.....
Please please please please please go read the entirety of what Urs has to say on this subject, I've posted the links above.
But your are correct having RSA keys does not offer a complete solution, because as you point out the scripting is visible, as it is in any solution - including "calling home" ones oft recommended and promoted here.
What having RSA does (and the only thing it does for you) is stop keygens. You encode a set of serial numbers outside of the plugin using the private key, you give one encoded serial to each valid customer. The plugin uses the public key to decrypt this serial - and check against the array of serials (that is clearly viewable by the pirate) inside the plugin.
The pirate cannot generate new serials because they dont have the private key, so they must alter the code itself, and then ship this "cracked" version.
This is all I'm trying to do in this first step of the ongoing battle. It is the SIMPLEST way to make the pirate hack the script. Simpler by far than some call home server based solution, which if you read Urs commentary you will see is the first thing the pirate looks for and circumvents.
Every single solution that uses scripts in ANY way is as vulnerable as any other - but RSA encryption of serials is (as far as I can see) the cheapest and easiest way to force the pirate to the next stage of hacking...
..and as an aside gives me a way to validate server messages at some point in the future...
-
If you think this is your line of defense
The pirate cannot generate new serials because they dont have the private key,
then this is the attack vector:
and check against the array of serials (that is clearly viewable by the pirate) inside the plugin.
A keygen would simply contain the "clearly viewable" list of valid serials and spit out one of them:
inline function nastyKeygen() { return extractedKeys[Math.randInt(0, extractedKeys.length)]; }
If you want to up your copy protection game, just use the ScriptLocker class. This enforces a system identification and a server call, but if your server is hacked, then you might as well give up.
-
@Christoph-Hart said in Blowfish - on a string:
If you think this is your line of defense
The pirate cannot generate new serials because they dont have the private key,
then this is the attack vector:
and check against the array of serials (that is clearly viewable by the pirate) inside the plugin.
A keygen would simply contain the "clearly viewable" list of valid serials and spit out one of them:
inline function nastyKeygen() { return extractedKeygens[Math.randInt(0, extractedKeygens.length); }
If you want to up your copy protection game, just use the ScriptLocker class. This enforces a system identification and a server call, but if your server is hacked, then you might as well give up.
well I think one of us doesn't understand RSA = it could well be me....
Heres a serial: 1234-1234
I take the encrypting(private) key and generate an encrypted version....
qw247dnwpoie75hb4985345h34
I give this to my customer....
My app asks for this encrypted key:...
The app contains the decrypting(public) key:
333eee333eerr444rrr
it uses this public key to decrypt it the serial provided by the user, getting:
1234-1234
it checks against the array of valid serials held in the app:
1234-1234
5668-5678
2345-6784
2291-6144its present so valid all good....
Along comes my pirate, he gets a copy of my app:
he can see the list of serials...
1234-1234
5668-5678
2345-6784
2291-6144he can see the public key:
333eee333eerr444rrr
Okay so now he needs to generate an encrypted serial that will be decrypted by the public key....for that he needs the private key....he doesn't have it..and its very complex to get it. So he will have to hack the code.
Did I misunderstand something?
-
@Lindon so I think what I'm looking for is these JUCE calls to be implemented in HISE
static void RSAKey::createKeyPair( RSAKey & publicKey, RSAKey & privateKey, int numBits, const int * randomSeeds = nullptr, int numRandomSeeds = 0 )
which is a convenience but gives me two RSA keys...
and this:
bool RSAKey::applyToValue(BigInteger & value)const
which I can use with the encoding key to encode my serials, and with the decoding key to decode them...
-
@Lindon Actually, no, you're right. I forgot the decryption step in my calculations...
Alright, you win. But I would recommend to not store serials inside the plugin (unnecessary loading time for parsing ten of thousands of JSON strings, possibility of license overflow), but to just check them with any arbitrary logic:
isSerialValid(decryptedSerial) { return decryptedSerial.charAt(4) = 'A'; // or something a bit more secure... }
then only generate serials that match against that filter in your keygen.
-
@Christoph-Hart said in Blowfish - on a string:
@Lindon Actually, no, you're right. I forgot the decryption step in my calculations...
Alright, you win. But I would recommend to not store serials inside the plugin (unnecessary loading time for parsing ten of thousands of JSON strings, possibility of license overflow), but to just check them with any arbitrary logic:
isSerialValid(decryptedSerial) { return decryptedSerial.charAt(4) = 'A'; // or something a bit more secure... }
then only generate serials that match against that filter in your keygen.
hmm, yeah that looks good... - still I'd like to be in the position to require "tens of thousands" of strings....LOL.
The actual next thing to do is to recreate the decrypt-and-check-steps in several places in the plug-in AND to do so in slightly different ways each time so the result isnt easy to just pattern match trace in the script...the to defer some of them, time and functionality based...
-
Alright, it's pushed (won't show up in the API until I'm back on my Windows system though). You can create the RSA key pairs already in the Tools menu. Just make sure you don't save it as file, or HISE will think you are using its copy protection...
// You can create those with "Tools / Create RSA Key pair, then copy to clip board and paste it here" const var publicKey = "101,6e72f1e9720ba9f28c32034c61575948f919ec78d97ad0cecd539f798084e284d983c580db1d3fb72897535305df0bc61769825f18174a46c2d524b32138f80d"; // Obviously don't include that one in your shipped product... const var privateKey = "c0889eb9cdc6a2c5afa7dde7c29645f9ba332aa8d3c32a3fa7aaac6838afdc89a1b66da08b40f71c68797a4977b00c3c3a8dcf750adc9238b1c0a42c78a4b01,6e72f1e9720ba9f28c32034c61575948f919ec78d97ad0cecd539f798084e284d983c580db1d3fb72897535305df0bc61769825f18174a46c2d524b32138f80d"; const var dummyData = "1234abc" const var encrypted = FileSystem.encryptWithRSA(dummyData, privateKey); const var decrypted = FileSystem.decryptWithRSA(encrypted, publicKey); Console.print(encrypted); Console.print(decrypted);
-
@Christoph-Hart man you're quick...Thanks.
-
@Lindon Did you get this implemented yet?
-
@dustbro Paste the code into a script and find out :)
-
@Christoph-Hart I have no doubt that it works. I guess that was just opening a conversation to "how does it work?" Is there a flow chart or something I can look at? I have a key that I'd like to hide in my script, and this seems like a way to do it... I just don't know how it works. .
-
@dustbro depends what you mean by "hide" - read the "flow of control description" I wrote earlier...and it should be obvious.
RSA encryption/decryption allows you to hide one key, (the private key) and to use the public key(viewable) to decrypt the string
-
@ustk said in Blowfish - on a string:
@Lindon I've just added two methods:
https://github.com/christophhart/HISE/pull/331to use this way:
Did this ever get included in HISE? Its not working here...
-
@Lindon Christoph posted an example a few posts up.
-
@d-healey no, I'm looking for the simple blowfish stuff.... it doesnt seem to work anymore..
-
@Lindon Looks like that pull request hasn't been merged yet.