Complex encryption/decryption model - is this even possible? - java

Suppose I have a server which is publishing information (e.g. via a message bus) to four parties: A, B, C and D. All traffic can be discovered in encrypted form by any party. In order to make use of the information, obviously it would need to be decrypted:
Party A should be able to read all information (i.e. decrypt information intended for A, B and C)
Party B should be able to read information intended for B and C
Party C should only be able to read information intended for party C
Party D should be able to read information for B and D
Obviously this could be achieved by having completely separate public/private key pairs for each party and then sharing the private keys as per the requirements above. Unfortunately this does not scale nicely to hundreds of parties.
Is there a better way?
EDIT
Basically, what I would like to do is for each person to have their private key and for me to say, when encrypting a message, that it is encrypted with key = A | B | C such that this means that a person with any of key A, B or C can decrypt it. Imagine a trunk which can have n locks fitted to it, any of which can open the trunk.

Imagine a supermarket. Every single shelf is independently stockable. There are a hundred shelf stackers, each of whom stack a number of shelves. These stackers have managers, who can overview the shelves of all of their subordinates. These stock managers have section managers possibly having complex relationships, such as manager A being able to see a subset of manager B's shelves. There are a few store managers who can see everything.
I don't think the scalability problem comes from using public-key crypto. It rather comes from the complexity in your requirement (wanting to have so many configurable groups).
If you are going to send out the same encrypted message to hundreds of parties, and there can be an arbitrary subset of them that are supposed to read it, and you want to be able modify these permissions later, you need to give everyone his own key-pair.
You would then send out the message encrypted symmetrically (with a random session key) along with copies of the session key encrypted for all recipients.
If you see that very often you address the exact same subset, you may extend the validity of those session keys to span multiple messages. Then you do not need to transmit all the keys every time (you should still expire them after some time, though).
None of the shelf stackers, stock managers, section managers or store managers would have any kind of clue about public/private key cryptography
Well, their software/device would handle that.

What you want can be achieved using normal protocols based on public key cryptography. The Bouncy Castle Crypto APIs has support for both OpenPGP and CMS, either of which can work from Scala.
TO set everything up:
Every party is given a public/private key pair.
No one EVER shares the private key. The private key must stay private
Every party knows every other party's public key
The protocols allow encryption using multiple public keys. For example, if you use something like the PGPEncryptedDataGenerator, then you would call the addMethod(PGPPublicKey) method for every recipient you wish to be able to decrypt the message.
There are a lot of nuances to the API's, but the unit tests and examples will really help you navigate them.
Implementation Details
Both protocols work in fundamentally the same way.
Securely generate a random symmetric key
For every recipient, encrypt the symmetric key with the recipient's public key. All of the encrypted public keys are written into a message header.
Encrypt the message using the symmetric key. This becomes the message content.
Recipients reverse the process to decrypt the message
Search message header for key addressed to self.
Use private key to decrypt symmetric key.
Use symmetric key to decrypt the message content.

Here's a way that requires n key exchanges, but keeps the messages themselves as small as for two-party communication.
Assuming that the general form of your problem is:
There are n parties, numbered p_1 through p_n
Messages have a security level m, such that only parties p_1 to p_m can decrypt the message.
You can use this key exchange step:
Generate n AES keys, numbered k_1 to k_n.
Securely give each key k_i to all parties p_1 to p_i.
Then to send a message with security level m, just encrypt it with the key k_m.
One side-effect of this scheme is that party p_b does not have the ability to prevent party p_a from decrypting messages they send if a < b. Hopefully that's okay.

Can you use custom encryption like Blowfish?
In such a case you can share the Blowfish encryption key and store it in a, let's say, a properties file!
When the data arrives, depending on the destination and the key value in properties file you can try decrypting them

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.

How to encrypt a txt file after obtaining a public key shared between a client/server in Java

