I've been struggling with a simple problem for hours now. I am working on a desktop application (a wallet) which needs a seed phrase to operate.
Naturally, the seed needs to be encrypted with a password and stored into a config file. I've found Jasypt which enables me to encrypt a String easily but apparently Jaspyt's PBEStringencryptor is supposed to be unsafe/deprecated. Since there's only one password, salting it wouldn't make any sense (would it?).
I've found many other methods on stackoverflock but I keep saying experts showing up and claiming how unsecure method x is.
To sum up my question: since I am only dealing with a single seed phrase, would using Jasypt's Stringencryptor be sufficient or should I use a different method?
The reason you are struggling to find a secure solution is probably that there is no secure solution that works in general.
Let me restate the problem that I think you are trying to solve:
Your application needs a "secret" to operate.
You cannot trust the user. (If you could, then you could in theory get the user to supply the secret each time they use the system.)
You cannot rely on operating system access control to keep the "secret" safe, because of one or more of the following:
the operating system is inadequate or buggy
you don't trust the operators / administrators
you can't be sure that the system hasn't been hacked, or
the system is not physically secured. (If someone can get undetected physical access to the hardware for long enough, they can circumvent OS security.)
Given the above assumptions, there is no secure solution. No matter what your application code does, it is possible for someone with sufficient OS-level privilege (assigned properly, or acquired nefariously) to watch what your code is doing and intercept the secret.
So what is the solution?
If you can assume that the platform is secure and the operators are trusted, there are technical ways to keep the secret secure ... from a non-privileged user.
There are mitigations for some kinds of security attacks. For example, you could use a Hardware Security Module to hold the secret so that it doesn't need to be stored in the file system.
Otherwise ... run the software on your (secure) infrastructure rather than the user's PC or your customer's servers.
seed needs to be encrypted with a password and stored into a config file..
Seems you are correct, the most reasonable way to encrypt the seed would be using some sort of password based encryption (PBE..).
Since there's only one password, salting it wouldn't make any sense (would it?).
you are storing the encrypted seed value itself, so in this case you may be ok with some application-wide static salt
PBEStringencryptor is supposed to be unsafe/deprecated.
would using Jasypt's Stringencryptor be sufficient
I am not aware of Jasyp being unsecure, it depends more on used parameters (any reference?). I usually use pure Java with standard PBKDF2 a few examples. However, Jasyp makes encryption done properly without deeper knowledge. The problem with cryptography is that it's easy to completely break security just using wrong set of parameters or using it wrong way. If you are just starting, using PBEStringencryptor may be safer option.
Someone mentioned using a hardware module (e. g. smartcard, TPM,.. ), could be safer, but less portable
I'am not an Java developer but as per described, what I would do in your case is to use asymmetric encryption of your seed with the desired password before storing it into a config file.
You could use Rivest Shamir Adleman (RSA), Elliptic Curve Cryptography (ECC) to name a few algorithms.
Cheers
Related
I'm trying to make sure that someone can't recompile my obfuscated application and then send malicious data to my server. I am doing an SSLed PHP_POST of my application's versionCode and packageName. These POSTED variables are all encrypted via asymmetrical encryption along with signature verification which will be changed per every version upgrade. I have thought of using checksums but those methods are not supported officially by Google and research has shown that they are not error-proof meaning that they could potentially disrupt legitimate users.
On top of all of this is a ban-on-site via IP/Mac Address/IMEI/Serial/Android_ID/etc when something is detected that is 100% not legit.
I understand that nothing could be 100% secured and the difference between a good security and a bad one is the time/money/effort it takes to break a security is valued higher than the item being protected by the security. With this in mind, are there any other methods I could use to protect my application or any ideas I should implement to add onto current security?
On a side-note, how easy is it to decompile/recompile an apk(jar) that's been obfuscated and would it be easier once its been done once? (aka, it doesn't matter how many times I change the key because the application is already compromised and the decompiler can simply look at the same spot where my last key was)
First thing, first, don't do your own crypto. If you are properly(!) doing SSL that is probably enough to protect data in transit against tampering, etc. What you need to do is authenticate your app somehow which is generally tricky, because you need to keep the credentials in the app. There are different ways around that, but currently the standard (and Google-endorsed way) is to use Google Play services to obtain a token and verify it in your server app. Details here: http://android-developers.blogspot.jp/2013/01/verifying-back-end-calls-from-android.html
This not perfect, but is probably better than most non-standard solutions you can come up with.
Decompiling is generally easy, and obfuscation doesn't change much, since it is trivial to find the places where you are calling system APIs (to get MAC addresses, hash, encrypt, etc.)
I have developed a system using Digital Signatures
The program is written in Java
Provider = "BC"
SIGNATURE_ALGORITHM = "SHA256withRSA"
Keys
The Client holds the public key
The Server holds the private key
License Generation
Clients request a license from the server
Server decides if they should get a licenses
Creates a signed object and sends it back to the client
I am wondering about easy ways to hack a system like this and what I can do to prevent it.
How can I prevent a user from decompiling my code and inserting their own code? (I am aware of proguard but hear that it can be worked around). I am also a little worried about a user creating a false licensing server and somehow modifying the source code to point to their server (because I will be releasing the licensing and server code to the public).
When dealing with cryptography and security - if it's of any real importance to you - never use anything home-made.
Always use a proper library.
The margin for bugs and mistakes in this field are huge. Your applications security deserves better.
How can I prevent a user from decompiling my code and inserting their own code?
The short answer is that you can't. You can make it harder (e.g. obfuscation) but you simply cannot prevent it. The fact that most computer games are cracked within days of release is evidence of this.
Turning to the rest of your question: the design looks fine. It's hard to prevent a fake licensing server, but maybe it's not going to be a likely attack anyway. The attacker could just remove the license check from the client instead.
As #Yuval points out, rolling your own crypto is a Bad Idea, but you seem to be doing it the right way by using BouncyCastle. Just make sure you always "sign what you mean", that is sign the license itself rather than, say, encrypting the license and signing the encrypted version.
BouncyCastle's lightweight API provides tools for signing arbitrary blobs of data; I'd recommend you use that rather than Java's cumbersome "provider" interface.
You should also take care to ensure the physical security of the private key. If that gets compromised then you're in real trouble. It may be worth thinking about a mechanism for revoking compromised licences and replacing them with new ones.
I need to encrypt an IP address, save it to file, and then be able to retrieve it later. I was wondering if anyone could suggest a good way to do this. Just the name of some encryption algorithms would be fine or links to resources.
Ive done my research and have come up with a few solutions. Just wanted to make sure there wasnt something I missed. If it helps at all, the application is written in java. We do use JNI for some native functions, but would prefer to stay away from JNI.
Thanks
EDIT:
Its a client/server model. The server will send the encrypted ip address to the client. The client will decrypt it, and then connect to that address.The data will be just a string. Its IPv4.
As other answers have already indicated, AES is your best bet for this problem. However, as is always the case with encryption, the real problem is not which algorithm to choose; it is how to keep your key a secret. If it is simply a string in your source code, it would take very little work for someone to figure that key out and use it to decrypt your file.
Assuming that you want arbitrary encryption on the client then you have a serious key management problem. It is pretty trivial to reverse engineer client code to obtain an embedded encryption key. And you need to consider what you'd do if that key is compromised and splattered all over the internet. Once it's embedded in your code then it's out of your hands (see CSS and deCSS for more fun reading on that subject).
So, a better solution is to have the server do the encryption and decryption and the client to just send up a bunch of bytes that it's stored locally.
Now, what's a good way of encrypting stuff on the server in an easy to maintain manner? I'm talking about key management; ease of use; strength of encryption; easy Ant/Maven targets/goals to manage the generation of said server side keys and so on. One framework that works really well for me is KeyCzar by Google. Simple API and external management is a piece of cake. Take a look.
I can answer to your straight question about encryption algorithm: AES
Java has classes for that!
But I still have my doubts about the robustness of you solution
I'd personally use AES.
Some more resources:
http://java.sun.com/developer/technicalArticles/Security/AES/AES_v1.html
Java 256-bit AES Password-Based Encryption
http://www.aescrypt.com/java_aes_crypt.html
I strongly recommend using the BouncyCastle library for Java. It's a lot cleaner than the built-in crypto stuff in Java and significantly easier to understand. Instead of mucking around with passing names of algorithms to methods and seeing if you actually get a cipher back you can just use new. Much easier.
You mentioned you have a few solutions, why not mention them.
Also, this is a very general question, are you looking for a symmetric algorithm or prefer public/private key, or something that uses both?
If you are looking at keeping the key on the server, since IP addresses are small (is this for IPv6, http://en.wikipedia.org/wiki/IPv6) then RSA would be a good choice, as you can then keep the public key on the server but no one can create a new key without the private key.
How will you be using the data? If you are going to decrypt all of them then just keep them in one file, zip it, then encrypt the entire file.
More details would help to narrow this down, as there are a large number of solutions.
But for libraries, in Java, I like BouncyCastle (http://bouncycastle.org/) as they give a large selection and works well if you need to exchange keys with .NET.
UPDATE:
Based on the latest update to the question the biggest concern is how to exchange the encryption key.
Since this is being sent to a client, your best bet may be to use something like RSA to help with this. The client would have a private key, and the server would have the public key of each client, so that if one is compromised the entire system isn't. Then, the server generates a symmetric key (AES is fine, I like IDEA), and encrypts that key. Then, you transmit both pieces to the client, the client then decrypts the symmetric key and then the IP address.
This idea was made popular by PGP.
You may want to use BouncyCastle, as I mentioned, so that if your client is written in .NET or Java you can still do the key exchange, since it has APIs for both platforms.
How you get the key to the server, from the client, or vice versa, depends on many factors, but that will be the weak link in this whole system, and so that part needs to be designed carefully.
As commented elsewhere, it is pointless. The information is available by other means so encrypting it via this channel is a compete waste of time. Netstat is yet another way the address can be detected.
Is there no way to route the TCP traffic through a proxy IP and "obfuscate" the IP that way?
I don't see the issue there unless the said provider of the proxy blocks the required ports according to projects needs. It's too bad Cloudflare wont allow anything except HTTP/S requests through their service unless you get on Enterprise, otherwise there is your solution in a blink.
I'm not even sure if this is possible, but is it feasible to secure, end-to-end runtime data on an uncontrolled client?
Specifically, is there any functionality in Java to take in encrypted data, process it and send it back out encrypted, all without exposing the data in plaintext to a curious 3rd party that has full access to the client?
Also, I know that code obfuscation is merely an annoyance to a dedicated individual with a decompiler, so I'm assuming for this scenario that the attack party has full source/operating knowledge.
I'm interested in answers either way. If there is no existing functionality, would it be feasible given Java's architecture? If Java can't do it, is there another language/platform that could? I'm fearing this may require special hardware.
To have a chance at doing what you are talking about, you need special hardware. You can't have a secure layer "on top" of an insecure layer. For example, if the attacker has full control over the hardware, he can always compromise the OS running on that host.
The special hardware is called a "Trusted Platform Module," or TPM. This supports remote attestation, which would allow you to verify that a client has not been tampered with. Some parts of the TPM are available on many computers (my Dell laptop, for example). In fact, I think all computers purchased by the US federal government are required to have a TPM. However, most consumers do not enable the TPM, and there's a lot of hostility toward TPM from privacy advocates. I'm also unsure how many machines with a TPM include the remote attestation capability.
Anyway, the bottom line is that you can't give someone a secret, and the key to the secret, and expect it to remain a secret. You have to retain control over the whole stack, top-to-bottom. Trusted Treacherous Computing allows you do do that, even if you don't legally own the hardware in question.
It is fundamentally not possible to be completely secure if the client is not locked down. At some point the bytes will exist in memory, and that memory can be read by hostile applications.
If your goal isn't to make it completely secure but merely inconvenient for the casually curious, then just be sure to not write the data to temporary files or anywhere else that would be trivial to examine.
Not only "can't be done", but "easy to compromise".
Look at 'aspect-oriented programming' and byte-compiler classes. This is normally used for things like inserting database transactions, performance logging, logging statements (so you can drop the calls from the source code and make it a lot cleaner), access control (so you separate the implementation and authorization), etc. There are a lot of extremely useful things you can do if you can quietly wrap one class with another.
But that also means it's trivial to wrap your classes to capture all of the unencrypted messages within your application, encryption keys, etc. I think I can get in even if you do everything in a single long procedure, although it might take a little more effort.
How can I retrieve the bytecode and make a hash to see if someone has manipulated my bytecode in-memory or on file?
EDIT:
Does signing the binaries protect the code from being modified and executed? As much as I want to protect my users from making sure they are running my software. I would also like to protect the program (server) from being used by a hacked client.
How do I detect from the server side if someone tampered with my client?
So you are trying to prevent some process with the same (or higher) privilege level than your application from manipulating your application?
That's a task that's doomed to fail. Because if you add your security checks, what would prevent the attacker from modifying your isSecure() method by replacing it with a simple return true;?
I think you need to clarify your requirements (at least I'm having trouble understanding what you are looking for).
In security-related areas, you always need to answer two questions, befor you can even start to tackle a problem:
What am I trying to protect?
What capabilities does an attacker have?
In your case, I believe you are trying to protect a Java client's class files from being modified. In that case the answer depends on what the (potential) attacker can do.
If the attacker actually has admin privileges on the machine the client is running on, then there is essentially nothing you can do. As saua above points out, if you cannot trust the the system you're running on, you're doomed.
If the attacker can only modify the class files before they reach the client maching, then signing your JAR files will let your clients detect the manipulation.
Maybe you want to sign your jar files instead?
What you want should be possible via Intrumentation, by adding custom Transformer. See http://java.sun.com/j2se/1.5.0/docs/api/java/lang/instrument/package-summary.html
Custom classloader also does the job, as it gets bytecode when class is defined.
How do i server side detect if someone tampered with my client?
You can not. On the internet nobody knows if you're a dog ;-)
Seriously: the only option server-side for making any assumptions about the client, is in the information sent back over the network. By encrypting the protocol and making it sufficiently hard to reverse-engineer, you can make it hard for an intruder to hack the client, but not impossible.
NGSCB (formerly known as Palladium) is designed to make this more secure, but this has its own set of issues.
You can create your own classloader and do the checking manually, or you can sign your code and let the java runtime do the job for you.
Signing the jars will protect the code from being modified. Signing involves creating a signature based on your private key. The public key is embedded in the jar with these signatures. Java will validate the signatures against your public key and refuse to load modified classes.
A hacked client will be a little harder to prevent. First an attacked would have to reverse engineer your protocol. You could take a step toward preventing this with a java obfuscator, but ultimately the attacker could just watch the wire and reverse engineer the protocol from the traffic. Even if you encrypt the client-server comms (this isn't exactly easy, considering using a protocol that already does it for you ... SSH or HTTPS) you will ultimately still be suceptible to a man-in-the-middle attack.
What exactly are you trying to protect against?
On the client, you can call getResourceAsStream with the path name to the class file in your jar.
That answers one part of your question ("How can i retrieve the bytecode"). Other answers cover the larger issues well.