tgalal/python-axolotl

KeyExchange interoperability with axolotl-java

gardenia opened this issue · 5 comments

Hi,

I am having an interpoerability problem with the java library when doing p2p KeyExchange. Sometimes it works, sometimes it doesn't.

Are there any known issues in this area?

I have created a functional example here to illustrate the problem I am seeing:
https://github.com/gardenia/axolotl-sandbox

to reproduce the issue I am seeing you will need 2 console windows.

In Window #1:

  • cd into the java directory and type "make run". if the build stuff is working you should output like the following:

ALICE keyexchange initiate >>> 2308c1c004122105c2923b830fcfc984d4f34e685720435b1bafb9bbfde71d32a62109019261ba4a1a21054bddc9e188f261aeecf04dcc08f011ac735be65786e9aa23c7be8a35c09ee3642221058825d0f050925cd3b671affeb11cde9f29dd7d64d9f4e5c9dc3f04e7b8c4ab10

  • copy the blob of hex (from your window) after the ">>>" bit
  • NOTE: the above will be followed by a prompt for a keyexchange response. we will fill this later but not yet

now switch to Window #2:

  • do "make init" followed by "make run"
  • paste in the blob of hex you obtained from Window #1
  • on the second last line you should see something like this:

RESPONSE >>> b'3308c2dc63122105ed51973caa1e00da087d18c0cda3ca92597f45179e7053a5080a42d9693c99241a21051479eb7d325bc5da0efaec6eb9844c36290d9ec49cf3fff6feaee630cf85e46f222105c3d6f9aa7d0b2e87e82664e44cd7591d17f57c8c7136bdfd8ef2cc1ac1fc88242a40f885ebff355d93e1f5c6a5019d9705815eb1760f077c93a20019a814ec6d15fa92d39bac0139b7b34151a4510ca5b81b58405a079b5a69528c1e155b0731d807

  • copy the hex bytes from the above (just the bit inside the quotes)
  • NOTE: the above will be followed by a prompt for a keyexchange response. we will fill this later but not yet

now switch to Window #1:

  • this window should still be prompting for "Enter BOB keyexchange response"
  • paste in the bytes obtained from Window #2 into this prompt
  • you should now see output like the following:

MESSAGE[HEX] >>> 330a210507df96417571fe22dd9f6c6b022f0a712f42adb1ad364e7f69b682743b4f3707100018002210ed04776fdee3747d5cc2117bca394a686836e1218f40ab90

  • copy the hex bytes into your clipboard

now switch to Window #2:

  • paste in the hex bytes you just copied from Window #1

when it works as expected it looks like this:

SessionCipher >>> <axolotl.sessioncipher.SessionCipher object at 0x2ab8c737ce80>
WhisperMessage >>> <axolotl.protocol.whispermessage.WhisperMessage object at 0x2ab8c737ccf8>
DECRYPTED >>>  Hello world

however, about 50% of the time this fails as follows:

SessionCipher >>> <axolotl.sessioncipher.SessionCipher object at 0x2ba2831d2e80>
WhisperMessage >>> <axolotl.protocol.whispermessage.WhisperMessage object at 0x2ba2831d2cf8>
EXCEPTION >>> No valid sessionsBad Mac!
*** print_tb:
  File "main.py", line 60, in handle_data_msg
    data = sc.decryptMsg(wm)

I tried digging into the bad mac error but after a lot of speculative printf style debugging. it seems that the axolotl.ratchet.chainkey keys are mismatching in the bad case but I can't figure out why.

I could well be missing something obvious here but I'm sufficiently stuck on this that I could really do with some further eyes on it.

any help appreciated. I'm happy to dig into it further myself if you have any suggestions.

Thanks.

I believe I see the problem here.

in RatchetingSession.isAlice the java code does a comparison of 2 certificates by making a java.math.BigInteger object with the byte arrays of each cert.

the java mechanism using big-endian and returns a signed integer (https://docs.oracle.com/javase/7/docs/api/java/math/BigInteger.html#BigInteger(byte[])

the current python mechanism returns an unsigned integer:
int(binascii.hexlify(self.publicKey), 16)

this leads to the non-derterministic results between java and python.

for python3 I was able to get it to work consistently correctly using the attached patch (which leverages int.from_bytes). howver, unfortunately this is not portable to python2 and would need to be emulated somehow.

djbec_cmp_patch.txt

here is a patch which from my testing solves the problem on both python2 and python3

it reads the bytes into a tuple of signed ints and then uses tuple comparison

djbec_cmp_patch2.txt

@gardenia can you make that patch into a PR? if you can't be bothered i'll do it
@tgalal hey if this patch is turned into a PR would you accept it ? it fixed my problems :)

@suqdiq - I'll make a PR today

Fixed by 084534f