I have a rather large signed FatJar (~150Mb) and I just tried running it and it turns out that it runs much slower than its unsigned equivalent. I'm using jdk1.8.0_131 (on Mac).
I'm curious as to whether this is normal or whether there are some tips and tricks that I can use to speed things up.
I noticed that the signing process actually signs each individual entry in the jar as opposed to signing the Jar as a whole. So I imagine that the slowness is due to the class loader having to verify the signature of every class it tries to load.
So my question is, is there a way to change this behavior? Can I have the class loader somehow just verify that the JAR is properly signed to begin with and then behave the same as if it were an unsigned JAR?
If not, I will implement my own signing/verification mechanism. Just want to make sure I'm not missing anything before I do that.
It might be a java bug.
See here
Actually sign verification should not has a significant impact on overall performance.
So try to update JDK version.
I have had a lot of slowness in calling a REST API, requests took up to 4 seconds instead of less than a second.
The reason was that
creating a client takes a lot of time.
Basically the solution was to make the client creation a singleton, then it was fast again.
Related
I'm deploying a JavaFX application and am not quite sure what does and doesn't need to be signed. Here are my thoughts:
- Installation file:
This obviously needs to be signed.
- The EXE that launches the application:
I believe this needs to be signed, although it feels a little bit funny because it isn't my code.
- My JAR files: I believe that these also need to be signed, although I'm not sure if anything terrible happens if I don't.
- Library JARs that I've grabbed off the internet: I don't feel like I should sign these. Is there any reason to?
- Java runtime:
I'm guessing there's no reason to sign this, and I'd probably violate some agreement if I do.
- JNLP file:
Not using this, no reason to touch this.
Have I looked at this properly? Am I signing the correct files?
A friend of mine has a saying " it's not what you did... it's what you can prove in court. "
With this respect, I advise you to look at this problem from a legal point of view and assume the worst possible context it can apply in; i.e. you becoming legally accountable after someone tampers with your software.
Digital signatures are designed especially for these types of problems.
With this respect, let's split your answer into 2 different classification parts:
the software you're releasing - includes your jars, jnlp, bundled .exes, etc.
all of these must be singed in order to ensure that you can't be affected by any unauthorized tempering with your own code. It doesn't matter whether or not you've released that jnlp. If someone generates an invasive one and it's traced back to you, your failure to authenticate your own released version of that jnlp will not be ok.
the software released by other people. - includes everything which you're using in order to get your system to work. (jre, libs)
when using something like this, it's a good idea to make sure you're using a genuine copy of whatever your lib manufacturer has released. Use their checksums/signatures/etc. to validate and verify their software integrity upon demand. You have to read their liability and disclaimer statements and in the event they fail to provide one themselves.
In general it is a good idea to place as little trust as possible when it comes to software sources other than yourself. Unfortunately, there are many compromised or malicious libs out there which are in fact security risks.
it is always a good idea to make sure you're releasing a downloaded lib which is certified by an external issuer and as such cannot be held responsible for any malicious code detected within.
To answer your question... it really depends on the client endpoint and the likelyhood of you getting sued for providing them with a security risk (i advise you to always expect this to be 100%). If you're liable for damages... you need to proceed accordingly.
In short... the best possible answer to this quesiton is to do whatever is possible to cover yourself in the event the worst happens.
Does your application need elevated privileges? If the installer is targeting Windows you wish to install the application to Program Files, then your installer will need to be signed. Without it, Windows will give a yellow banner during privilege escalation request.
So - sign your installer.
The exe that launches the application should ideally be signed as well. But for a java application, this is perhaps a mute point. Signing the exe is easy enough, that I'd just do it anyways.
Sign launcher exe - Optional, but I'd do it
Jar files. This is an interesting one and depends on what you goal is. Ie, the OS and the end user are probably not going to be aware of the signed or unsigned nature of your Jar. Therefore you will probably have to verify the integrity of the jar yourself. See https://docs.oracle.com/javase/tutorial/deployment/jar/signindex.html
Perhaps the launcher application can perform the integrity checks before the launch step ?
Library jars, Similar to the case above, if you want to make sure that no one has dropped in a diff jar into your application or some such use case, you will need to verify this yourself.
Java Runtime If you shipping this, is this not already signed by Oracle or your JVM vendor ?
I am using Eclipse WTP for a project. It requires few libraries to be used. Few are small in size and few are larger. My question is, what happens when we use external jars in servlets ? If I am importing a heavy-weight library in a Servlet, does it impacts webpage load time ?
Or Java just compiles my program including libraries to give results. I understand heavy-weight jar will take time to load once even on my local machine, but I can manage them to be initiated only once (by creating a separate class and initiate static variables and use them from other classes). But seems like, this can't be done in Servlets and every time a page is loaded, servlet has to load all those heavy jars.
Is it good to use Guava and Solrj in Servlets ? Do they slow down (asking because I feel Solrj is slowing down webpage load time) ?
Including a jar in-and-of itself does not slow down servlet run time. However, using a particular tool/class/functionality in a jar may slow down the servlet, depending on what you are trying to do.
I recommend using a profiler to analyze your code and actually determine what it causing the slowdown. Here's a quote from Martin Fowler's Refactoring:
I had speculated with various members of the team (Kent and Martin deny participating in the speculation) on what was likely wrong with code we knew very well. We had even sketched some designs for improvements without first measuring what was going on.
We were completely wrong. Aside from having a really interesting conversation, we were doing no good at all.
The lesson is: Even if you know exactly what is going on in your system, measure performance, don't speculate. You'll learn something, and nine times out of ten, it won't be that you were right!
I have a dilemma. Basically, I've given a group of people I'm friends with a program that utilizes source code that I don't want anyone outside the group knowing of. We all know Java is absolutely horrible at doing any level of obfuscation, as most obfuscation tools only rename objects, scramble code, etc. I've used such tools, but to be honest I'd like to go as far as possible with the security of the program.
Since the application requires a username, password, and other identifiers to log in to the server it uses, I was beginning to wonder if a unique AES key could be generated for the user to secure the JAR.
Basically, upon running a launcher of sorts to log in, the launcher app may request an AES key from the server, and use it to decrypt a secured JAR it's downloaded from the server already. The key would be completely unique to each user, which would mean the server would have to encrypt the JAR differently for each user.
Now, I know how crazy this sounds. But since this is such a low-level thing, I need to know if there is a way you can somehow both decrypt and run a JAR from any type of stream. Or, if that isn't possible, would it be reasonable to decrypt the file, run it, then re-encrypt it?
Of course you can decrypt and run Java bytecode on the fly - bytecode manipulation libraries such as ASM even go as far as creating new classes dynamically.
But, quite honestly, if something actually runs on a computer then its code is definitely going to be available to anyone with the knowledge. Java, especially, is even more convenient since it allows far better access to the bytecode of a class that is loaded by the JVM than any natively compiled language.
You could theoretically take your obfuscation a bit further by using JNA/JNI and a native shared library or two. But, in the hands of a determined attacker no measure will protect your code completely - it would just take more time for them to figure out how your algorithms work. And if you are concerned about piracy, well, we are in the era of virtualization; you can actually clone whole computer systems from top to bottom with a couple of key presses - you figure out the rest...
The only potentially viable solution would be to offer your software as a service, with all the issues entailed by that approach - and you would still not have absolute security.
If you are that concerned about protecting your intellectual property, then get a lawyer and consider publishing your algorithms in some form - obscurity will only go so far. It will not stop someone from doing black-box analysis on your system and quite often just knowing that something is possible is enough.
Please stop trying to find technical solutions to a problem that is so obviously not of a technical nature...
My answer would be to keep the server information outside of the jar entirely. Use a parameter or configuration file to point to where to get that information. Then the jar file has no secrets in it. Only the server where the code runs has that information. You can then do things like make the configuration file readable only by the user that can run the code in the jar.
I am curious about what automatic methods may be used to determine if a Java app running on a Windows or PC is malware. (I don't really even know what exploits are available to such an app. Is there someplace I can learn about the risks?) If I have the source code, are there specific packages or classes that could be used more harmfully than others? Perhaps they could suggest malware?
Update: Thanks for the replies. I was interested in knowing if this would be possible, and it basically sounds totally infeasible. Good to know.
If it's not even possible to automatically determine whether a program terminates, I don't think you'll get much leverage in automatically determining whether an app does "naughty stuff".
Part of the problem of course is defining what constitutes malware, but the majority is simply that deducing proofs about the behaviour of other programs is surprisingly difficult/impossible. You may have some luck spotting particular patterns, but on the whole you can't be confident (and I suspect it's provably impossible) that you've caught all possible attack vectors.
And in the general sphere, catching 95% of vectors isn't really worthwhile when the attackers simply concentrate on the remaining 5%.
Well, there's always the fundamental philosophical question: what is a malware? It's code that was intended to do damage, or at least code that doesn't do what it claims to. How do you plan to judge intent based on libraries it uses?
Having said that, if you at least roughly know what the program is supposed to do, you can indeed find suspicious packages, things the program wouldn't normally need to access. Like network connections when the program is meant to run as a desktop app. But then the network connection could just be part of an autoupdate feature. (Is autoupdate itself a malware? Sometimes it feels like it is.)
Another indicator is if a program that ostensibly doesn't need any special privileges, refuses to run in a sandbox. And the biggest threat is if it tries to load a native library when it shouldn't need one.
But all these only make sense if you know what the code is supposed to do. An antivirus package might use very similar techniques to viruses, the only difference is what's on the label.
Here is a general outline for how you can bound the possible actions your java application can take. Basically you are testing to see if the java application is 'inert' (can't take harmful actions) and thus it probably not mallware.
This won't necessarily tell you mallware or not, as others have pointed out. The app could still do annoying things like pop-up windows. Perhaps the best indication, is to see if the application is digitally signed by an author you trust; if not -- be afraid.
You can disassemble the class files to determine which Java APIs the application uses; you are looking for points where the java app uses the OS. Since java uses a virtual machine, there are well defined points where a java application could take potentially harmful actions -- these are the 'gateways' to various OS calls (for example opening a socket or reading a file).
Its difficult to enumerate all the APIs, different functions which execute the same OS action should require the same Permission. But java's docs don't provide an exhaustive list.
Does the java app use any native libraries -- if so its a big red flag.
The JVM does not offer the ability to run arbitrary code, or use native system APIs; in particular it does not offer the ability to modify the registry (a typical action of PC mallware). The only way a java application can do this is via native libraries. Typically there is no need for a normal application written in java to use native code (unless it needs to use devices).
Check for System.loadLibrary() or System.load() or Runtime.loadLibrary() or Runtime.load(). This is how the VM loads native libraries.
Does it use the network or file system?
Look for use of java.io, java.net.
Does it make system calls (via Runtime.exec())
You can check for the use of java.lang.Runtime.exec() or ProcessBuilder.exec().
Does it try to control the keyboard / mouse?
You could also run the application in a restricted policy JVM (the instructions/tools for doing this are not as simple as they should be) and see what fails (see Oracle's security tutorial) -- note that disassembly is the only way to be sure, just because the app doesn't do anything harmful once, doesn't mean it won't in the future.
This definitely is not easy, and I was surprised to find how many places one needs to look at (for example several java functions load native libraries, not just one).
I know about class/jar executable format. But jar/class can not ensure source security, because java source code(.java) can retrieve from it. I am looking for such a format where source are secure/un-retrievable.
You can't make code secure from reverse engineering. If one has permission to execute it, then it can be examined where it can be disassembled, reverse compiled, or matched against known assemblies.
If your computer can run it, then you can reverse-engineer it. There is no way to avoid this. The best you can hope for is to stop casual cracking by (for example) passing your source through an obfuscater before compiling.
IBM did this with their type-4 JDBC drivers and it makes it hellishly difficult to understand what's going on (right up until the point you write a program that can de-obfuscate it although you still need to add information back in like function and variable names, no easy task).
Security through obscurity never works against a determined foe. This is the same as with physical security. You can put as much security in your house as you like, and that will prevent casual break-ins, but it will not stop a determined burglar.
I would rather concentrate on doing what I do best, providing top-notch quality software. Most attempts to secure code (beyond simple obfuscation) almost always disadvantages your real customers more than your attackers. Is your code really so precious that you want to risk that?