Encryption/decryption using shared key in java? - java

I have customer token which i am sending from one webapplication say app1 to another webapplication say app2. I want to encrypt the customer token
at app1 and decrypt it at app2 using key which is shared at both app1 and app2. i am not getting how to start with this? It would be very
helpful if somebody can point me some sample code or some tutotrial using shared key as there are too much encryption/decryption stuff(like symmetric key, public-private key) on net which has really confused me. Another limitation is that i have really short time for this to go in details. Thanks in advance.
EDIT:- I am looking for simple programme something like given at http://sanjaal.com/java/186/java-encryption/tutorial-java-des-encryption-and-decryption/ but using AES? Not able to find this kind of example in AES using shared key?

I would suggest this :
Have each app of yours assigned a public/private keypair and store the private key securely protected with a password in a secret key. Make sure that this is very secure. Needless to say the public certificate(which contains the public key as well) will be public. Each app will have the public key certificates of all the other app. Now when ever an app wants to communicate with other app ;
First sign(basically encrypting) the token with the sending app's private key. Then encrypt the resulting value with the public key of the app you want to send the data to.
This way the app that receives this value can be assured that no man in the middle will be able to make out what you have sent and also verify that the token has come from a trusted entity.
But if you use a shared key(symmetric key), then if the symmetric key is compromised, then all the apps will be compromised.

Usually you use a asymmetric algorithm (Eg. RSA) to encrypt a symmetric key (Eg. AES) to securely share it with another party and then your subsequent communication is encrypted with the symmetric key. That is VERY basic gist of it but there are a lot more factors to consider.
And I can see yourself getting in to VERY big trouble right now for several reasons.
You don't understand the concepts of cryptography
You are not willing to thoroughly study it
Simply wants to grab some code from the web and use it.
Really short time
I understand that you might not have a choice perhaps your employer/client wants to get this done quickly. But I thoroughly advice you NOT to go ahead unless you know what you are doing. If you are handling sensitive details such as credit card information or other critical customer information, do your self a favor and study cryptograph in depth.
It doesn't matter how strong the cryptographic algorithm is if you use it in an incorrect fashion. So you need to understand HOW to properly use each algorithm and it's advantages/disadvantages.

Related

Best way to encrypt messages in Java where ciphertext is public

