turiya / keyczar

Automatically exported from code.google.com/p/keyczar
0 stars 0 forks source link

Signed Sessions Encoding problems #136

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
There is a flaw that makes Java signed sessions incompatible with C++ and 
Python signed sessions by the design. In both Python and C++, the ciphertext is 
encoded before it is signed and in Java it is not encoded. (And then the 
reverse of that for decryption) This means that messages between the two 
implementations will fail to respond. Any options added may be unclear as there 
are several places where encoding happens in signed sessions.

For people unfamiliar with signed sessions, they generate an AES key to encrypt 
data and than return the generated key using another keyczar key provided by 
the user. Then messages are encrypted using the AES key and signed using 
another key provided by the user. This allows a user to use slow asymmetric 
encryption to send longer messages more quickly. There are 4 things that can be 
encoded for communication.
nonce
session_material := Encrypted(json({"key" : AES_KEY, "nonce": encoded_nonce}))
encrypted_message := AES_Encrypted(message)
signed_ciphertext := Signed(encrypted_message, nonce)

In all implementations session_material is encoded before it is returned. The 
nonce is also always encoded before it is added to the json in all 
implementations.

The signed_ciphertext has the option to be encoded in C++ (encoded by default). 
It is always encoded in python and it is always not encoded in Java. This is 
given directly to the user so it is really just an inconvenience across 
implementations (although the options for encoding should be there, in my 
opinion)

In C++ and Python the encrypted_message is encoded. In java it is not encoded. 
This will lead to garbled text being returned. This is a design problem as this 
is interior logic that fails cross implementation. I see two solutions

Option 1) Since this is an internal design decision that the user is not 
actually interacting with, I feel like it would be very strange if we gave the 
user the option to encode their encrypted_message, in addition to the option 
encode the signed ciphertext. The user would then have to enable/disable this 
option depending on what version of keyczar the person they are communicating 
with is using.

Option 2) If we just changed the Java implementation (or the C++ and python 
implementations) so all three versions were consistent, the signed sessions of 
the old version will become incompatible with the new version, but it would be 
easier to use without confusing option for how to use it cross implementation.

Option 1 is pretty ugly. but it won't break current code (unless we change 
defaults). This may mean Option 2 may fit better in v2. 

What do you think?

Original issue reported on code.google.com by dlundb...@google.com on 22 Jul 2013 at 7:05

GoogleCodeExporter commented 9 years ago
This broke my brain when I read this. 

How did all the integration tests I wrote pass on every permutation of keyczar 
(minus 50% of c++ since it's missing keyczartool features).

So I went through the code for SignedSessionEncrypter/Decrypter ciphertexts.

* Java version doesn't encode, so the user can encode after signing.

* The C# has option of encoding after signing or not at all. 

* The Go encodes only after signing.

* Python version once upon a time encoded before signing, but it was a bug 
fixed 2011, so it also only encodes after signing.
https://code.google.com/p/keyczar/source/detail?r=974885e7bb7b59429adff5d54974fb
abf8ff178d

So that leaves C++ version. Which I know at least SessionDecrypt passes against 
each of the above versons.
https://code.google.com/r/jtuley-keyczar-dev/source/browse/cpp/src/keyczar/inter
op_test.cc?name=cpp/all#126

But even looking through the code it optionally encodes/decodes only on the 
Sign and Verify step, and the raw binary is used for Encrypt and Decrypt (sent 
to Key class directly)
https://code.google.com/p/keyczar/source/browse/cpp/src/keyczar/session.cc#136
https://code.google.com/p/keyczar/source/browse/cpp/src/keyczar/session.cc#178

So nothing encodes before signing.

So is this issue only the inconvenience of the java version not having an 
option to encode the final result?

Original comment by jtu...@gmail.com on 23 Jul 2013 at 2:17

GoogleCodeExporter commented 9 years ago
You're right. For some reason I was looking at the SessionDecrypter instead of 
the Signed SessionDecrypter in python. And C++ they are using the raw key as 
well. Sorry for the false issue. Java still does not give the option to encode 
the final result and python will always encode the final result. But these are 
not major issues as you suggested.

Original comment by dlundb...@google.com on 23 Jul 2013 at 4:35