Closed andreassolberg closed 6 years ago
The Nefit Easy thermostat is shipped with two codes: the serial number and the access code. The user adds their password when they initialize the device for the first time.
The access code for the Easy is a 16-character code. It's not hex and contains both upper- and lowercase characters (so I don't think it's a base-?? representation of a long number). It's presented as such, not as a QR code.
The access key and the password are used, in combination with a fixed "secret" in the Nefit Easy app, to encrypt/decrypt messages. The serial isn't used in that process.
I assume that you can control the pump with an app? If so, how do you "pair" the app with the pump? Which data do you have to enter? That might provide a clue which values might be getting used in the encryption/decryption process.
Sorry to drag up an old "issue" but I was trying with with another Bosch product, under the swedish brand IVT, which is similar to the Bosch mentioned before.
The api uses wa2-mz36-qrmzh6.bosch.de, but I can't get the server to authentic ok. On the unit I have a "Loginname", "Passwort" and QR code. I could register the unit on the IVT Anywhere app with the QR code, or the Loginname and password, after which I assign my own password.
The loginname seem to be based on the serial of the unit 9 numeric digits, and the "passwort" is 16 digits in 4 digit chunks separated by "-" XXXX-XXXX-XXXX-XXXX where X is a mix of numeric digits and upper and lower case letters.
I've tried with: node v8.12.0 npm 6.4.1 easy-server 5.0.2 and just for interest the earlier node v6.0.0 npm 3.8.6 easy-server 5.0.2
and got the same "XMPP authentication failure"
Even tried removal of the "-" in the access-key/passwort
I've also attached the com.bosch.tt.IVT_2018-06-28.apk file (renamed to zip) if that helps Any help would be appreciated.
@GitDuff I've recently taken a look at the IVT Anywhere app for a Norwegian user, but in the end we didn't get very far.
We did determine that the username that is being used is contact_SERIAL
(where SERIAL
is replaced by the 9-digit serial number), but I now realise that the current version of nefit-easy-core
hardcodes certain string prefixes that are required for the Nefit Easy, but won't work with IVT (because it uses a different prefix).
If you know how to modify a Node module, you can edit the file nefit-easy-core/lib/index.js
, specifically these lines:
const ACCESSKEY_PREFIX = 'Ct7ZR03b_';
const RRC_CONTACT_PREFIX = 'rrccontact_';
const RRC_GATEWAY_PREFIX = 'rrcgateway_';
Start by changing the first two to this:
const ACCESSKEY_PREFIX = '';
const RRC_CONTACT_PREFIX = 'contact_';
And see what that does.
Cheers, I'll try that and see if I get any further.
Still "XMPP authentication failure"
Did you also try removing the dashes from the password? Other than that, I can't be of more help: I don't have an appliance that uses the IVT Anywhere app so I can't do any testing or network sniffing :(
Yeah, Tried that also. Seems like the IVT app is in essence identical to the Bosch EasyRemote app since I can use that also without any issues. I'll try and connect a laptop with wireshark between the IVT Gateway and router and see if I can see anything obvious on the packets regarding the prefixes.
The Norwegian user also provided some Wireshark traces, which is how I found out which username was being used. But password isn't sent in the clear (thankfully ;), and at least for the Nefit app, the password is also prefixed with a string before being hashed. I haven't been able to find out it the same applies to the IVT/EasyRemote apps, though.
If you're interested in a decompiled version of the app, let me know. I have to warn it's obfuscated, so not very clear, but nonetheless it might be helpful if you can read code :)
Hi, Code is no probs :) its my day job too, granted Erlang. Which is the reason I ended up here. The heating system is the final part to integrate in my own home automation software.
I scanned through the apk of the NefitEasy app and can see the "rrcgateway" "rrccontact" and "Ct7ZR03b_" visible in the classes.dex file. Unfortunately I couldnt see an equivalent in the classes.dex file in the IVT app, wishful thinking it might be so simple.
Absolutely interesting to see the decompiled version of the app.
Thanks Alan
Cool :) If you can send me an e-mail (robert AT klep DOT name), I'll send you the decompiled app.
done :+1:
A while since I looked at this last time, I did not succeed then. But I am very interested in solving this.
The content of the communication with wa2-mz36-qrmzh6.bosch.de
seemed to be a simple REST based protocol wrapped in XMPP. The simple REST protocol is exposed directly at the heat pump from the local network. If I remember correctly this protocol is stateless, and there is no authentication, however the response was encrypted using aes-256-ecb
. I did create a simple script to try to decrypt the response based upon this library. But I have not yet succeeded.
If the logic and code is correct, I guess the variables are prefixes, and the secret magic key.
I use an iOS app called Bosch ProControl. I have decompiled it, but it seems that the interesting part may be within an SO file. And I have no experience with debugging these things further:
[andreas@andreas-solberg:com.bosch.tt.ProControl-v3.2.4_source_from_JADX]$ grep -ri wa2-mz36-qrmzh6.bosch.de *
Binary file lib/armeabi-v7a/libcomlib-android.so matches
Binary file lib/x86/libcomlib-android.so matches
Binary file lib/arm64-v8a/libcomlib-android.so matches
Binary file lib/armeabi/libcomlib-android.so matches
@andreassolberg for IVT and Nefit, XMPP authentication is required, and on top of that, there's an additional layer of encryption that is exactly how you describe (a REST-ish protocol over XMPP where request and response data is encrypted using AES256).
IVT uses different authentication and encryption mechanisms than Nefit, and it sounds like your heat pump uses yet another mechanism. For IVT, what really helped was decompiling an older version of the IVT app, which is much less obfuscated than current versions. Perhaps the same applies to the ProControl app too (I'm also using jadx).
If you connect to wa2-mz36-qrmzh6.bosch.de
you have to authenticate, some XMPP SASL variant.
However, if I perform a simple GET call directly to the heat pump from the local network, I get an encrypted response. I tried to wireshark this today, by checking of the iOS app to perform a local connection rather than going via bosch cloud service.
The request goes like this (unauthenticated):
GET /dhwCircuits/dhw1/actualTemp HTTP/1.0
User-Agent: TeleHeater
Connection: Close
Host: 10.0.0.15
and the response is encrypted (at least looks encrypted):
200 OK
Content-Type: application/json
DRWPn5EsglvzkwzJI0xQmPTPW0bkHAzKfN9KfvyMqiSaT9QLjFElsBBgDSyhVHeO2/7HdoB9N9OTNIT6JqynIQqWYrz4gc4Jr8/No9Vb8gpaJiopRPY+IhRDnvqRmp/khtrI17FkBv+/iADI+BWqpDuXl11gHoQnI5ZMoshPZpasBedRxcLm2tx+qqotU7LPjtRo4c1gbS9+i0xNxI31veIsoA49Gz3l8d3C5JWgseQ=
Looks like you could get this working using this Node.js module that I uploaded to Github earlier today: https://github.com/robertklep/bosch-xmpp
Try the IVT example with the correct credentials. FWIW, this doesn't communicate with the device directly, but over XMPP (basically because all this code is based on my initial work for the Nefit Easy device, which doesn't expose an HTTP server directly).
At least for IVT devices, decryption works.
WOW IT WORKS! Thank you!!!
[andreas@andreas-solberg:bosch-xmpp]$ node bosch-example.js
{
"id": "/heatSources/returnTemperature",
"type": "floatValue",
"writeable": 0,
"recordable": 0,
"value": 29.4,
"unitOfMeasure": "C",
"state": [
{
"open": -3276.8
},
{
"short": 3276.7
}
]
}
Nice!
What type of device (make and model) are you communicating with? I'm trying to compile a list of devices (or device ranges) that the code works with :)
Must have a try at the local api also...
On 23 Sep 2018, at 21:35, Robert Klep notifications@github.com wrote:
Nice!
What type of device (make and model) are you communicating with? I'm trying to compile a list of devices (or device ranges) that the code works with :)
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread.
What type of device (make and model) are you communicating with?
Bosch Compress 7000i AW
Closing this issue.
For those interested: I added a command line interface to bosch-xmpp
that will make it easier to interface with your devices. More info here: https://github.com/robertklep/bosch-xmpp#command-line-interface
Thanks for the help... Works great.
Hi.
if you still need a key then i have the "vendor key" or get it https://github.com/hansliss/regofetcher i did the program c# to read and write to the rego2000 module I believe "vendor key" is the same in other modules. Bosch, IVT, et al.
-Marko
Thanks @Marko-Rintamaki :)
That is indeed the same key as I'm using for IVT (here).
WOW IT WORKS! Thank you!!!
[andreas@andreas-solberg:bosch-xmpp]$ node bosch-example.js { "id": "/heatSources/returnTemperature", "type": "floatValue", "writeable": 0, "recordable": 0, "value": 29.4, "unitOfMeasure": "C", "state": [ { "open": -3276.8 }, { "short": 3276.7 } ] }
Hi @andreassolberg, @robertklep I'm trying to retrieve values from my new Bosch 7000i using bosch-xmpp on my local network. I seem to have trouble authenticating. This is what I'm trying:
const{IVTClient} = require('bosch-xmpp');
const client = IVTClient({
host : '10.180.1.20',
port: 5222,
serialNumber : '2600-818-000036-8738208984',
accessKey : 'xxxxxxxxx',
password : 'XXXX-XXXX-XXXX-XXXX'
});
client.connect();
console.log('This example is different!');
try {
console.log('client = ',client);
console.log('%j', client.get('/gateway/versionFirmware'));
console.log('%j', client.get('/heatSources/returnTemperature'));
} catch(e) {
console.log('error')
console.error(e.stack || e);
}
client.end();
This is the result:
yunux@angkor:~/Documents/src/bosch-xmpp-test$ node connect.js
{"isFulfilled":false,"isRejected":false}
{"isFulfilled":false,"isRejected":false}
Unhandled rejection Error: MAX_RETRIES_REACHED
at queueMessage.catch.e (/home/yunux/Documents/src/bosch-xmpp-test/node_modules/bosch-xmpp/lib/base-client.js:179:51)
at tryCatcher (/home/yunux/Documents/src/bosch-xmpp-test/node_modules/bluebird/js/release/util.js:16:23)
at Promise._settlePromiseFromHandler (/home/yunux/Documents/src/bosch-xmpp-test/node_modules/bluebird/js/release/promise.js:512:31)
at Promise._settlePromise (/home/yunux/Documents/src/bosch-xmpp-test/node_modules/bluebird/js/release/promise.js:569:18)
at Promise._settlePromise0 (/home/yunux/Documents/src/bosch-xmpp-test/node_modules/bluebird/js/release/promise.js:614:10)
at Promise._settlePromises (/home/yunux/Documents/src/bosch-xmpp-test/node_modules/bluebird/js/release/promise.js:690:18)
at _drainQueueStep (/home/yunux/Documents/src/bosch-xmpp-test/node_modules/bluebird/js/release/async.js:138:12)
at _drainQueue (/home/yunux/Documents/src/bosch-xmpp-test/node_modules/bluebird/js/release/async.js:131:9)
at Async._drainQueues (/home/yunux/Documents/src/bosch-xmpp-test/node_modules/bluebird/js/release/async.js:147:5)
at Immediate.Async.drainQueues [as _onImmediate] (/home/yunux/Documents/src/bosch-xmpp-test/node_modules/bluebird/js/release/async.js:17:14)
at processImmediate (timers.js:632:19)
Unhandled rejection Error: MAX_RETRIES_REACHED
at queueMessage.catch.e (/home/yunux/Documents/src/bosch-xmpp-test/node_modules/bosch-xmpp/lib/base-client.js:179:51)
at tryCatcher (/home/yunux/Documents/src/bosch-xmpp-test/node_modules/bluebird/js/release/util.js:16:23)
at Promise._settlePromiseFromHandler (/home/yunux/Documents/src/bosch-xmpp-test/node_modules/bluebird/js/release/promise.js:512:31)
at Promise._settlePromise (/home/yunux/Documents/src/bosch-xmpp-test/node_modules/bluebird/js/release/promise.js:569:18)
at Promise._settlePromise0 (/home/yunux/Documents/src/bosch-xmpp-test/node_modules/bluebird/js/release/promise.js:614:10)
at Promise._settlePromises (/home/yunux/Documents/src/bosch-xmpp-test/node_modules/bluebird/js/release/promise.js:690:18)
at _drainQueueStep (/home/yunux/Documents/src/bosch-xmpp-test/node_modules/bluebird/js/release/async.js:138:12)
at _drainQueue (/home/yunux/Documents/src/bosch-xmpp-test/node_modules/bluebird/js/release/async.js:131:9)
at Async._drainQueues (/home/yunux/Documents/src/bosch-xmpp-test/node_modules/bluebird/js/release/async.js:147:5)
at Immediate.Async.drainQueues [as _onImmediate] (/home/yunux/Documents/src/bosch-xmpp-test/node_modules/bluebird/js/release/async.js:17:14)
at processImmediate (timers.js:632:19)
Unhandled rejection Error: connect ETIMEDOUT 10.180.1.20:5222
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1083:14)
I'm very new to node.js, xmpp, and related so please bear with me. Am I missing any information, what port should I use? Any pointers are greatly appreciated. @andreassolberg if you can share some code that made it work for you, it would be really helpful. Thanks!
@yunux it's probably the easiest if you base your code on the bosch-xmpp
example code.
Try this:
const { IVTClient } = require('bosch-xmpp');
const client = IVTClient({
serialNumber : '2600-818-000036-8738208984',
accessKey : 'xxxxxxxxx',
password : 'XXXX-XXXX-XXXX-XXXX'
});
client.connect().then(() => {
return Promise.all([
client.get('/gateway/versionFirmware'),
client.get('/heatSources/returnTemperature'),
]);
}).then(responses => {
console.log('%j', responses);
}).catch(e => {
console.error(e.stack || e);
}).finally(() => {
client.end();
});
Some remarks:
host
option is not meant to contain the IP-address of your IVT device, it should only be used if you want to change the address of the Bosch backend server (which you most likely don't want to do)bosch-xmpp
module hereThanks @robertklep . Very helpful. Thanks for putting up with my ignorance :) Now I get this:
yunux@angkor:~/Documents/src/bosch-xmpp-test$ node example.js
XMPP authentication failure
I must have either serial number, accesskey or password wrong although I have tried several combinations.
@yunux try removing all hyphens (-
) from the access key and/or serial number. For the XMPP authentication part, only the serial number and access key are used, the password is only used for data encryption/decryption.
Thanks @robertklep. I tried that already without any luck.
@yunux if you're okay with sharing your credentials with me (over direct e-mail: robert AT klep DOT name), I'll take a look if you want.
On my IVT, there's a 32-byte binary vendor key which is embedded in the app, a device password on the format "aaaa-aaaa-aaaa-aaaa", that's printed on the IP module, and a user password that can be set on the front panel.
The actual encryption key is generated from by first calculating the MD5 of the device password minus hyphens, prepended to the binary vendor key, and then calculating the MD5 of the binary vendor key prepended to the user password, and then concatenating the MD5 sums.
You can find the vendor key for the IVT in my sample config file on https://github.com/hansliss/regofetcher
I'm trying to debug communication with the Bosch backend for a heat pump Bosch Compress 7000 AW. The protocol seems to be more or less identical what this software implements.
However, I'm struggelig with decrypting the messages. I'm not sure what is the accessKey and password for the heat pump. The serial is OK I think. I have set one password when initializing the app, may be that one is the password? But then what is the accessKey? Could it be the QR code on the pump? That is a long digit number, should it be translated into binary/hex? All help is welcome! Thanks...