Copy link to clipboard
Copied
I wanted to ask how safe is to keep data inside localStorage.setItem(Key, Value).
If I want to create extension for Illustrator and want to store license key for that extension inside localStorage. License key in localStorage will be encrypted of course.
Is this safe to do such thing?
It depends on what "safe" means. If you're including API keys to paid services then no, storing them in any local file or localStorage is not good practice and is very insecure even if encrypted, but if by "safe" you're asking if a malicious actor could harm the user in any way if they could access and decrypt your license key the short answer is no. At most, all that would happen is a lazily cracked version of your extension might be available online -- but if I wanted to do that, I'd just stri
...Copy link to clipboard
Copied
If someone enables debug mode, they will then be able to modify the script to do whatever they want, including access to all localStorage values.
Copy link to clipboard
Copied
Yes but data will be encrypted.
Alternative is to store in some file but there also will be the case that data are accessible, but if they are encrypted we are on the same.
What is difference?
Copy link to clipboard
Copied
It depends on what "safe" means. If you're including API keys to paid services then no, storing them in any local file or localStorage is not good practice and is very insecure even if encrypted, but if by "safe" you're asking if a malicious actor could harm the user in any way if they could access and decrypt your license key the short answer is no. At most, all that would happen is a lazily cracked version of your extension might be available online -- but if I wanted to do that, I'd just strip out the code in your extension that checks for licensing to begin with then resign and redistribute it as a ZXP to skip the licensing part entirely and unfortunately, no amount of security measures would prevent that due to how relaxed CEP is with self-signed certificates.
If I were a malicious actor looking to redistribute your extension with extra code that modifies the user filesystem then your manner of licensing is completely irrelevant regardless of the depth of your security measures from code visibility alone. All it would take is someone who knows what they're doing committing to the time and effort it would take to just erase whatever lines of code you're using to authenticate a license or make requests to bypass this issue, and though it's not an inevitably that's going to happen, taking too many steps trying to prevent it will end up being a sunken cost in my opinion. Either they have the skill (and you can't stop them anyway) or they don't, and either something like this will happen or it won't. Have decent SEO to appear above any redistribution on search engine results and that catches 99% of potential users finding that redistributed version to begin with. As someone who's made a variety of CEP extensions some of which for large clients with a combined userbase of over 20K licenses, it's never happened to mine, at least that I know of.
There are plenty of online resources about "API key provisioning" (exact phrase for ease of googling for you) that address and discuss this along with best practices for security, but it becomes a manner of scale and if I'm honest, I don't think any CEP extension merits the college education level of knowledge needed for perfect security. The Goldilocks Zone between simple and secure is something like this:
In my opinion, any obstacle is enough to discourage 90%. SHA-256 with some hidden salt could be plenty to store your license in localStorage since most likely will never get beyond that point. If it's your first extension or your first serious extension, it's hard not to have ideas like this -- "I want to prevent people from stealing my work", "I don't want to miss out on any paying customers" -- and so on, but the market is small and niche. Your target market are professional artists who are used to paying for SaaS solutions and other means of improving their production. Focusing too much on things like this can just be a distraction from a worried and anxious inner mind and in reality, won't make much meaningful difference unless your extension is successful enough to sell several hundreds or thousands of licenses to begin with. If the extension isn't 100% done in every other aspect, then there's more pressing work to attend to.
Copy link to clipboard
Copied
@Inventsable Thank you for such detailed answer. I will select this as corect answer as I want to award for your time and for useful informations.
But I have one more question. It will be gumroad for license keys and unfortonelly store licence key locally.
Now, if for example I choose to store inside some file, license key and machine Id.
Lets say that this machine Id will protect against reuse this file on multiple computers, by simple coping file.
But still it will be possible to reuse this file in same computer, in the way that someone could just copy that file, do deactivation (which will be offer in extensions ui) and then just paste back that file.
What is the best protection against this?
Copy link to clipboard
Copied
If I were doing it, I'd use fs.stat or fs.statsync to know when it was last modified:
// Use fs and path from node
const fs = require("fs");
const path = require("path");
// Resolve the filepath to absolute
const filePath = path.resolve("./somePathHere.json");
// Get the millisecond value of when the file was last modified:
const dateModified = fs.statSync(filePath).mtime.getTime();
If you're the one writing the file, write a key/value to localstorage with Date.now() at the same time your license file was written or whenever your panel is modifying it, then when the panel mounts in future compare if your localstorage value is equal to the license file stat getTime above within a small margin like ~20 ms (or just capture the getTime of the file after writing it for exact comparison). If it is equal you'll know that it was last modified by you, but if it isn't, the user (or something else) must have modified it.
Copy link to clipboard
Copied
@Inventsable Thank you
Creation Time, Modification Time, Access Time....this is all possible to change with js or through terminal or some other app, right?
So is this then some protection?
He do not need to do any modification of file just need to do in this order: copy license file, deactivate, paste license file. And still will have functional extension on current computer and still one more actication as he just deactivate on that computer. And can do like this infinitely.
With that copy paste Creation Time of license file will change, but he can back to original value.
If I add that info about creation time in localstorage this will not protect from this above, right?
Please let me know if I did not understand you well?
Copy link to clipboard
Copied
Creation Time, Modification Time, Access Time....this is all possible to change with js or through terminal or some other app, right?
No, but even if they were, the user would need to be smart enough to open the panel with CEF Client to display localstorage values anyway. At the point they know how to do that, this is mostly a moot point, because like I originally posted there's nothing stopping someone from stripping out Javascript in your panel then resigning or using it as is, or even running arbitrary JS in the CEF console.
He do not need to do any modification of file just need to do in this order: copy license file, deactivate, paste license file. And still will have functional extension on current computer and still one more actication as he just deactivate on that computer. And can do like this infinitely.
With that copy paste Creation Time of license file will change, but he can back to original value.
If I add that info about creation time in localstorage this will not protect from this above, right?
This is why I recommended and gave you date modified, not date created. Modified is changed whenever the file path changes or the content inside changes. Also you're using seating, so just poll the license and seats silently every 10 minutes and no one alive will have the patience to deactivate licenses manually like you've described 6 times per hour whenever they use the app.
I think you're massively over-thinking this. This is such an obscure use-case of how to "hack" and sure, if you can think of a hole you may as well try to fill it, but I cannot stress enough to you that there are much easier ways to bypass security and you are not going to be able to stop that.
Copy link to clipboard
Copied
Why would they need to display localstorage values they can just read that data about time from license file itself.
I think that Modification Time is changed only when content of file is changed, not path and this behave is on win/mac the same. So only Creation Time of license file will change with copy/paste you can test that on some file.
But it does not matter, it could be that you though that file is present all the time (from time of extension installation), but it is created when it is activated and deleted after deactivation, maybe I did not explain that part.
Also I did not explain how gumroad works, it has verification of license key where you can choose to increase or not increase number of uses on each verification. So I set to increase only on activation (when user input lic. key for first time). That number of uses I am using to check agains max number of activation.
So I can check how many seats are busy only on activation so once he has license file he can use that without restriction.
"stripping out Javascript in your panel then resigning or using it as is, or even running arbitrary JS in the CEF console. "
"but I cannot stress enough to you that there are much easier ways to bypass security and you are not going to be able to stop that. "
For this part I do not know, obviously you have more expirence with security of cep extensions and not have reasons to not belive you.
I mean it is easy to copy and resign that part is obvious but how to access parts of js file which run functions from jsx (on both were applyied obfuscator) I did not have time to check yet. I am sure that there are workaround.
I am very currious if you can not write here you are free to send me private message???
Sorry if I bored you, this was very interesting communication for me so far!
Copy link to clipboard
Copied
You didn't specify that you were using Gumroad earlier, no.
I mean it is easy to copy and resign that part is obvious but how to access parts of js file which run functions from jsx (on both were applyied obfuscator) I did not have time to check yet. I am sure that there are workaround.
Any obfuscation can be easily reversed (if you know what to look for or what libraries to use) and even JSXBIN has public cracks on Github allowing converting from JSXBIN back to human readable JSX so it's not secure either. This is the only point I'm trying to reiterate to you -- at some point this becomes a sunken cost. You're the one who decides when that point is, but genuinely I don't think it's something you have to worry or care about unless you know for a fact your extension is going to sell several hundreds if not thousands of licenses. The scope of CEP and the market existing inside it is just too small for nuanced license concerns, you're not pushing patches of CrowdStrike to millions of users here.
If you only sell 50 licenses with this product (which happens to every one, most of my own tools have not been as successful as I wanted them to be) then all this time, care, attention and worrying is for nothing but practice I guess.
But if someone knows how to use fs.utimesSync, then they likely already know how to reverse obfuscation or strip out your validation JS in the first place. All this "what if this" and "what if that" is just hyper-focusing on a very small and manual bypass that, in the big picture, is not very likely or even efficient in the first place. Say a user does deactivate then copy then reactivate, what does this produce? A single extra use per session of your tool requiring manual work every time in a way that can't be easily shared between several people? That's an extremely small problem to have.
Get ready! An upgraded Adobe Community experience is coming in January.
Learn more