Informatic / py9b

Ninebot/Xiaomi electric scooter communication library
GNU General Public License v3.0
5 stars 1 forks source link

m365 code to allow encryption #2

Open ilker-aktuna opened 4 years ago

ilker-aktuna commented 4 years ago

Hi @Informatic ,

I know this is not the correct way of contacting but I couldn't find another method. I am really sorry to disturb you this way.

I saw your post here: https://github.com/CamiAlfa/M365-BLE-PROTOCOL/issues/7#issuecomment-546872603

I want to use your method to support BLE> 70 on my project. But I am not a pro. developer and I really know too few about Python. I need some help on integrating your method to the project here: https://github.com/maisi/M365-Power

Can you tell me how I can use your method ?

thanks.

Informatic commented 4 years ago

Yeah, I need to finally do a proper writeup on how that all works.

General principle is as follows:

On older m365 firmware packets were formatted as follows:

  55 AA bLen bAddr bCmd bArg bPayload[bLen-2] wChecksumLE

(borrowed from ninebot-docs wiki)

On m365 BLE firmware >= 0.81 data is formatted as follows:

  55 AB bLen bAddr bCmd bArg bPayload[bLen-2] 00 00 00 00 wChecksumLE
             |                encrypted                 |

As you can see main differences are:

Encryption scheme seems to be just XOR over an unknown keystream. Didn't get to reverse engineer how it is actually properly generated in the first place, but for sure the keystream is symmetric. Likely by accident (?) BLE characteristic 00000014-0000-1000-8000-00805f9b34fb contains first 12 bytes of the keystream, which can be used to encrypt/decrypt any packets which are <12 bytes long. Since we have enough keystream to do any register read, we can then request a very long register read over known plaintext (eg. a block of 00s on BMS memory starting at address 0x50) and then use that to give us further keystream to be able to decrypt/encrypt more data.

Interestingly, seems like packets are decrypted, parsed and verified directly on BLE/dashboard CPU, so that some requests (like ESC register reads of BLE firmware version) pass without encryption. (and thus can be used to enable encryption only on supported firmware versions)

Looking at MiHome app, they used blecipher.so library for encryption, which is common for many Xiaomi devices. This seems a lot like the algorithm documented here: https://github.com/aprosvetova/xiaomi-kettle/blob/master/cipher.go Sadly, again, I haven't been able to find how the secret part of this whole scheme is generated/fetched and only work on scrambled keystream.

PSA: this has been mostly based on reverse engineering of already existing unofficial Android apps that support newer m365 firmware, and there's little to no original research here. Also keep in mind I've only been able to get hold of and test it on (my) m365 Pro running BLE firmware 1.00, so this might actually not be 100% correct for "original" m365.

ilker-aktuna commented 4 years ago

Hi,

Thanks for your response. However, I could not find where I should make changes on the code here: https://github.com/maisi/M365-Power

I guess it would not be an easy change. But maybe if we can locate where to make the change, I can at least try. can you have a look at this code ? (Its author is not responding, I guess he's abandoned it)

ilker-aktuna commented 4 years ago

nobody has any interest in this ?

robbiet480 commented 4 years ago

Just a quick update that the encryption has been mostly if not entirely broken. You authenticate using a few undocumented commands and after that all messages are AES-ECB encrypted with a SHA1 key originally derived from the device BLE name. I hope to produce some solid documentation in the next few days. Currently just working through some last remaining issues to verify the protocol. Hang tight a little longer! Also, so far I haven't had to touch any of the FE95 characteristics although they may help at some point. I own a Ninebot Max, I assume the protocol will be very similar for Xiaomi.

Informatic commented 4 years ago

Sounds great. This is somewhat what I anticipated, but just didn't have enough time and motivation to dig that deep, since I already achieved what I needed in my specific case. Would love to see some write-up on that.

On Fri, 28 Feb 2020, 00:01 Robbie Trencheny, notifications@github.com wrote:

Just a quick update that the encryption has been mostly if not entirely broken. You authenticate using a special and undocumented command and after that all messages are AES-ECB encrypted with a SHA1 key originally derived from the device BLE name. I hope to produce some solid documentation in the next few days. Currently just working through some last remaining issues to verify the protocol. Hang tight a little longer! Also, so far I haven't had to touch any of the FE95 characteristics although they may help at some point.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/Informatic/py9b/issues/2?email_source=notifications&email_token=AAIUEXWMDNBYUPEQDXUXNLLRFBA5TA5CNFSM4JIKDLM2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOENGJM4A#issuecomment-592221808, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAIUEXUJ24HTAVQWFUS5F6DRFBA5TANCNFSM4JIKDLMQ .

ilker-aktuna commented 4 years ago

I'd really appreciate if you could help me to implement this encryption support on the code at https://github.com/maisi/M365-Power

I am not good at understanding what you have suggested. I need advise on the code. I know I am asking too much but this code is not mine and I don'T know where to implement the new method you suggested.

mwkaufmann commented 4 years ago

Just a quick update that the encryption has been mostly if not entirely broken. You authenticate using a few undocumented commands and after that all messages are AES-ECB encrypted with a SHA1 key originally derived from the device BLE name. I hope to produce some solid documentation in the next few days. Currently just working through some last remaining issues to verify the protocol. Hang tight a little longer! Also, so far I haven't had to touch any of the FE95 characteristics although they may help at some point. I own a Ninebot Max, I assume the protocol will be very similar for Xiaomi.

@robbiet480 has there been any documentation effort I so far? Would be really interesting from my point of you. Thank you!

robbiet480 commented 4 years ago

@robbiet480 has there been any documentation effort I so far? Would be really interesting from my point of you. Thank you!

https://github.com/scooterhacking/NinebotCrypto is the best available right now.

mwkaufmann commented 4 years ago

@robbiet480 has there been any documentation effort I so far? Would be really interesting from my point of you. Thank you!

https://github.com/scooterhacking/NinebotCrypto is the best available right now.

That was fast! :) Will check it out. Thank you very much.

ilker-aktuna commented 4 years ago

is there any android source code that uses the encryption ?

robbiet480 commented 4 years ago

@ilker-aktuna There's Kotlin examples in that repo.

ilker-aktuna commented 4 years ago

I saw that but I really don'T know Kotlin. Prefer to work with Java. can you have a look at this repo: https://github.com/ealvarezpereira/M365-Power

it seems new. But does it support new firmwares with authentication ?

robbiet480 commented 4 years ago

Sorry, I'm not a Java/Kotlin/Android developer.

mwkaufmann commented 4 years ago

@ilker-aktuna Had a short look at the M365-Power repo. It does (currently) not seem to support the encryption, as I couldn't find any usage of the sha1-hashing function, which is needed to generate the encryption key(s).

But you can simply add the Kotlin code to your Android project and call the methods from regular Java code, as Android projects can be mixed.

ilker-aktuna commented 4 years ago

Actually I really don'T know much about BLE communication procedures and I have the original code from m365 Power app by maisi: https://github.com/maisi/M365-Power so I really don't know how to integrate the encryption algorithm to the original source. I have to read all the code, understand it and then do the integration. , not something I have the time for. maybe later , when I have more time.

but meanwhile, if I can find a code with encryption already applied, I can move to that...