This is a brainstorming question about what\'s possible in Java (or not). I want to know if it is possible to hide a secret within a class and prevent anymore from accessing
Some people question the relevance of the issue I am raising here. Although I am asking a general question in order to trigger an open conversation, there is a very concrete application to this class:
If I want to decrypt some messages, I need to load a private key data into a class. If I can't prevent other Java code from accessing it, then it is impossible to create a secure system. Of course, if I want to decrypt a message, I should rather do it in the class than giving away the secret, but still, the safe has to remain unbreakable.
First in security, unbreakable doesn't exist. There is tiny chance that by random I find your encription key by just writting random things on my keyboard. If your key is complex is would make you a really unlucky man, but this is possible.
Second point, using a public/private key value pair to protect communications between a client and a server is really common and it works perfectly if done right. But one must understand that this really protect the communication between the two computers. It doesn't protect the computer themselves. The whole thing is based on total trust the computer have from each-other.
Third point, when you have physical access to a computer you can do everything you want with it, in particular this include spying everything a program do. And all content of the computer. Content can be encrypted yes, but while being used, it is not encrypted anymore. This is a major problem of public/private key system : the private key are stored somewhere so you must be sure this place is safe.
This flow can be perfectly acceptable for you if you trust the computers involved in the communication. This is the case for exemple when you connect to your bank account.
Bank computers are trusted by the bank, and the provided access to external word is really restricted and controlled. They are "safe".
If you give away your own private key or access credential to the bank. You are compromized, but it is your responsability and problem. Because it is not in your interrest to be compromised, you'll do your best to avoid that. That nice, because you are the one with full control on your computer.
But let say you access to your bank from a public computer, or a computer from another person. Then a simple keylogger can just record the keys and mouse move you make when you enter your password.
Security on client side is based on trust you can have on the client. If you can trust him, this is perfect, it work. If you can't, then it is broken.
http://code.google.com/p/joe-e/ is an object-capability subset of java which is meant to allow decomposable security -- the ability for one part of a program to preserve its security properties even when other parts of the program are controlled, compromised, or manipulated by an attacker.
That said, valid JVMs are allowed to extend the semantics of the language with additional language facilities, such as the ability to attach a debugger at runtime. Code that can use Runtime
to invoke shell access could attach a debugger to many stock JVMs and work around private
access limitations even if the JVM is set up so that normal reflection respects field private
ness.
Joe-E disallows a lot of the reflective abuses of information hiding that could complicate this, and of course disallows unfiltered access to Runtime
.
There is another angle to this issue: Java delivered Permissions. In a context where the environment is controlled, one can assign a set of permissions to classes loaded with a secure class loader.
Java delivers 3 permissions objects related to the implementation of security:
PrivateCredentialPermission SecurityPermission AuthPermission
These can help improve and control access to functionalities when implementing a cryptography system. They are necessarily sufficient to make the system secure.
I think you can do this, but you end up pushing the security problem somewhere else. Is there any reason that "secret" cannot be encrypted using (for simplicity) your favourite symmetric key algorithm? The gimmeTheSecret() method would have to take an additional parameter being the secret key use to decrypt the secret.
Of course then the problem becomes that this secret key needs to be known and entered by a user or a machine storing it somewhere securely. You could use some kind of Hardware Security Module depending on how sensitive the data is and how much you want to spend!
You can obfuscate it from the .class file by using proguard or similar tools. You may also sign your JAR so other packages can't access it. Signing your JAR may help too.
This "security" is laughable.
Where does it run? On my desktop? I connect to the JVM with debugger and view all the secrets in clear text.
Or I place my code next to it and use reflection to dump the content.
Or I inject my own code modification via BCEL, and modify the constructor of Safe to dump the "secret" value to a file.
Or I simply replace the whole package with mine with the same name by placing it into bootstrap classloader.
Or I can even modify and compile java sources to get a modified JVM.
Or... my, one can list dozens of ways to extract a value from a runtime instance!
The real question in any security design is: who is a attacker? What is the threat model? Without answering this the topic is pointless.