I finally figured out how to perform a Diffie-Hellman key exchange in Java, the problem now is that I have to encrypt a txt file using the shared key. I do not know how to even start to do that. The txt file is just simply the integers 1 2 3 4 5 each on a new line. Is there a simple line of code I do not know about that can perform this function? The shared key that I have is 18.0.
encrypt a txt file after obtaining a public key shared between a client/server in Java
Let's assume you are working on a learning or toy project, otherwise there's no point of (re)inventing your own secure communication. If you want to take the security seriously, just use TLS/SSL (optionally with 2-way client auth ssl) for online content transmission.
I really hope for your own sake you are just learning or playing with this.
to encrypt a txt file using the shared key. I do not know how to even start to do that.
For encryption in rest (encrypting the file itself) - assuming from the question that the sender and receiver are having their own keypairs.
I suggest to create a random data encryption key to encrypt the content. Then you could simply use receiver's public key to encrypt the data encryption key and sign the content's hash using sender's private key. Never use plain (textbook) RSA, use propper padding.
I made a few notes about encryption for myself, you can take some inspiration.
The shared key that I have is 18.0.
Apprently you are using not long enough or not random enough public keys. Symmetric ciphers require keys of fixed length (e.g. AES requires 128, 192 or 256 bit keys). You could generate longer keys using any key derivation function or hash. If you want to use two-way communication, you need a separate key for each direction.
Regardless that - short key seed (small shared key, short public keys) would be feasible for brute-forcing. There are many ways how you could shoot yourself in your leg when dealing with crypto, so use some industrial standard when possible (e.g. TLS).

Encryption/decryption using shared key in 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.

Credit Card storage solution

I'm developing a solution that is designed to store membership details, as well as credit card details. I'm trying to comply with PCI DSS as much as I can. Here is my design so far:
PAN = Primary account number == long number on credit card
Server A is a remote server. It stores all membership details (Names, Address etc..) and provides indivudal Key A's for each PAN stored
Server B is a local server, and actually holds the encrypted PANs, as well as Key B, and does the decryption.
To get a PAN, the client has to authenticate with BOTH servers, ask Server A for the respective Key A, then give Key A to server B, which will return the PAN to the client (provided authentication was sucessful).
Server A will only ever encrypt Key A with Server B's public Key, as it will have it beforehand.
Server B will probably have to send a salt first though, however I doin't think that has to be encrypted
I havn't really thought about any implementation (i.e. coding) specifics yet regarding the above, however the solution is using Java's Cajo framework (wrapper for RMI) so that is how the servers will communicate with each other (Currently, membership details are transfered in this way).
The reason why I want Server B to do the decryption, and not the client, is that I am afraid of decryption keys going into the client's RAM, even though it's probably just as bad on the server...
Can anyone see anything wrong with the above design? It doesn't matter if the above has to be changed.
Thanks
jtnire
As a preface, you're going to have a nightmare of a time developing this and going through PCI compliance. It would definately be worth considering alternatives, such as using a Payment Service Provider that can store these card details for you, and perform ad-hoc authorisation/settlement using Token Ids (rather than keying them in through a 'dialup credit card machine' that you described)
If you chose to ignore that advice and go the PCI route, then at least make sure to get a PCI approved Qualified Security Assesor (QSA) involved as early as possible, to approve of whatever designs you come up with. PCI isnt something you should 'try to comply with as much as you can', its an all or nothing thing unfortunately!
That said though, one way to tackle this would be to have a key serving application running on box A. This application requires entry of two 'key administration' keys, which when xor'd together form a Master Key. Master Key is only ever stored in RAM, never persisted to disk.
The application generates Key Encrypting Keys, which are stored on box A, encrypted by the Master Key. The KEK is generated automatically (its not something that a user keys in). The KEK can be persisted to disk on box A, encrypted by the Master Key.
Card details are stored on box B. This box also stores the Data Encryption Key, which is used to perform symmetric encryption of the card details. The DEK is itself stored in an encrypted format, encrypted with the Key Encrypting Key from box A.
The application that performs encryption/decryption should be on box B, and authenticate itself to box A before requesting the KEK. The KEK is then used to decrypt the DEK, and encryption/decryption can then take place.
If Server A is hacked - this meansI baically can still get all credit cards in clear text, or? I have access then to all individual KEY a information that i need to access every credit card.
You might be interested in reading the Bytemark Blog entry on how they store credit card information.
The gist is that the server holding the card information will not divulge the numbers; the allowed operations are "Add new card", "Update or remove existing card" and "Charge a card" -- the server connects to the payment processor itself.

Categories

Resources