mweimerskirch / smarty_dsmr_proxy

This project is abandoned. I recommend using https://www.zuidwijk.com/product/slimmelezer-plus/
MIT License
20 stars 13 forks source link

ERROR: Invalid Tag #1

Open rthill opened 5 years ago

rthill commented 5 years ago

Finally found some time to play with the smarty smart meter, but I do receive an error most of the times I am starting the decrypt.py script. Sometimes when I start it displays the values in clear but like 7/10 times I get the error Invalid Tag.

ERROR: Invalid Tag.
Traceback (most recent call last):
  File "smarty.py", line 231, in <module>
    smarty_proxy.main()
  File "smarty.py", line 66, in main
    self.process()
  File "smarty.py", line 178, in process
    self.analyze()
  File "smarty.py", line 195, in analyze
    gcm_tag
  File "smarty.py", line 215, in decrypt
    return decryptor.update(payload) + decryptor.finalize()
  File "/opt/misc/lib64/python3.6/site-packages/cryptography/hazmat/primitives/ciphers/base.py", line 198, in finalize
    data = self._ctx.finalize()
  File "/opt/misc/lib64/python3.6/site-packages/cryptography/hazmat/backends/openssl/ciphers.py", line 170, in finalize
    raise InvalidTag
cryptography.exceptions.InvalidTag

Do you have an idea what the problem might be?

JeanMiK commented 5 years ago

This error code is thrown when the AES-GCM fails to authenticate the message.

Explication: Inside the SmartMeter, the payload (the telegram with the different readings from the meter) is encrypted with a key and with some initialization data (IV) which includes e.g. the frame number. The algorithm takes also an additional piece of data as input, the so-called AAD for 'Additional Authenticated Data'. The output of the algorithm is

The meter then sends a frame that contains in particular the IV, the cipher and the GCM tag, but not the AAD, which is kind of a shared secret between the meter and the user (but it is actually not secreat at all, as ist value is explicit in the specification: 30 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF).

When deccoding / decrypting, the system first computes the original text using the cipher text, the key and IV, In parallel, using the AAD that was also used by the encryption, the expected value of the GCM tag is computed.

In the end, the expected GCM tag is compared to the actual one found in the frame. If they don't match, one gets the exception that you observed.

It means that either the key is incorrect, the frame is corrupt or incorrect AAD got provided.

If you sometimes get correct data, the key must be correct. The AAD is a known constant in our case, so the most likely source of the problem is an unreliable transmission channel: your data gets corrupted from the meter to the decrypting device.

Check you cabling.

Some crypto libraries allow to retrieve the decrypted text without validating the AAD / GCM tag Consistency, but not the python library used by this project. But this would anyways only help if the corruption was to occur only in the last bytes of the frame containing the GCM tag.

haklein commented 3 years ago

I have the same issue with a SAGEMCOM T210-d. Apparently it's not using the well known AAD, the validation fails (not only with this project, also with schopenhauer/sage and with my own code based on Cryptodome). First I did assume I got a wrong key, but it is the right one (called GUEK_SM_CI_128) and I'm successfully able to decipher with the following code:

from Cryptodome.Cipher import AES
cipher = AES.new(key, AES.MODE_GCM, iv, mac_len=12)
cipher.update(additional_data)
decryption = cipher.decrypt(payload)