protect Java Application by licence or key [closed] - java

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I want to make an desktop application that only runs on machines that have key or licence.
How this can be achieved?

This depends entirely on how secure you want to make it...
The problem with Java is that you can reverse compile it. So if someone wanted to, they could download your software, reverse compile it, and then remove whatever security you have put in place (and then redistribute it if they wanted).
This is only a problem if you plan on going mass market and selling it and piracy would actually be a problem though.
If you're not concerned about this, then you can either go for online, or offline checking.
The company I work with uses the online method; there are a few steps:
EDIT: I've since changed how this works, as the old way was a maintenance nightmare.
A license file
(this can contain whatever you want in reality, it just has to be unique per user. Most people normally go with general garb;
name
company
email
and then a key. i.e. the JDU8-AJS9-88DF-SASF-ASF9 kind of thing you often see.
The program generates a hash from the license file.
put all the data from the license file into a string
pass the string to a hashing function this page can show you how.
have the program check online (on your server). The data gets encoded in an HTML request (post/get/json/whatever you want) and submitted to your license verification page, which then verifies the data. Included in the data is a randomly generated string, which is used by the verification page to generate another password. This is then returned to the program, which has also used the random string to generate its own password. If the two match, the program starts up.
To generate the keys, just use the same hashing function, and then upload the hash to your server.
If you want it to be offline, you could include the hashes in the code I guess and check against them there.
I should point out, however, that I'm not a security expert by any means, I just develop for a company as a portion of a Ph.D. and this is just how I did it.
Edit: this image might be helpful:
Second Edit:
I have now included "offline verification" in the process. It's not really offline verification, it just uses the user as a proxy - they need to access the internet another way.
it works like this:
no internet connection found: supply the user with a 4 digit code
user goes to offline verification page (optimized for mobile use too)
user selects which software they use from the dropdown list
user enters their username (this field remembers entries)
user enters the code the program gave them and submits
webpage provides a 4 digit code, which they then enter into the program, and it starts.
program adds some special data to the license file meaning that this process won't need to be repeated for the next week/month/however long.
every time the program successfully verifies online, it also adds an offline access password to the license file, which means it's robust against temporary internet downtime, and will only stop working if the internet is down for more than a week/month/however long it's set up to work for.

You can track licencing of a machine with macIP on online . Even in windows you can write in registry there is no api but still you can do it. Find snippet bellow to read registry -
public static final String readRegistry(String location, String key){
try {
// Run reg query, then read output with StreamReader (internal class)
Process process = Runtime.getRuntime().exec("reg query " +
'"'+ location + "\" /v " + key);
StreamReader reader = new StreamReader(process.getInputStream());
reader.start();
process.waitFor();
reader.join();
String output = reader.getResult();
// Output has the following format:
// \n<Version information>\n\n<key>\t<registry type>\t<value>
if( ! output.contains("\t")){
return null;
}
// Parse out the value
String[] parsed = output.split("\t");
return parsed[parsed.length-1];
}
catch (Exception e) {
return null;
}
}
And in class level if you want to obfuscate use proGuard .

it depends how many customer you plan to have and the distribution mode also. You may use a licence server but this require an internet connection for the customer. You can also use USB dongles to manage licencing.
There are no perfect system you need to make a comproise between simplicity, effort and price.

Related

Where to store keysytore password?

Every example I see says to use a strong password but then they just slap it in the source code. That doens't seem quite right to me.
Is it possible to authenticate to the keystore as the current account so no passwords are involved?
If that's not possible, I have a requirement to not store passwords in source code, which is perfectly acceptable, but it seems like at some point a password needs to be a part of the equation, can someone point me to the most secure way to handle this?
I'm tempted to add the password as part of the build, but then I have a plaintext password on the build server, which almost seems roughly the same to me.
First, the general rule: If you ship software which, all by itself, is able to unlock some 'secure store' (so, without involvment of a server under your control or some other hardware under your control)... it is impossible to hide this information from the owner of the computer it runs on.
Example: Webbrowsers tend to have a feature to offer storing website passwords. These passwords are stored in files, and with the right tools you can open these files and see the passwords plain as day. There is no way to fix that with more software or more cryptographic algorithms. The only solution is to make the software incapable of unlocking said datastore, for example by requiring that the user enter a master password every time they wanna look into it, or putting some sort of secure enclave into the hardware and having THAT take care of the crypto. Java generally does not have the right libraries to interact with such hardware (apple's T2 is a very advanced take on this concept; TPM chips are a budget option).
So, once you're okay with that, you can still go: Okay, well, I do NOT want the authentication keys in the source code; in order to build a production distributable from the sources, the builder will have to supply it. To accomplish that:
(Assuming maven style project structure):
Make file src/main/resources/com/yourcompany/yourproject/keys/KeyFile.txt and then update your .gitignore file to ignore that, by putting /src/main/resources/com/yourcompany/yourproject/keys/KeyFile.txt in there.
Write the key in this file. Share this file with some secure means with all members of the project who should have it.
Write code: In src/main/java/com/yourcompany/yourproject/keys/ProjectKey.java have a static method to retrieve the key. It would look something like this:
public final class ProjectKey {
/* prevent instantiation */ private ProjectKey(){}
private static final String PROJECT_KEY = loadKey();
public static String getKey () {
if (PROJECT_KEY != null) return PROJECT_KEY;
throw new IllegalStateException(
"Key file not present; find somebody with the file and place in: " +
"src/main/resources/java/com/yourcompany/yourproject/keys/KeyFile.txt");
}
private static String loadKey() {
InputStream in = ProjectKey.class.getResourceAsStream("KeyFile.txt");
try {
return in == null ? null : new Scanner(in, "UTF-8").next();
} finally {
if (in != null) in.close();
}
}
}
Make a dir in your project called 'keys' or whatnot. In your .gitignore file at the root, put the line /keys in order to ensure these do not go into source control.
You'd have to mess around with some build tool plugins if you want builds to fail if the file is missing. Also, you'd have to update the scanner's delimiter if the 'key' contains any whitespace (I'm using scanner here as the fastest way to turn an inputstream into a complete string; if you have for example Guava, it has better calls to do that, and you should use those).

How to allow specific characters with OWASP HTML Sanitizer?

I am using the OWASP Html Sanitizer to prevent XSS attacks on my web app. For many fields that should be plain text the Sanitizer is doing more than I expect.
For example:
HtmlPolicyBuilder htmlPolicyBuilder = new HtmlPolicyBuilder();
stripAllTagsPolicy = htmlPolicyBuilder.toFactory();
stripAllTagsPolicy.sanitize('a+b'); // return a+b
stripAllTagsPolicy.sanitize('foo#example.com'); // return foo#example.com
When I have fields such as email address that have a + in it such as foo+bar#gmail.com I end up with the wrong data in the the database. So two questions:
Are characters such as + - # dangerous on their own do they really need to be encoded?
How do I configure the OWASP html sanitizer to allow specific characters such as + - #?
Question 2 is the more important one for me to get an answer to.
You may want to use ESAPI API to filter specific characters. Although if you like to allow specific HTML element or attribute you can use following allowElements and allowAttributes.
// Define the policy.
Function<HtmlStreamEventReceiver, HtmlSanitizer.Policy> policy
= new HtmlPolicyBuilder()
.allowElements("a", "p")
.allowAttributes("href").onElements("a")
.toFactory();
// Sanitize your output.
HtmlSanitizer.sanitize(myHtml, policy.apply(myHtmlStreamRenderer));
I know I am answering question after 7 years, but maybe it will be useful for someone.
So, basically I agree with you guys, we should not allow specific character for security reasons (you covered this topic, thanks).
However I was working on legacy internal project which requried escaping html characters but "#" for reason I cannot tell (but it does not matter). My workaround for this was simple:
private static final PolicyFactory PLAIN_TEXT_SANITIZER_POLICY = new HtmlPolicyBuilder().toFactory();
public static String toString(Object stringValue) {
if (stringValue != null && stringValue.getClass() == String.class) {
return HTMLSanitizerUtils.PLAIN_TEXT_SANITIZER_POLICY.sanitize((String) stringValue).replace("#", "#");
} else {
return null;
}
}
I know it is not clean, creates additional String, but we badly need this.
So, if you need to allow specific characters you can use this workaround. But if you need to do this your application is probably incorrectly designed.
The danger in XSS is that one user may insert html code in his input data that you later inserts in a web page that is sent to another user.
There are in principle two strategies you can follow if you want to protect against this. You can either remove all dangerous characters from user input when they enter your system or you can html-encode the dangerous characters when you later on write them back to the browser.
Example of the first strategy:
User enter data (with html code)
Server remove all dangerous characters
Modified data is stored in database
Some time later, server reads modified data from database
Server inserts modified data in a web page to another user
Example of second strategy:
User enter data (with html code)
Unmodified data, with dangerous characters, is stored in database
Some time later, server reads unmodified data from database
Server html-encodes dangerous data and insert them into a web page to another user
The first strategy is simpler, since you usually reads data less often that you use them. However, it is also more difficult because it potentially destroys the data. It is particulary difficult if you needs the data for something other than sending them back to the browser later on (like using an email address to actually send an email). It makes it more difficult to i.e. make a search in the database, include data in an pdf report, insert data in an email and so on.
The other strategy has the advantage of not destroying the input data, so you have a greater freedom in how you want to use the data later on. However, it may be more difficult to actually check that you html-encode all user submitted data that is sent to the browser. A solution to your particular problem would be to html-encode the email address when (or if) you ever put that email address on a web page.
The XSS problem is an example of a more general problem that arise when you mix user submitted data and control code. SQL injection is another example of the same problem. The problem is that the user submitted data is interpreted as instructions and not data. A third, less well known example is if you mix user submitted data in an email. The user submitted data may contain strings that the email server interprets as instructions. The "dangerous character" in this scenario is a line break followed by "From:".
It would be impossible to validate all input data against all possible control characters or sequences of characters that may in some way be interpreted as instructions in some potential application in the future. The only permanent solution to this is to actually sanitize all data that is potentially unsafe when you actually use that data.
To be honest you should really be doing a whitelist against all user supplied input. If it's an email address, just use the OWASP ESAPI or something to validate the input against their Validator and email regular expressions.
If the input passes the whitelist, you should go ahead and store it in the DB. When displaying the text back to a user, you should always HTML encode it.
Your blacklist approach is not recommended by OWASP and could be bypassed by someone who is committed to attacking your users.
You should decode after sanitising your input:
System.out.println(StringEscapeUtils.unescapeHtml("<br />foo'example.com"));

Anti-hack solution for a secret key in Android app?

I need to store a private string key inside of the app. Its value will never change and is set manually in code. I cannot obviously just store it as a String as reverse-engineering method would reveal it, even with obfuscation applied.
How do you suggest I protect this private key?
I though of saving it into a database, but a database can be pulled out of the phone as well.
PS. this key is a special parameter so an important method and it's crucial it stays unknown to anyone! It's not a decrypting key. This string will be used as a parameter to encryption method (md5 or similar) and then a result will be sent to our Internet service.
EDIT
Sorry, for making it so complicated. I thought I could get an answer with as few info as possible.
This app will allow users to send some text to an Internet service which then posts that text to a web site. We need to make sure that the text is sent via Android phone as any web robot script can mimic android phone and post a spam. As captcha-like methods are not welcome on mobile phones, there will be a secret key which will be put through md5 (with some other things) to generate a hash code. This hash will be sent to an Internet service. The Internet service will use the same key to get a md5 result and then compare it to see if the sender is a mobile phone or some robot.
This is really the max I am allowed to say. I hope it is enough.
I'd suggest that you rethink your security architecture. Anything shipped with the app is discoverable. (For instance, Android's license validation library is designed so that a public key is shipped with the app.)
One possibility is for the app to retrieve the key from a server (over a secure socket or https connection). This would obviously require that the app submit to the server some sort of identification/validation (probably based on user input).
If you're using the key for encryption, then take another look at how public key encryption is supposed to work. Your app should have the public key; the internet service can then decrypt with the matching private key.
If you can settle with #Adam's comment, there is at least one solution I know of for persisting a String value on the phone in a... well... persistent manner, meaning that the value will survive a uninstall/re-install of your app (a factory reset would remove it though), yet remain "hidden" for the user (i.e. stored in system private storage, not on the SD-Card).
You can use the system settings content provider to store the value like so:
final String myKey = "verySecretKey";
final String myValue = "verySecretValue";
final boolean isSuccess = System.putString(getContentResolver(), myKey, myValue);
And to retrieve it you can do:
myValue = System.getString(getContentResolver(), myKey);
And yes, on a rooted phone a handy user might get hold of the persisted value, but in that case nothing is holy anymore and #Adam's comment will get valid: You shouldn't store the data on the device.

