Code Monkey home page Code Monkey logo

Comments (19)

aldadic avatar aldadic commented on June 30, 2024

Hi @doli08!

I have never questioned how I got the mbedtls library in the Arduino IDE. It was simply available when I needed it, which is why I thought that this might be always the case. But it seems I was wrong on this assumption 😅. After a bit of googling I found out that the library was probably installed as a part of the Arduino core for the ESP32 (see here). Therefore I would suggest that you install the ESP32 board in your Arduino IDE by adding

https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json

as "Additional Board Manager URL".

from esp-smartmeter-reader.

leecher1337 avatar leecher1337 commented on June 30, 2024

Otherwise, crypto library should also work, I guess..

#include <AES.h>
#include <CTR.h>

    // Initialisation Vector zusammenbaun:
    uint8_t iv[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02};
    // 8 Bytes von 13 (=system-title)
    memcpy(&iv[0], fullData->sys_t, 8);
    // 4 Bytes von 23 (=nonce). INFO: Nonce wird bei jedem Paket um 1 größer (=increment counter)
    memcpy(&iv[8], &fullData->inv_cnt, 4);

    // Entschlüsseln
    uint8_t plainText[sizeof(fullData->data)];
    CTR<AES128> ctr;
    ctr.setKey(Key, sizeof(Key));
    ctr.setIV(iv, sizeof(iv));
    ctr.decrypt(plainText, (unsigned char*)&fullData->data, sizeof(fullData->data));

image

from esp-smartmeter-reader.

aldadic avatar aldadic commented on June 30, 2024

Thanks a lot for sharing @leecher1337! I was unfamiliar with that library. As soon as i have time i will try your code with an ESP8266 and probably update the repository accordingly.

from esp-smartmeter-reader.

curtosvienna avatar curtosvienna commented on June 30, 2024

first of all thank you for effort pushing this project to GH (!)

I am struggling loading the project to a Lolin Wemos D1 Mini (ESP 8266). I cannot activate the Mbedtls libary in the arduino IDE.

