Nice research again @GSzabados!
Unfortunately I do not own tapo plugs, so I am not able to work on this. I stick with the well supported tplink hs110 with api available.
Nice research again @GSzabados!
Unfortunately I do not own tapo plugs, so I am not able to work on this. I stick with the well supported tplink hs110 with api available.
Getting API reverse engineered is the best option but Iām using the following combination:
Pair Tapo with Google Assistant, Install assistant-relay (execute google home commands via api), hass.io making requests to assistant-relay.
Iāve watched what tapo app is sending and after a while Iām able to generate valid TPIoTRequest
which are sent to the p100. (p100 answers with error_code
:0 so itās valid)
Now I will try to decrypt the answer from the p100.
edit:
Iām able to decrypt answer from the p100! So when sending login_device
request, p100 sends {"error_code":-1501}
backā¦ I can communicate with p100 but my username and password are not correct.
Bingo! Username & Password needed to be base64 encoded + username needs to be a SHA-digest.
P100 answers: {"error_code":0,"result":{"token":"887E98FF98EB90AB1......9D0881A98"}}
Sounds very promising! Great work.
Do you think this opens the door for a functional integration?
I think I should be able to send on/off requests
After that point the P100 communicates by using the token the way how it is in this post:
Thanks for picking up this work and carrying further!
More progress!, Iāve patched the android app with my pre-made key pair, so I can decrypt all information the app is sending/receiving to/from p100. (Itās easier to reproduce pure HTTP requests than searching through decompiled code for requests)
App sends this request to change the state of the plug:
{"method":"set_device_info","params":{"device_on":false},"requestTimeMils":1602840338865,"terminalUUID":"88-54-DE-AD-52-E1"}
I can now craft it dynamically, so I can change the plug state (turn on/off) with my own code!
Edit: Now, itās time to document it and create repository with an PoC.
Great work to all of you guys!
Really incredible what you achieved so far!
Definitely easier, great work!
Ah, nice technique.
So the plug uses the key pair from the app? Interesting!
Iāll take a look at the Bluetooth packets tomorrow
Yup, Iāve written a post about the connection here: https://k4czp3r.xyz/posts/reverse-engineering-tp-link-tapo/
Great write up!
So, last night i paired a new p100 and i had packet capture enabled, but it failed to capture any packets.
However, while i was looking for the cached firmware, i found what looks like the AES key.
/mnt/sdcard/Android/data/com.tplink.iot/files/model_cache/deco_model/deco_model
its a txt file with two key:value pairs.
{
"DECO_TPSERIALIZEUTILS_AES_KEY":"skf6gYCmI25E1mcE9WvDWG5wxdExTTAtOeNrFN5aui1SMEHK6Udx9XEgsaDL1ifJEPcDce9gHbSB\nnqfAeSdcTvt+JNP7KBxTdGgU64irT2i8pt+uBxhODNmN\/PX5g2PorsnjsUs6op8us8v4xFxWsSp2\ng4jQLdEgbEkluTz8\/I+htZrgUvaV8EUWVy6oz0nSdkG5b8DJutna\/iqJOO75P2AaqSCf8fnLZet6\ntK1zrSa3+GBifnK+J98gjXn6I6kxkPPUWbRA0JTZhLS+JvLEAa4W34+ZggdFo6soeK7Ga\/gGUy1M\nls2xMSihnt9UR7MO6+P3cLKxu6COZzLbO7bPVQ==\n",
"DECO_TPSERIALIZEUTILS_AES_VECTOR":"IDoSrxMmme+YrIwVJ0tv2tI+ZcCYOPMgprpqwPdgsCu\/ncM4WY6BXNN272KaAHkrAlu+nbNHqa51\nxufCO2DsJz6eQjkuq9IUYw9mzeHsgU4\/lsHJmFd2thfdppaHyIGrFlYA5O\/mfC2gMBMSpXKxXq4G\nyhaxKHN7jynghLrHO6i9d3TvoFXPNbHc0+Koo7COIBMHNn6EbNMSlzrSWi7TEoX7NBwPf\/5FZcnL\ntV+d1IrShHeACrmF2D6ufJkXvaPuA3SIZ7lecdzlTn9ixrBWbJ4cZY3V\/2f7d2vTfm9QxDxkorbQ\n0h8DQtQ\/ub59rdcvjEmRfE9tHZwpLUNHmYOBgQ==\n"
}
I should be able to make a pip package and a custom integration next week. Assuming nobody else wants too before then
Hey,
Iām currently working on a pip package for the plug but Iāve hit a problem. I am sending the turn off code to the plug using requests.post
def turnOn(cookie):
URL = "http://192.168.0.157/app"
Payload = {
"method": "set_device_info",
"params":{
"device_on": "false"
},
"requestTimeMils":1603557345731,
# "terminalUUID": "1c:3b:f3:a5:71:e5"
}
headers = {
"Cookie": cookie
}
r = requests.post(URL, json=Payload, headers=headers)
The request is coming back with
{"error_code":0,"result":{"response":"SCJqlRa0KLL06A3YSoTiqWEMBAHgdD8O6hcwyIw2XUI="}}
But the plug is not turning off (or on for that matter)
@K4CZP3R do you know whatās going on?
Thanks
Your payload needs to be encrypted and inserted as param in payload with method: securePassthrough
(Read āfirst secure passthroughā in my write up)
Edit: Iāve started to implement it in Python too. Iām having problem with decryption methods (in Java itās way easier because app is written in Java too). And there are so many formats of encoding etcā¦
Is this just a simple Base64 encode or does it involve another method?
Thanks for all the help
Itās a encryption using AES.
Ok, Thanks I will try that now
edit: Whatās the key I should be using? My public and private keys are too long. (Sorry if this is a stupid questionā¦)