Send string from java (or other platform) to application

I want to send a barcode, read with my cellphone, to my computer. My computer has a simple server running, which listens to barcodes. When a barcode arrives, the server app should be able to input the value of the received barcode into the active application (I don't really care which application is going to get the input, the user should be able to select gedit, a terminal window or the browser if they choose to).
My language at the moment is Java on GNU/Linux (Ubuntu), so I know about the Robot class. But the Robot class emulates a keyboard, which means: when you send VK_1 on a US keyboard layout, the output is '1' indeed, but when you send VK_1 on another layout (like belgian, which I use), which requires shift for the '1' key, the output is '&' (this is the character on the '1' key, when you don't hold shift).
I also found xsendkeys, but this application too requires you to specify whether you need to hold shift. So it will be able to send an 'a' but for an 'A' (thus capital) you need to specify you want to hold shift with your 'a'.
Isn't there an easy way to do this, for GNU/Linux and Windows, just using strings. I want to be able to send "12a68dd" to the active application. And I also would like to be able to send UTF-8 characters to the active application.
I have been looking for a solution, but most require the breakdown in multiple keystrokes, which are often dependent on the keyboard layout.
Seems like you want to be able to send an arbitrary keyboard sequence to any possible application. With that I cannot help you (you should look for "Java UI testing automation" to find any suitable tools), but if the application you are sending the string to listens for it on its standard input, I would go for:
// Example: send your string to "cat" (or "type" on Windows), which simply prints it.
Process spawned = ProcessBuilder.command("cat" /*No arguments*/).start();
spawned.getOutputStream().write(yourString.getBytes("UTF-8"));
Simple stdin/stdout redirection, in other words.
If I understand you correctly, you wish to send a series of characters into another application (the destination). This destination could be any application, and you may not have access to its source code.
The answer is simply no.
Key strokes differ to characters (which I gather you have probably worked out) and Robot was intended just to invoke key strokes. The resulting output of those key strokes is generally different due to the fact most keyboards used do not follow the ISO standard for keyboards.
There are often other ways of accomplishing the same affect though, through APIs, file IO, etc.
I may not have grasped your question completely, but you want to separate applications, both written in Java, to exchange information? I'd recommend you read up on RMI, which exists för that very purpose.
Just wanted to let you know my sollution:
Call xvkbd -text from java and give the text to be writen as argument. If the text contains spaces, I call xvkbd multiple times with a xvkbd -text \[space] call within.
My current way is pretty easy to 'port' to windows, so that wont be too hard to get running with a SendKeys VB application.
Thanks all for your help!

Multiple questions in Java (Validating URLs, adding applications to startup, etc.)

I have an application to build in Java, and I've got some questions to put.
Is there some way to know if one URL of a webpage is real? The user enters the URL and I have to test if it's real, or not.
How can I konw if one webpage has changes since one date, or what is the date of the last update?
In java how can I put an application running on pc boot, the application must run since the user turns on the computer.
I'm not sure what kind of application you want to build. I'll assume it's a desktop application. In order to check if a URL exists, you should make a HTTP HEAD Request, and parse the results. HEAD can be used to check if the page has been modified. In order for an application to start when the PC boots, you have to add a registry entry under Windows; this process is explained here
To check whether a url is valid you could try using a regular expression (regex for urls).
To know if a webpage has changed you can take a look at the http headers (reading http headers in java).
You can't make the program startup automatically on boot, the user must do that. However, you can write code to help the user set the program as startup app; this however depends on the operating system.
I'm not sure what you mean by "real". If you mean "valid", then you can just construct a java.net.URL from a String and catch the resulting MalformedURLException if it's not valid. If you mean that there's actually something there, you could issue an HTTP HEAD request like Geo says, or you could just retrieve the content. HTTPUnit is particularly handy for retrieving web content.
HTTP headers may indicate when the content has changed, as nan suggested above. If you don't want to count on that you can just retrieve the page and store it, or even better, store a hash of the page content. See DigestOutputStream for generating a hash. On a subsequent check for changes you would simply compare the new hash with the the one you stored last time.
Nan is right about start on boot. What OS are you targeting?

Categories