what I have tried (but not solved):

  • find the libary in the libary manager (not found the correct one, just "Seeed_Arduino_mbedtls"
  • install the mbedtls lib from github via zip file -> faulted
  • copy the unzipped folders to: install folder or to the project folder

error msg:

C:~~\SmartMeterSchnittstelle\esp32-smartmeter-reader-main\esp32-smartmeter-reader-main\esp32-smartmeter-reader\esp32-smartmeter-reader.ino:2:10: fatal error: mbedtls/aes.h: No such file or directory 2 | #include "mbedtls/aes.h" //=> not found :( | ^~~~~~~~~~~~~~~ compilation terminated.

exit status 1

Compilation error: mbedtls/aes.h: No such file or directory

Hallo @doli08 !

habe hier selbes Problem.
Hast du eine Lösung gefunden.?
stehe hier komplett an, komme nicht weiter

from esp-smartmeter-reader.

leecher1337 avatar leecher1337 commented on June 30, 2024

Hallo, ich hab meine eigene Variante von dem Code geschrieben. Soll ich sie auf Github stellen?
Ich konnte sie nur noch nicht verifizieren, weil der Netzbetreiber mir wahrscheinlich den falschen Schlüssel geschickt hat o.Ä., jedenfalls kann ich die Pakete von meinem Smartmeter nicht entschlüsseln, aber in meinem Code selbst hab ich keinen Fehler gefunden.
Eigentlich wollte ich den erst online stellen, wenn ich ihn verifiziert habe, ob er auch funktioniert, aber das kann bei dem Netzbetreiber noch Monate dauern, bis der mal irgendwas macht, wenn er überhaupt was macht :(

from esp-smartmeter-reader.

curtosvienna avatar curtosvienna commented on June 30, 2024

Hallo @leecher1337,

ich hätte nichts dagegen. ;-) Dann könnte ich deine Version mit meinem Schlüssel testen ob es funktioniert und hier Rückmeldung geben.

from esp-smartmeter-reader.

aldadic avatar aldadic commented on June 30, 2024

Hi @curtosvienna!

Ich habe meinen Code mit der library, die @leecher1337 vorgeschlagen hat, umgeschrieben. Hier ist der Code:

https://gist.github.com/aldadic/31abea0001c0a231c59814a3e0c68146

Auf meinem ESP32 klappt es tadellos.

from esp-smartmeter-reader.

aldadic avatar aldadic commented on June 30, 2024

Update: Der Code läuft nun erfolgreich auf meinem ESP8266. Im obigen Code musste ich dafür noch die Wifi library ändern (#include <ESP8266WiFi.h> um genau zu sein; ich habe das GitHub gist entsprechend angepasst). Den Lesekopf habe ich wie folgt angeschlossen:

IR reader ESP8266
VCC 3.3V
GND GND
RX GPIO3 (RX)
TX GPIO1 (TX)

Im config.h musste ich daher die letzte Zeile zu

HardwareSerial *smart_meter = &Serial;

ändern. Ich würde mich freuen zu hören, ob das auch bei dir klappt @curtosvienna. Dann könnte ich das nämlich im repository entsprechend ergänzen.

from esp-smartmeter-reader.

curtosvienna avatar curtosvienna commented on June 30, 2024

from esp-smartmeter-reader.

curtosvienna avatar curtosvienna commented on June 30, 2024

Hallo @leecher1337 @aldadic @,

alles zusammengebaut, konfiguriert, ......
Funktioniert einwandfrei,
Daten werden an den MQTT Server übertragen.
MQTT werd ich mich noch spielen bzw. in influxdb schieben und in Grafana visualisieren
Danke für eure Hilfe.
falls noch von Interesse .... Hichie Lesekopf(Clon) > ESB8266NodeMCU > RaspberryPI4 > Mosquitto Broker
habe es auch mit einem Wemos ESP-Wroom-02 D1 Mini WiFi Module ESP8266 + 18650 mit Akku versucht, da ist aber die WLAN Verbindung nicht ausrreichend.

Grüße
Kurt

from esp-smartmeter-reader.

aldadic avatar aldadic commented on June 30, 2024

Super! Freut mich zu hören, dass der Code auch bei dir funktioniert @curtosvienna. Dann werde ich den Code bzw. die Anleitung im repository demnächst entsprechend aktualisieren.

from esp-smartmeter-reader.

leecher1337 avatar leecher1337 commented on June 30, 2024

Hallo @curtosvienna

Prima, dass es funzt! Was mich noch interessieren würde, weil ichs mit meinem Cryptoschlüssel ja nicht entschlüsseln kann:
Korrespondiert der SystemTitle eigentlich mit der Zählernummer im Portal (die Wiener Netze haben so ein Portal, da steht eine Zählernummer und da kann man sich auch den zugehörigen Cryptoschlüssel anzeigen lassen)?
Ich hab nen Landis&Gyr, da beginnt die Zählernummer mit LGZ... Und auch das SystemTitle beginnt so:

Beispiel:

0x4C,0x47,0x5A,0x68,0x71,0x69,0xA4,0x2A
L   ,G   ,Z   ,103 ,113 ,105 ,164 ,42

Aber die Nummer hinter dem LGZ passt nicht mit dem Zähler zusammen, von dem ich auslese, daher die Frage, ob das korrespondieren sollte?

from esp-smartmeter-reader.

curtosvienna avatar curtosvienna commented on June 30, 2024

from esp-smartmeter-reader.

leecher1337 avatar leecher1337 commented on June 30, 2024

Hallo @curtosvienna Ich meine nicht den Schlüssel, sondern den SystemTitle!
Also die ersten 8 Bytes, die Du in den IV kopierst.

from esp-smartmeter-reader.

aldadic avatar aldadic commented on June 30, 2024

@leecher1337 Ich habe mal bei mir nachgesehen. Bei mir beginnt der SystemTitle ebenfalls mit 0x4C, 0x47, 0x5A, 0x67. Die nächsten vier Stellen stimmen aber nicht mit der Zählernummer überein, die ich Smartmeter Portal sehe.

from esp-smartmeter-reader.

leecher1337 avatar leecher1337 commented on June 30, 2024

Danke, war bei mir auch so.
Ok, dann ist das auch kein Hinweis darauf, warum ich offensichtlich einen Schlüssel habe, der nicht richtig entschlüsselt.
Habe neben meiner eigenen Implementierung in C auch dieses Python-Script probiert: https://gist.github.com/pocki80/941fa090a8d6269a9b3b68c195f8750f
Kommt exakt dasselbe raus bei dem Python Script, Rahmen-Prüfsumme ist OK, Inhalt ist wirr.
Dann kann ich nur hoffen, dass die Wiener Netze rausfinden, warum mein Schlüssel nicht passt. :-(

from esp-smartmeter-reader.

curtosvienna avatar curtosvienna commented on June 30, 2024

Also ich gebe in der config.h folgendes ein:
const byte KEY[] = ( 0x2a, 0x47, 0xf8, 0xa4, 0x9d, 0xaa, 0x37…….
Das sind doch genau die Daten aus dem Schlüssel.
2a 47 f8 a4 9d aa 37 ( 2A47 F8A4 9DAA)

from esp-smartmeter-reader.

leecher1337 avatar leecher1337 commented on June 30, 2024

Ich auch, nur bei mir kommt eben dann Schrott :(
landis.c ist mein eigenes Entschlüssler, der dasselbe macht wie bei diesem Projekt hier und das og. Python-Script.

$ gcc -o landis -lssl landis.c
$ ./landis
Rahmen-Pruefsumme des Pakets ist gueltig
Entschluesseltes Datenpaket: 52 F6 AA ED 3F A6 C9 E6 C8 39 C5 91 EB D5 02 01 D9 C1 42 6A 54 76 BE E6 CB E5 A5 FF 82 DA B7 22 34 5F 93 9F F8 8E 45 8E CD 40 57 99 0B AC C4 A1 F8 EF 72 EB 01 36 0F E5 23 E7 6A 83 A1 80 4F EE 4A 9B 9A 8F D4 6B B9 2C 5E 4D

Entschluesselung fehlgeschlagen? Falscher Paketstart

Mir sieht das nach Schrott aus...

Mein Code, wenns wen interessiert:

//
// Smartmeter Datenpaket Entschluesselungs Testprogramm
//
#include <stdio.h>
#include <stdint.h>
#include <memory.h>
#include <openssl/aes.h>
#include <openssl/rand.h>
#include <openssl/hmac.h>
#include <openssl/buffer.h>

// Schluessel aus dem Kundenportal der Wiener Netze
uint8_t Key[16] = {0x30, 0xCF, 0x95, ....};

// Beispiel
unsigned char MBusData[] = {
	0x7E,
	0xA0,
	0x67,
	0xCE,
	0xFF,
	0x03,
	0x13,
	0x38,0xBD,
	0xE6,
	0xE7,
	0x00,
	0xDB,
	0x08,
	0x4C,0x47,0x5A,0x??,0x??,0x??,0x??,0x??,
	0x4F,
	0x20,
	0x00,0x20,0xE4,0x10,
	0x27,0xDE,0xCF,0x3D,0x4D,0x8D,0xA8,0x00,0xF3,0x20,0x6C,0x16,0x04,0xA0,0xEC,0x9B,0xB0,0x32,0x56,0x10,0x28,0x48,0x72,0x69,0xAF,0x53,0x05,0xE0,0x1A,0x9E,0x1E,0xE1,0x67,0x73,0xD9,0x7C,0x48,0xC5,0x83,0xF1,0x7F,0x7D,0x3D,0x8C,0xAC,0xDF,0x58,0x35,0x5A,0x8B,0x74,0xE8,0x54,0xFA,0xFB,0x37,0x53,0x9F,0xE5,0x2B,0x68,0x95,0xAE,0xBE,0x23,0x8A,0x71,0x0C,0x80,0xF0,0xC6,0xB5,0x60,0x6B,
	0x5D,0xBB,
	0x7E};

// Strukturen der Datenpakete
#pragma pack(1)
typedef uint32_t  TYP_PacketNumber;
typedef struct
{
    uint16_t Year;
    uint8_t Month;
    uint8_t Day;
    uint8_t DayOfWeek;
    uint8_t Hour;
    uint8_t Minute;
    uint8_t Second;
    uint32_t Unknown;
} TYP_TimeStamp;
typedef uint16_t TYP_Unk1;
typedef uint32_t TYP_32BitVal;
typedef uint8_t TYPID;

enum
{
    TYPID_Unk1 = 0x02,
    TYPID_32BitVal = 0x06,
    TYPID_TimeStamp = 0x0C,
    TYPID_PacketNumber = 0x0F
};

typedef struct
{
    TYPID Type;
    TYP_PacketNumber Data;
} DS_PacketNumber;

typedef struct
{
    TYPID Type;
    TYP_TimeStamp Data;
} DS_TimeStamp;

typedef struct
{
    TYPID Type;
    TYP_Unk1 Data;
} DS_Unk1;

typedef struct
{
    TYPID Type;
    TYP_32BitVal Data;
} DS_32BitVal;

// Variante 3
// https://oesterreichsenergie.at/fileadmin/user_upload/Smart_Meter-Plattform/20200201_Konzept_Kundenschnittstelle_SM.pdf
typedef struct
{
    DS_PacketNumber PacketNumber;
    DS_TimeStamp TimeStamp1;
    DS_Unk1 Unk1;
    DS_TimeStamp TimeStamp2;
    DS_32BitVal pA;    // Wirkenergie +A Wh
    DS_32BitVal nA;   // Wirkenergie -A Wh
    DS_32BitVal pR;   // Blindenergie +R varh
    DS_32BitVal nR;   // Blindenergie -R varh
    DS_32BitVal pP;   // Momentanleistung +P W
    DS_32BitVal nP;   // Momentanleistung -P W
    DS_32BitVal pQ;   // Momentanleistung +Q var
    DS_32BitVal nQ;   // Momentanleistung -Q var
} PAYLOAD_PACKET;

typedef struct {

    uint8_t flag;               // Opening flag (0x7E)
    uint8_t type;               // Frame format type
    uint8_t length;             // Length of packet
    uint8_t client_nr;          // Client number?
    uint8_t dst_address;        // Destination address
    uint8_t src_address;        // Source address
    uint8_t control;            // Control field
    uint16_t hcs;               // Header check sequence, CRC-16/X25 (Byte 2-7)
    uint8_t dst_lsap;           // Destination LSAP
    uint8_t src_lsap;           // Source LSAP
    uint8_t llc_quality;        // LLC quality
    uint8_t llc_sdu;            // LLC service data unit
    uint8_t len_sys_t;          // Length of system title
    uint8_t sys_t[8];           // System title
    uint8_t len_content;        // Length of ciphered content
    uint8_t sc_e;               // SC-E: bit 5=1 = Encryption only
    uint32_t inv_cnt;           // Invocation counter
    PAYLOAD_PACKET data;        // Crypted payload (74 bytes)
    uint16_t fcs;               // Frame check sequence
    uint8_t end;                // End flag (0x7E)
} DATA_FRAME;

#pragma pack()


//
// CRC validierung der Pakete
//
uint16_t HdlcCrcReflect(uint16_t crc, int bitnum)
{

  // reflects the lower 'bitnum' bits of 'crc'

  uint16_t i, j = 1, crcout = 0;

  for (i = (uint16_t)1 << (bitnum - 1); i; i >>= 1)
  {
    if (crc & i)
      crcout |= j;
    j <<= 1;
  }
  return (crcout);
}

#define order 16
#define polynom 0x1021
#define crcinit 0xffff
#define crcxor 0xffff

// http://www.zorc.breitbandkatze.de/crc.html
// http://www.zorc.breitbandkatze.de/crctester.c
uint16_t HdlcCrcBitByBit(unsigned char *p, uint16_t len)
{
  uint16_t crchighbit;
  uint16_t i, j, c, bit, crc;
  uint16_t crcmask;

  crcmask = ((((uint16_t)1 << (order - 1)) - 1) << 1) | 1;
  crchighbit = (uint16_t)1 << (order - 1);

  crc = crcinit;
  for (i = 0; i < order; i++)
  {

    bit = crc & 1;
    if (bit)
      crc ^= polynom;
    crc >>= 1;
    if (bit)
      crc |= crchighbit;
  }

  // bit by bit algorithm with augmented zero bytes.
  // does not use lookup table, suited for polynom orders between 1...32.

  for (i = 0; i < len; i++)
  {

    c = (uint16_t)*p++;
    c = HdlcCrcReflect(c, 8);

    for (j = 0x80; j; j >>= 1)
    {

      bit = crc & crchighbit;
      crc <<= 1;
      if (c & j)
        crc |= 1;
      if (bit)
        crc ^= polynom;
    }
  }

  for (i = 0; i < order; i++)
  {
    bit = crc & crchighbit;
    crc <<= 1;
    if (bit)
      crc ^= polynom;
  }

  crc = HdlcCrcReflect(crc, order);
  crc ^= crcxor;
  crc &= crcmask;

  return (crc);
}

int CheckValues(uint8_t *data, size_t dataSize)
{
  uint16_t crc = HdlcCrcBitByBit(data, dataSize - 2); // -2 because last 2 bytes are the checksum I have to compare it to
  uint8_t hiByte = (crc & 0xff00) >> 8;
  uint8_t loByte = (crc & 0xff);

  return hiByte == data[dataSize - 1] && loByte == data[dataSize - 2];
}




int main(int argc, char **argv)
{
	AES_KEY key;
	unsigned char ecount_buf[AES_BLOCK_SIZE] = {0};
	int num = 0;
	unsigned int i;
	DATA_FRAME *fullData = (DATA_FRAME*)MBusData;
    // Initialisation Vector zusammenbaun:
    uint8_t iv[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02};
    uint8_t plainText[sizeof(fullData->data)]={0};

	// Rahmen-CRC pruefen
	printf ("Rahmen-Pruefsumme des Pakets ist %s\n", (CheckValues((unsigned char*)&fullData->type, sizeof(DATA_FRAME)-2)?"gueltig":"UNGUELTIG!!!"));

    // 8 Bytes von 13 (=system-title)
    memcpy(&iv[0], fullData->sys_t, 8);
    // 4 Bytes von 23 (=nonce). INFO: Nonce wird bei jedem Paket um 1 groesser (=increment counter)
    memcpy(&iv[8], &fullData->inv_cnt, 4);

    // Entschluesseln
	AES_set_encrypt_key(Key, 128, &key);
    AES_ctr128_encrypt((unsigned char*)&fullData->data, plainText, sizeof(fullData->data), &key, iv, ecount_buf, &num);
	//memcpy(plainText, &fullData->data, sizeof(fullData->data));

	printf ("Entschluesseltes Datenpaket: ");
	for (i=0; i<sizeof(plainText); i++) printf ("%02X ", plainText[i]);
	printf("\n\n");

	if (fullData->data.PacketNumber.Type != TYPID_PacketNumber)
		fprintf(stderr, "Entschluesselung fehlgeschlagen? Falscher Paketstart\n");

} 

from esp-smartmeter-reader.

aldadic avatar aldadic commented on June 30, 2024

The changes from the GitHub gist were integrated into esp-smartmeter-reader.ino. This sketch now compiles for both ESP32 and ESP8266.

from esp-smartmeter-reader.

Related Issues (3)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.