Let's imagine Alice wants to send Bob a table with 2 columns:
+----------+-----+
| location | age |
+==========+=====+
| ny | 22 |
+----------+-----+
| london | 23 |
+----------+-----+
| ny | 18 |
+----------+-----+
| paris | 25 |
+----------+-----+
| madrid | 28 |
+----------+-----+
| london | 35 |
+----------+-----+
Bob will receive this data and perform some stats over it. The result will be send back to Alice:
+----------+-------------+
| location | average age |
+==========+=============+
| ny | 20 |
+----------+-------------+
| london | 29 |
+----------+-------------+
| paris | 25 |
+----------+-------------+
| madrid | 28 |
+----------+-------------+
However, Alice doesn't want Bob to know the "location" of the individuals (it is irrelevant to perform the average function).
Instead Alice wants to send the first column converted to an "hash" (in terms of keeping coherence between equal values; and the output string has the same length independently of the input string) BUT she should be able to "unhash" the receiving Bob's table (without storing any dictionary that translates the "hashes" into the original strings).
Alice sends:
+----------------------------------+-----+
| location | age |
+==================================+=====+
| 531beb50ffb32d08756e6462c037c8e1 | 22 |
+----------------------------------+-----+
| bc180dbc583491c00f8a1cd134f7517b | 23 |
+----------------------------------+-----+
| 531beb50ffb32d08756e6462c037c8e1 | 18 |
+----------------------------------+-----+
| ccbee73cd81c7f42405e1920409247ec | 25 |
+----------------------------------+-----+
| ed2539fe892d2c52c42a440354e8e3d5 | 28 |
+----------------------------------+-----+
| bc180dbc583491c00f8a1cd134f7517b | 35 |
+----------------------------------+-----+
and receives:
+----------------------------------+-------------+
| location | average age |
+==================================+=============+
| 531beb50ffb32d08756e6462c037c8e1 | 22 |
+----------------------------------+-------------+
| bc180dbc583491c00f8a1cd134f7517b | 29 |
+----------------------------------+-------------+
| ccbee73cd81c7f42405e1920409247ec | 25 |
+----------------------------------+-------------+
| ed2539fe892d2c52c42a440354e8e3d5 | 28 |
+----------------------------------+-------------+
1st approach:
Alice should send a key (in the message heading) to Bob.
Bob, together with his response, will send the same key back (again, in the response heading) to Alice.
[alternative method is proposed after]
This key is valid just for that request and gives Alice a way to decrypt the "hashes" back to the original values:
+----------+-------------+
| location | average age |
+==========+=============+
| ny | 20 |
+----------+-------------+
| london | 29 |
+----------+-------------+
| paris | 25 |
+----------+-------------+
| madrid | 28 |
+----------+-------------+
2nd approach:
The envelope of this message is also encrypted asymmetrically and it should be alright to use traditional client identification (such as client key exchange message in elliptic curves) together with session key, as the final key that generates the symmetric transformation (avoiding sending another key on the heading as proposed before).
In conclusion,
- Equal origin strings should be converted into equal ciphertext strings (for each session)
- Different sessions should produce different ciphertexts for the same string
- Alice should be able to decrypt the ciphertext string into the original one, without storing a dictionary (unlike what happens when using unidirectional hashes)
- The decrypt key should preferably reuse the generated keys that protect the communication envelope, to avoid redundancies or unnecessary information
- Bob should never be able (well, should be very difficult) to reverse engineering the encryption data of a transaction or by collecting multiple transaction's messages (although he could know the mutable part of the key)
- The transformation string should always have the same length (so Bob couldn't identify "ny" because its short length)
Any ideas?