Closed patvdleer closed 7 years ago
I've updated my code and verified that your generate key functions returns the same as my key (minus the dict for chat). Somehow the data still isn't decrypting...
class AESCipher(object):
def __init__(self, magic, access_key, password):
self.bs = 32
self.key = hashlib.md5(bytearray(access_key, "utf8") + magic).digest() + \
hashlib.md5(magic + bytearray(password, "utf8")).digest()
def encrypt(self, raw):
raw = self._pad(raw)
iv = Random.new().read(AES.block_size)
cipher = AES.new(self.key, AES.MODE_ECB, iv)
return base64.b64encode(iv + cipher.encrypt(raw))
def decrypt(self, enc):
enc = base64.b64decode(enc)
iv = enc[:AES.block_size]
cipher = AES.new(self.key, AES.MODE_ECB, iv)
return self._unpad(cipher.decrypt(enc[AES.block_size:])).decode('utf-8')
def _pad(self, s):
return s + (self.bs - len(s) % self.bs) * chr(self.bs - len(s) % self.bs)
@staticmethod
def _unpad(s):
return s[:-ord(s[len(s) - 1:])]
Decrypt is fixed, will work on the rest later
class AESCipher(object):
def __init__(self, magic, access_key, password):
self.bs = 16
self.key = hashlib.md5(bytearray(access_key, "utf8") + magic).digest() + \
hashlib.md5(magic + bytearray(password, "utf8")).digest()
def encrypt(self, raw):
raw = self._pad(raw)
iv = Random.new().read(AES.block_size)
cipher = AES.new(self.key, AES.MODE_ECB, iv)
return base64.b64encode(iv + cipher.encrypt(raw))
def decrypt(self, enc):
enc = base64.b64decode(enc)
cipher = AES.new(self.key, AES.MODE_ECB)
return cipher.decrypt(enc).decode("utf8")
def _pad(self, s):
return s + (self.bs - len(s) % self.bs) * chr(self.bs - len(s) % self.bs)
@staticmethod
def _unpad(s):
return s[:-ord(s[len(s) - 1:])]
Sorry for bugging you again, I've almost completed the port but I've one last big issue which I seem unable to fix... I've compared my data to yours and the encryption content, the base64's, match.
What I send is:
DEBUG:sleekxmpp.xmlstream.xmlstream:SEND: <message from="rrccontact_[SERIAL_NUMBER]@wa2-mz36-qrmzh6.bosch.de" to="rrcgateway_[SERIAL_NUMBER]@wa2-mz36-qrmzh6.bosch.de"><body>PUT /heatingCircuits/hc1/temperatureRoomManual HTTP/1.1
Content-Type: application/json
Content-Length: 24
User-Agent: NefitEasy
0BlCRtWBHVpf458IXp2ipQ==</body></message>
DEBUG:sleekxmpp.xmlstream.xmlstream:SEND: <message from="rrccontact_[SERIAL_NUMBER]@wa2-mz36-qrmzh6.bosch.de" to="rrcgateway_[SERIAL_NUMBER]@wa2-mz36-qrmzh6.bosch.de"><body>PUT /heatingCircuits/hc1/manualTempOverride/status HTTP/1.1
Content-Type: application/json
Content-Length: 24
User-Agent: NefitEasy
1H2/Nt03I7zYLhe4Bx15kg==</body></message>
DEBUG:sleekxmpp.xmlstream.xmlstream:SEND: <message from="rrccontact_[SERIAL_NUMBER]@wa2-mz36-qrmzh6.bosch.de" to="rrcgateway_[SERIAL_NUMBER]@wa2-mz36-qrmzh6.bosch.de"><body>PUT /heatingCircuits/hc1/manualTempOverride/temperature HTTP/1.1
Content-Type: application/json
Content-Length: 24
User-Agent: NefitEasy
But the response is the following:
DEBUG:sleekxmpp.xmlstream.xmlstream:RECV: <message xml:lang="en" to="rrccontact_[SERIAL_NUMBER]@wa2-mz36-qrmzh6.bosch.de/927e9e62" from="rrcgateway_[SERIAL_NUMBER]@wa2-mz36-qrmzh6.bosch.de/RRC-RestApi" type="chat"><body>HTTP/1.0 400 Bad Request
Content-Type: application/json
connection: close
</body></message>
DEBUG:sleekxmpp.xmlstream.xmlstream:Event triggered: message
DEBUG:sleekxmpp.xmlstream.xmlstream:RECV: <message xml:lang="en" to="rrccontact_[SERIAL_NUMBER]@wa2-mz36-qrmzh6.bosch.de/927e9e62" from="rrcgateway_[SERIAL_NUMBER]@wa2-mz36-qrmzh6.bosch.de/RRC-RestApi" type="chat"><body>HTTP/1.0 400 Bad Request
Content-Type: application/json
connection: close
</body></message>
@patvdleer sorry for the late response, I was on holiday for a few days :)
From what I remember, the backend is pretty strict about what it accepts as valid messages.
It looks like you're adding an additional empty line between the header and the body, where there should only be one (empty line, that is).
Also, IIRC, the lines should be separated using just \r
(not \r\n
as with regular HTTP requests).
I did that but still no luck, https://github.com/patvdleer/nefit-client-python
I did notice you replace the \r
with old style enter
but my library translates that into &#13;
Oh yeah, you're right, they get translated to \n
, even.
So try and see if \r\n
works. If not, you probably do have to translate the \r
to
(did I mention the backend is a bit weird in that way? 😉)
Ugh... Currently looking into how I can prevent this, by the looks of it it's the send function that replaces the &
with &
DEBUG:sleekxmpp.xmlstream.xmlstream:SEND: <message to="rrcgateway_@wa2-mz36-qrmzh6.bosch.de" from="rrccontact_@wa2-mz36-qrmzh6.bosch.de"><body>PUT /heatingCircuits/hc1/manualTempOverride/temperature HTTP/1.1&#13;
Content-Type: application/json&#13;
Content-Length: 24&#13;
User-Agent: NefitEasy&#13;
&#13;
0BlCRtWBHVpf458IXp2ipQ==
Forcing the
(in violation of xml) results in No Content...
DEBUG:sleekxmpp.xmlstream.xmlstream:SEND: <message from="rrccontact_@wa2-mz36-qrmzh6.bosch.de" to="rrcgateway_@wa2-mz36-qrmzh6.bosch.de"><body>PUT /heatingCircuits/hc1/manualTempOverride/temperature HTTP/1.1
Content-Type: application/json
Content-Length: 24
User-Agent: NefitEasy
0BlCRtWBHVpf458IXp2ipQ==</body></message>
DEBUG:sleekxmpp.xmlstream.xmlstream:RECV: <message from="rrcgateway_@wa2-mz36-qrmzh6.bosch.de/RRC-RestApi" to="rrccontact_@wa2-mz36-qrmzh6.bosch.de/54924df" xml:lang="en" type="chat"><body>HTTP/1.0 204 No Content
Content-Type: application/json
connection: close
</body></message>
\n
DEBUG:sleekxmpp.xmlstream.xmlstream:SEND: <message to="rrcgateway_@wa2-mz36-qrmzh6.bosch.de" from="rrccontact_@wa2-mz36-qrmzh6.bosch.de"><body>PUT /heatingCircuits/hc1/manualTempOverride/temperature HTTP/1.1
Content-Type: application/json
Content-Length: 24
User-Agent: NefitEasy
0BlCRtWBHVpf458IXp2ipQ==</body></message>
Results in:
DEBUG:sleekxmpp.xmlstream.xmlstream:RECV: <message to="rrccontact_@wa2-mz36-qrmzh6.bosch.de/799a0817" type="chat" from="rrcgateway_@wa2-mz36-qrmzh6.bosch.de/RRC-RestApi" xml:lang="en"><body>HTTP/1.0 204 No Content
Content-Type: application/json
connection: close
</body></message>
204 is actually what's expected to be returned when a PUT
request was successful 👍
Seriously??!?!??!?! 204 is the new 200 OK? It works... THANKS!!!
https://github.com/patvdleer/nefit-client-python/commit/03c7d4d457a1fe4a25d3e5b8c2bb7d79527744b1
204 is quite common for REST API's 😃
Awesome work Robert but I'm running Home Assistant(.io) which runs on Python, so I would like to port it.
Based on https://github.com/robertklep/nefit-easy-client/blob/master/lib/encryption.js#L11-L12
Would you be able to provide me with an example of the input and output of the function so I can verify that my code is working since I'm getting an empty string back. Random values should suffice.
function generateKey(magicKey, id_key_uuid, privatePassword)