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 开发者_如何学Goseparate 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
精彩评论