I'm writing an app in Java where users must be able to share encrypted messages, and communication happens exclusively via a database where all data is publicly visible.
Requirements are roughly:
Each user may publish some information (e.g. a public key) to the public database but should only do this once
Other users must be able to encrypt a message for a target user and publish it publicly on the same database
The intended recipient must be able to decrypt the message, but no other user should be able to do so
The encryption must be strong enough that no plausible brute force computation should be able to decrypt the message (now or in the future)
Messages are arbitrary length, but usually quite small (think short emails, tweets etc.)
Must be easy to implement in regular Java (libraries like Bouncy Castle are fine if needed)
Users already have Ed25519 key pairs for digital signatures if necessary
What crypto algorithm or combination of algorithms would be best to meet these requirements? I'm assuming some form of asymmetric encryption algorithm with a public/private key pair for each user but alternative ideas welcome. I definitely want to avoid the "roll your own crypto" trap though....
You (almost) always roll your own protocols. Which is usually where the hacks are.
Now, if you were to roll your own algorithm (as in, you avoid, say, AES-256, and write something on your own. We'll just XOR every byte with a repeated application of 'OhWowThisIsTheBestSecurityEvar', it's like a one-time pad right, can't be cracked! - that kinda thinking is what the whole 'dont roll your own crypto' meme is all about. Don't do that.
Even if you use off the shelf 'protocols', it's real easy to mess it up and create holes. The protocol side (HOW you use the crypto algorithms) is by its nature not easily abstracted into a single, hard-to-impossible to abuse prebuilt library.
So, roll your own. Protocol that is.
It seems nearly trivial here - but it's not. The basic job is to use Public/Private key crypto, in the usual fashion, encrypting the message with symmetric crypto (say, AES-256), generating a random IV and random key, and storing both in the DB, but the key is stored encrypted - encrypted using Public/Private key crypto.
That is, at its core, enough to do what your requirements say you want. But, what about replay attacks? Possibly overzealous or implausible, but what if I can write stuff into your DB? I could replay the message: Store the exact same ball of encrypted bytes but with different timestamps, and you'd think it was real.
That's exactly one of those protocol thingies: It helps if you include the timestamp, sender, etc all inside the blob to be encrypted - you want a replay attack to be innocuous, and generally, if the message (including the metadata) is the exact, precise same, it should be. Maybe. Usually. It depends on what your users expect and what they'll be using it for. There is no such thing as perfect crypto, after all. But if even that is not acceptable, there are solutions to that too, though the easy route is simply to ensure nobody has raw SQL-level write access to the DB.
If your system gets 'hacked' it'll almost always be in the second-level 'protocol' bits. Can I just call your help desk and inpersonate a user? Can I just say I lost my password and get a new one mailed to me, and 'just' hack the user's email instead? Can I stick a keylogger in their computer? Maybe litter some USB sticks with RAT worms around the parking lot; a RAT worm specifically written to find their key files, catch them in entering the password for this key file, and send it all to me? No 'off the shelf java library' is ever going to protect you against any of this. You can't do security in a 'I dont really know what I am doing, but I at least I know I don't know so I'll make sure to get a community and expert recommended library and try to follow its manual as well as I can and surely I'll be fine!' - kind of fashion. Not if you take it seriously.
Some of the algorithms you should probably use:
BouncyCastle supports ElGamal, a Public/Private key encryption scheme. The idea is that all users have a public and private key; the public key is known to your server (and all users on demand; your server is a clearinghouse for them and will have to vouch for the truth, that is, if you go: "here is the public key for user Foo", you're vouching that this is true, and presumably vouching that the personal info of user Foo on your site is correct. How - that's on you, and has nothing to do with crypto, but with politics and local processes. Do you call them? Do they identify themselves with a passport? What? The private key is known only to them. You'll need to handroll some sort of invalidation scheme. Perhaps users can anoint a few other users - they then get the right to invalidate their key. The idea being, if a user feels their private key is compromised, they ask one of their buddies to log in and authenticate themselves to the system, and tell the system to mark your public key as no longer valid for any further communications.
Note that you'll have to find a way to use that Ed25519 key pair you have if you want to use that for the vouching system as above.
Use AES-256 along with your plane jane basic new SecureRandom() to generate a key for each and every message you want to store in the system. To store a message, you take the data, generate a random key, encrypt the data using that key and the AES-256 algorithm, store the encrypted data, then you encrypt the key using ElGamal and the user's public key, and store that too. To decrypt this data, the user fetches the (with their public key encrypted) key data (which can be public), and the encrypted data (also public), and can undo the job on their end by first using their private key + ElGamal to derive the randomly generated AES-256 key used, and then use that. You don't encrypt the entire message with ElGamal; that's quite slow and not the common way to do it. AES-256 is blazingly fast. But symmetric. You'll need a 'block mode' and a 'padding mode' for your encryption in addition to an algorithm (Which will be AES-256). block mode should probably be GCM; you may read about CBC; that's outdated (worse, and slower). Definitely don't pick ECB, that's straight up insecure. Padding probably doesn't matter, depends, as usual, on so many factors.
You mentioned nothing about signatures. If user "Foo" wants to send a message to user "Bar" in a way that nobody but Bar can read it, all they have to do is the above. But if they do, "Bar" has absolutely no idea who sent it. GCM has some built in support for MACs, which is what you need to tag a message in a way that senders can prove they were, in fact, the sender, and also to tag date and time, though this is not easy; basically you as a server would tag any message with 'I, server, decree, and you are going to have to trust me, that this was present in the DB at this point in time and appeared recently; to me anyway. Signed, server'.
That'll give you a few terms (MAC, GCM, AES-256, ElGamal, Bouncy Castle, signatures, and a few more) to search the internet for and read up on.
It sounds to me that you are developing a chat system.
The way to fulfil your requirements you need to combine two crypto systems.
The first one is a Diffie-Hellman key exchange - in short: each party generates a private/public key pair. The public key is stored on the server. If I try to send a message to Bob I'm using your database for "Bob" and get his public key. Next I'm generating a "shared secret" with my private key and Bob's public key - this shared secret is usually 32 bytes long.
Now the second phase begins - I'm encrypting my message with an AES algorithm (best one could be "GCM"-mode) and save the encrypted message (encoded as Base64-string) in your public database (of course with any hint that the counterpart is me).
Third phase: Bob is getting the encrypted message with the note it's from Michael. Now Bob is searching in the database for Michael's public key, builds the shared secret with his (Bob's) private key and Michael's public. Some kind of magic will happen - the shared secret is the same key I used for encryption. Now Bob is been able to decrypt my message.
Just a note: beware the risks because if Bob will lose his private key (maybe stored on his stolen smartphone) he will no longer read any messages for him, so a backup of his private key is needed.

Is it safe to store the encryption/decryption key into a static variable?

I am developing an app in Android Studio and I am passing data from server to phone via JSONs.
Is there a way for me to encrypt JSON data?
Is it safe to store the encryption/decryption key into a static variable? If not where should i store the keys in Android?
None of theses SO questions below helped me:
Can I encrypt my JSON data?
Encrypt json data
It is absolutely NOT safe to store the encryption/decryption key into a static variable.
For this kind of communication, rather than one secret (symmetric) key being shared between the server and your app (which you have to arrange and keep track of), an asymmetric key pair is used. A key pair is a private key and the corresponding public key.
Let's pretend you only need to encrypt data going one way, from the server to the app: Your app generates a random, dispensable, temporary key pair, and sends the public key to the server. The server can then use that public key to encrypt the message that it is sending back to the app, without ever seeing the private key, and the message can only be decrypted with the private key, which never left the app. The public key cannot be used to decrypt, only encrypt.
If that key pair was created just for that exchange, then it can be thrown away and a new pair established for communication at any time (or after an expiration date/time).
That said, this is all done automatically, in both directions with https connections. So, setting that up would probably cover your needs. You're kind of re-inventing the wheel, otherwise. Unless you want that kind of strict control over the security. Even then, do both!
**Note: The above explanation is for conceptual purposes. Strictly speaking, https uses the Diffie-Hellman key exchange to send public keys between client and server (as stated above), but those are used to compute a shared symmetric key, which is more efficient, computationally.
Solution for your question is Certificate pinning. It prevents from MITM (man in the middle) attacks. Certificate pinning means that your app is verifying that the site the app is communicating with is the actual site by comparing the certificate presented by the site to one bundled in the app.
Please refer following link for more information
https://davidtruxall.com/android-certificate-pinning/
Yes, Communication between Android and Server can be secure and you sure can encrypt your JSON payload. Take a look at this git hub repo for how to encrypt your JSON payload. Encrypt your JSON payload(android project)
You can generate a public-private key pair and only share your public key with the client(Android). You can save the public key in whatever way you want to on the Android device. https, is also a good way to secure communication between client and server but take a look at this question to help guide you more.

Where do we store key/passphrase/salt for encryption?

My app needs to encrypt some data (a user session token). Most examples I see around have a method that generates a Key using a passphrase and a salt, like:
public static Key generateKey(char[] passphrase, byte[] salt) {
...
}
My understanding is that we have three options for generating the passphrase:
Have the user enter it every time the app starts (annoying to the user).
Hard-code the passphrase into the app itself. More convenient for the user, but someone can find out what your passphrase is given your app binary.
Randomly generate a passphrase, but then we have to store the generated Key on disk. Now we've just shifted the problem to having to store the key securely on disk, which also seems impossible. If the attacker finds the generated key, big problem.
Option #1 won't work for me. Options #2 and #3 seem inherently flawed, unless I'm grossly misunderstanding how to go about this (hoping that I am). What's the recommended way to do this if we can't go with #1? Do we put in a bunch of obfuscated hoops for an attacker to jump through and hope for the best?
Thanks
"Do we put in a bunch of obfuscated hoops for an attacker to jump through and hope for the best?" Basically yes. The size and number of the hoops being how hard you want to make it.
If you are not using a server, then whatever you do to obsfucate and encrypt your data is reversible. However, you can make it REALLY hard. For example, a technique I used to protect some video assets.
Replaced the first 1024 bytes of the header (it's MP4) with 1024 bytes taken from the middle of one of the apps image assets. I tried several repairers, all of which failed to automagically recover the file - although it can be done manually. Then...
Encrypted the file using a private key which is 256 bytes taken from another image asset.
When the key is extracted, it's hashed through an algorithm which does all kinds of otherwise non-sensical maths to mangle the key.
Used a pre-compile obsfucator.
I've tried myself to reverse engineer this, even knowing how it's done, and it's so hard as to make the effort not worth the result.
There are numerous discussions on SO which summarise as; If you simply want to stop copying, make it difficult (cost vs reward) but otherwise sleep easy because there is ultimately nothing you can do. If the data is commercially sensitive, then a server coupled with system level security (e.g whole device encryption and no root) is required.
You store the salt along with the encrypted data, it is not secret information. You can derive the key on either something the user enters, or some sort of a device property: (hashed) IMEI, MAC address, etc.
Basically, think who are you protecting your data from and why. Since the user needs this, there is not much point trying to protect it from them. If you store this in a private file, other apps cannot read it on a non-rooted phone. If you want to protect it on rooted phones, encryption might help, but as long as the key resides in the app, or is derived based on something on the device, it is only making it harder, not impossible to recover.
Android does have a system-wide keystore service, but it has no public API and is subject to change. You could use that to protect your key(s), if you are willing to take the risk of your app breaking on future versions. Some details here: http://nelenkov.blogspot.com/2012/05/storing-application-secrets-in-androids.html

DSA vs RSA and AES128 vs AES256 encryption in Java

DSA & RSA
It's not about which one is stronger.
I've been researching the subject on the internet and below is the summary of information I've got.
Can you please advise if it is correct or not, and if there are any additional important issues which I don't mention here.
Here I am talking only about DSA vs RSA in application to Java.
My main goal - to use Public key algorithm to send Session key (AES) from client to server and then to check authencity of client.
DSA.
1. In Java you're are supposed to encrypt the file with private key.
2. It means that IT IS a signature - anyone with a public key can read it, but only the owner can sign it.
3. If you try using public key as private and vice versa, you'll run into trouble, because it is not that difficult to guess public key by private.
4. You effectively can't use DSA to send Session key, because everyone will be able to decrypt it.
RSA.
1. In Java you're are supposed to encrypt file with public key.
2. It means that this is best way to deliver secret messages to one specific recepient. Nobody can read it after being signed, except for the owner.
3. If you try switching keys with each other it will bring troubles (the same as above)
4. You can effectively use RSA for a client to send Session key encrypted with Server's open key and then receive confirmation from servers signed with Client's open key.
Based on this I decided to use RSA for my purposes.
AES256 vs AES128
Another unrelated question - do you think that for session encryption without any extremely sensitive data it makes sense to use AES256?
I'd like to, but it creates problems for end user. I know it is very easy to install update to Java which allows 256 bit keys, but the sad truth is that even such simple thing can cut potential userbase by half.
On the other hand - if I don't send sensitive information (like credit card numbers) and each key is used for not more than a few days, maybe AES128 is enough?
Obviously I am going to include the option to use AES256 for those users who are not bothered by the need to install update.
Thanks for any comments!
As you found out, DSA is only a signature algorithm, not a encryption one, and as such not suitable for key exchange.
If you have a online connection (and not just transport from one point to another), you can use Diffie-Hellman (which is based on similar ideas like DSA), and use DSA or RSA in signature mode to authenticate the other side to avoid a man-in-the-middle attack.
Other than that, RSA key exchange is also quite usual (i.e. sending the key AES key encrypted with the RSA key of the server).
For the AES variants, AES-128 should be secure for about any time (i.e. bruteforcing should take longer than you'll live). There is only a larger key variant as the US military wanted to use different levels of security for different stuff. (And also, AES-256 is lately showing some (theoretical) weaknesses which are not in AES-128, which could mean that AES-128 is actually more secure.)
But as Kerrek commented, don't try to invent your own protocol, use existing ones. You will make all mistakes the other ones did before, and add new ones. (You can do your own implementation of these protocols if you want, but it is also often easier and safer to reuse existing implementations, too - there are lots of things to do wrong even with secure protocols, like using bad random numbers.)
For online (two-sided) communication, SSL (or now better its successor TLS) is the way to go. In Java, it is available as the SSLEngine class (if you want to use asynchronous I/O), or with a SSL(Server)SocketFactory (for normal socket read/write). I used this for applet/server communication (for my project fencing-game).
For offline (one-directed) communication (like e-mail) or storage, use the PGP data format (which also can use RSA and AES). (I don't know of an existing Java implementation, though.)
DSA means "Digital Signature Algorithm". It's meant for signatures. You cannot use it to encrypt anything.
AES128 is plenty secure enough for sensitive information. Even the US government allows its use for anything except information classified as TOP SECRET, and that only because of a "better safe than sorry" mentality and considering that such information may still be harmful if decoded 50 years from now. I wouldn't hesitate a second to use it for transmitting credit card numbers (which, after all, expire in less than 10 years).

How to securely store a PrivateKey in code [duplicate]

This question already has answers here:
How do I securely store encryption keys in java? [closed]
(4 answers)
Closed 7 years ago.
I'm working on a software project where the application will end up being run in an untrusted environment. I have a need to perform some ancillary cryptographic signing (meaning this is not the primary means of securing data), but do not wish to leave the key in plain view as such:
private static final String privateKey = "00AABBCC....0123456789";
What method can I use to reasonably secure this? I'm aware that nothing is full proof, but this will add an extra layer in the security wall.
For clarification: I've got what is essentially a String that I don't wish to have easily pulled out in a debugger or via reflection. I'm aware that decompilation of the class file could essentially render this moot, but that's an acceptable risk.
Obviously storing the key offsite would be ideal, but I can't guarantee Internet access.
It's impossible to secure a key in an untrusted environment. You can obfuscate your code, you can create a key from arbitrary variables, whatever. Ultimately, assuming that you use the standard javax.crypto library, you have to call Mac.getInstance(), and sometime later you'll call init() on that instance. Someone who wants your key will get it.
However, I think the solution is that you tie the key to the environment, not the program. A signature is meant to say that the data originated from a known source, and has not been tampered with since that source provided it. Currently, you're trying to say "guarantee that my program produced the data." Instead, change your requirement to "guarantee that a particular user of my program produced the data." The onus is then shifted to that user to take care of his/her key.
Forget about obscuring it in the code. It will only make your software harder to read, debug and maintain. You'll also be nailed if your software has to go through a security audit.
If you can't put the key in secure storage (securely on disk, secure memory or a passphrase in someones head), don't bother with anything else.
If you're in a *nix environment, storing the key on disk with root/root 400 permissions might be "good enough".
On Windows, you could use the DPAPI to store the data in Microsofts secure memory.
You could also use a lightweight PBE to encrypt the sensitive key and have the user enter the passphrase when the application starts up.
Whose private key is that? The private key is supposed to be private, so it is wrong to distribute it.
First off - good on you for thinking about this problem!
Is it possible to instead generate a private key, communicate with your Certificate Authority and have it sign the key (and manage a CRL as well)?
As an alternative, if this is going to be running on Windows, you can use the Crypto API to securely store a private key that is marked as not-exportable. How you distribute that key securely can be another challenge though.
Can you break the private key out into two parts: store one in your program, then interactively request the second half - when your app starts ?

Categories

Resources