toreamun / amshan

Package to help decode smart power meter data stream of Cosem HDLC frames used by MBUS. The package has special support of formats for Aidon, Kaifa and Kamstrup meters used in Norway (AMS HAN).
MIT License
8 stars 6 forks source link

Encrypted DLMS Payload #7

Open dstrigl opened 2 years ago

dstrigl commented 2 years ago

Hi Tore,

really nice package!

One question:

Do you have any plans to support "Encrypted DLMS Payload" which I would need to use your package with our Kaifa smart power meter.

[ https://www.tinetz.at/fileadmin/user_upload/Kundenservice/pdf/Beschreibung_Kundenschnittstelle_Smart_Meter_TINETZ.pdf ] (sorry, general text is only in German, but relevant parts are in English)

Regards, Daniel.

toreamun commented 2 years ago

Hi, I am glad you liked the package.

I want to support encryption, but I have not been able to find good enough documentation. The official documentation costs money. The link from you looks promising, and I will look at it. But I will need some test samples and its encryption keys to be able to do this. Are you able to provide this?

dstrigl commented 2 years ago

Hi Tore,

yeah I really like your package, it looks very professional ;-) But for my usage it misses the encryption ...

At our home we have a new Kaifa smart power meter with activated encryption. I also got the encryption key from our energy supplier.

So, yes I am able to provide you with this information. I would be glad to support you with that ... Of course I don't want to provide you my personal encryption key I got from the energy supplier, but I could provide you with test samples (payload read from Kaifa) and test the encryption for you. Maybe this would be an option for you?

Beside, there several other projects with included ecryption, but there not at that professional level of yours:

Regards, Daniel.

toreamun commented 2 years ago

Of course I don't want to provide you my personal encryption key I got from the energy supplier, but I could provide you with test samples (payload read from Kaifa) and test the encryption for you. Maybe this would be an option for you?

In my experience, many small details is important when you work with encryption. It is hard to get correct at first attempt. I also need some encrypted data with corresponding key to include in my tests. I don't want to implement anything without having tests in place to be able to run when the projects moves on with other changes. I understand that you dont want your active key to be on Github forever, but maybe you energy supplier can issue a new key when this issue is sorted out?

I can have a look in the projects you linked to see if any of them has some test data with encryption keys. I learned German at school 30 years ago, but I was not av very good student in that subject. But Google translate should be able to help me.

dstrigl commented 2 years ago

Hi Tore,

please take a look at my fork of your repo at: https://github.com/dstrigl/amshan

I just added the support for my Kaifa smart meter from our network operator TINETZ in a "quick and dirty" way, but it seems to work well :-)

I run the reader_async.py script with: python reader_async.py -serial /dev/ttyUSB0 -sp E -key ABCDEF1234567890ABCDEF1234567890 which produces the following output:

DEBUG: Decoded frame: {
    "meter_manufacturer": "KaifaTINETZ",
    "meter_datetime": "2022-03-14T11:34:35+01:00",
    "meter_id": "1KFM0000000000",
    "meter_device_name": "KFM0000000000000",
    "voltage_l1": "232.4",
    "voltage_l2": "233.8",
    "voltage_l3": "233.3",
    "current_l1": "0.58",
    "current_l2": "0.63",
    "current_l3": "7.99",
    "active_power_import": "1952",
    "active_power_export": "0",
    "active_power_import_total": "6698800",
    "active_power_export_total": "0",
    "reactive_power_import_total": "3468988",
    "reactive_power_export_total": "1013767"
}

Maybe you could take a look on it, so that it can find the way in your repo in more professional way?!

Regards, Daniel.

dstrigl commented 2 years ago

This is how the encryption works:

import binascii
from Crypto.Cipher import AES

system_title = b"KFM\x10 \x01\x19\xe9"
frame_counter = b"\x00\x10:\xe8"
i_v = system_title + frame_counter

hex_key = "ABCDEF1234567890ABCDEF1234567890"
key = binascii.unhexlify(key_hex)

data = ...
print(data)

cipher = AES.new(key, AES.MODE_GCM, nonce=i_v)

encrypted, _ = c.encrypt_and_digest(data)
print(encrypted)

decrypted = cipher.decrypt(encrypted)
print(decrypted)
toreamun commented 2 years ago

Nice. I will have a look at it.

toreamun commented 2 years ago

It seems like a bit different protocol than what I know so far. The current implementation expects HDLC wrapped APDU (with payload). The APDU can also be encrypted (not currently supported by amshan) when wrapped in HDLC frame. A HDLC frame always startes with flag sequence (0x7E) and can contain escaping character (0x7D). The frame has a header with CRC checksum and a new checksum at the end of frame. The frame normally ends with (0x7e).

This protocol has a different framing of the payload. It starts with start character (0x68) and ends with a simple checksum and a stop character (0x16). I think this is something called Wired M-Bus profile. This is new to me. I cant find much about it in the public parts of the COSEM blue and green books. But if found an example with payload and encryption key here: https://www.netz-noe.at/Download-(1)/Smart-Meter/218_9_SmartMeter_Kundenschnittstelle_lektoriert_14.aspx

Do you know is protocol has any kind of escaping in case the payload contains the start character and the end character?

Does a new frame (0x68) follow directly after the stop character (0x16) of the previous, or is some kind of special flag sequence of "filler" characters between them?

dstrigl commented 2 years ago

Hi again,

It seems like a bit different protocol than what I know so far.

You are right, at the beginning of my tries I was a little bit confused, because I oriented me on your implementation, before I registered that my Kaifa smart meter delivers a different format of the frames ...

This protocol has a different framing of the payload. It starts with start character (0x68) and ends with a simple checksum and a stop character (0x16).

That's correct.

I think this is something called Wired M-Bus profile.

Sorry, I don't know the correct naming ...

That's the main reference I worked with (from my network operator TINETZ): https://www.tinetz.at/fileadmin/user_upload/Kundenservice/pdf/Beschreibung_Kundenschnittstelle_Smart_Meter_TINETZ.pdf and a few already working implementations on Github (see the links a few posts above).

Do you know is protocol has any kind of escaping in case the payload contains the start character and the end character?

No, not that I know or recognized during my tries. (That was also the reason why I simple tried to "parse" the received data and moved forward to the next start character in case of an ConstructError - I know, not the best method ...)

Does a new frame (0x68) follow directly after the stop character (0x16) of the previous, or is some kind of special flag sequence of "filler" characters between them?

I looks like, the "new frame" starts directly after the stop character, no kind of special flag or "filler". I also looked on the other implementations on Github, non of them has some kind of special handling ...

I hope this will help you!

And thanks for beeing interested in this topic!

Regards, Daniel.

dstrigl commented 2 years ago

Just checked again:

The new frame starts directly after the stop character of the previous frame, no special character or filling ... So, after a few ConstructError at the start of the script (some kind of synchronisation time) the "process" is in sync and the frames are received and parsed without any error. That's what I found out ...

dstrigl commented 2 years ago

Hi Tore,

any plan to include my requested feature?

I am running it on a RPi since several months without any problem. I am reading the values every 5s from the smart meter and writing it into an InfluxDB.

Works fine so far :-)

dstrigl commented 1 year ago

Hi Tore,

have you ever thought about including my requested feature?

It runs without any problems since nearly a year ...

Regards, Daniel.