ich versuche mit Java, Daten aus Geräten (Zähler im OMS (Open Metering System)) zu entschlüsseln. Verschlüsselt sind die Daten mit AES 128 CBC FIPS 197.
Auf der Webseite https://www.miller-alex.de/WMbus ist die Entschlüsselung zum Testen implementiert. Auf dieser Seite lassen sich meine Daten entschlüsseln. Also, habe ich den richtigen AES Schlüssel für die Daten und ich sehe u.a. einen IV.
Mein Implementierungsversuch findet man bei https://github.com/bitkorn/aes-java/tree/main/de/bitkorn/aes. Es gibt eine Main.java und eine AES.java. Die Entschlüsselung ist in der AES.java. Implementierungen im Netz (und ChatGPT) machen es genau wie ich. Leider gibt mir meine Implementierung nur unleserliche Zeichen zurück.
Bei AES 128 CBC FIPS 197 werden mehrere Entschlüsselungs-Runden gemacht. Und der IV für den nächsten Block wird aus dem vorigen Block erzeugt usw. usw.. Das sollte doch die Java Funktion (javax.crypto.Cipher() => doFinal(byte[] input)) übernehmen, oder? Oder, muss ich die Runden implementieren? Wie entschlüsselt man solche Daten?
Kann mir jemand weiter helfen? Wo habe ich den Denkfehler?
Um die Korrektheit einer Ver-/Entschlüsselungs-Software nachzuweisen, benutzt man üblicherweise Testdaten. Ich bin mir sehr sicher, daß der FIPS 197 Standard derartige Testdaten enthält.
Um die Korrektheit einer Ver-/Entschlüsselungs-Software nachzuweisen,
benutzt man üblicherweise Testdaten. Ich bin mir sehr sicher, daß der
FIPS 197 Standard derartige Testdaten enthält.
Hallo Axel,
Testdaten habe ich bereits. Wie oben geschrieben, habe ich Daten inklusive dem AES Schlüssel, die mit anderer Software (https://www.miller-alex.de/WMbus) entschlüsselt werden kann.
Jetzt findet man in dem Repository einen Datenbank Dump mit Testdaten.
Z.B. für die Device ID 00945301 (AES Key: 9876543210FEDCBA9876543210FEDCBA) wären die ersten verschlüsselten Daten:
5E44A8340153940081087A034050050CBE58A7DBF052E98AC2122D5C7A74C4F6A8D9EA3A5BC709FA67012FB8B4CF5DB7EA294014FFD4F0CCEC210D78587C10F92648ACFF6EFF8A7E1301DD10923E9DA14F823C1B51C0ED5ABDB9DD9AD19BFBFF
Ich sehe momentan nicht wie sich Deine Daten auf https://www.miller-alex.de/WMbus entschlüsseln lassen. Da wird bei mir nur der unverschlüsselte Header der Daten angezeigt.
Wenn die Entschlüsselung klappt sollten dort auch die entschlüsselten Daten stehen (hinter "DECRYPTED", so wie mit dem Default-Beispiel), das passiert bei Deinen Daten nicht. Entweder stimmen Deine Daten nicht (warum steht z.B. ein 0xFF am Ende?) oder der Schlüssel ist falsch.
Nachtrag: Soll 9876543210FEDCBA9876543210FEDCBA tatsächlich ein individueller Schlüssel für den Smart Meter sein?
[Bin kein Java Programmierer - kenne die Sprache nur grob und die Libraries gar nicht.]
Ich vermute mal, dass die Cryptoroutinen bereits das Chaining machen (cipherType = "AES/CBC/NoPadding").
Allerdings bezweifel ich, dass aesKey.getBytes(StandardCharsets.UTF_8) korrekt sein kann: entweder ist der Key ein Hex-String, dann muß der nach Binary konvertiert werden, oder er ist bereits Binary, dann ist das UTF_8 verkehrt.
Mist, du hast Recht. Ich habe andere Daten, die auf der Seite einen Error produzieren. Da war ich mit diesen Daten wohl etwas schnell mit positivem Denken.
Individuell sind die AES Keys in meiner Datenbank alle nicht. Manche bestehen nur aus lauter großen 'F'.
Es scheint ein riesen Datenmüll Problem zu sein :(
Foobar schrieb:
Ich vermute mal, dass die Cryptoroutinen bereits das Chaining machen
(cipherType = "AES/CBC/NoPadding").
Allerdings bezweifel ich, dass aesKey.getBytes(StandardCharsets.UTF_8)
korrekt sein kann: entweder ist der Key ein Hex-String, dann muß der
nach Binary konvertiert werden, oder er ist bereits Binary, dann ist das
UTF_8 verkehrt.
Deine Aussage mit dem Chaining versüßt mir den Tag. U.a. habe ich auch in C++ die AES Implementierung mit diesen Chainings und XORS aus verschiedenen Quellen studiert. Darum bin ich schon sehr zufrieden, wenn die Funktion das Chaining etc schon macht.
Zu deiner anderen Aussage: SecretKeySpec hat nur Konstruktoren die den Key als byte[] erwarten. Und da braucht es eine Codierung. Die Funktion ohne Codierung aufrufen bringt den gleiche Müll raus.
Zusammengefasst scheinen die Daten Müll zu sein. Darum suche ich jetzt mittels der Webseite https://www.miller-alex.de/WMbus bei mir nach Daten die sich entschlüsseln lassen.
Zusammengefasst scheinen die Daten Müll zu sein. Darum suche ich jetzt
mittels der Webseite https://www.miller-alex.de/WMbus bei mir nach Daten
die sich entschlüsseln lassen.
Zum Testen Deiner AES Implementierung kannst Du ja das Default-Beispiel von der Webseite nehmen.
1
Key
2
F8B24F12F9D113F680BEE765FDE67EC0
3
4
IV
5
496A0392631400075050505050505050
6
7
Encrypted
8
98A78E0D71AA6358EEBD0B20BFDF99ED
9
A2D22FA25314F3F1B84470898E495303
10
923770BA8DDA97C964F0EA6CE24F5650
11
C0A6CDF3DE37DE33FBFBEBACE4009BB0
12
D8EBA2CBE80433FF131328206020B1BF
13
14
Dercrypted
15
2F2F0C1329730600026C942182046C81
16
218C0413754406008D0493132CFBFE12
17
44005141007035007733007549001636
18
00735600915500955700315700284200
19
18470061390056420002FD1700002F2F
Der "Encrypted" Teil ist bereits ohne den Header. Das funktioniert mit AES-CBC (No Padding), muss aber noch von Hexadezimal in die entsprechenden Bytes umgewandelt werden.
So wie du es schreibst, klingt es lustig, weil ich es als Hex mit
Garantie nicht lesen kann.
Die Telegramme sind aber nicht menschenlesbar. Bei der Entschlüsselung wird nicht "Die Temperatur beträgt 23,7°C" herauskommen, sondern eben ein Haufen Bytes, die noch durch einen Parser menschenlesbar gemacht werden müssen.
Die neuen Daten lassen sich auf jeden Fall korrekt entschlüsseln:
1
Key
2
B8AA9688DDD6528E86D8EEB45F866908
3
4
IV
5
C5250301101055084D4D4D4D4D4D4D4D
6
7
Encrypted
8
3F1EC0BB524BEEA88234B44D7D9F7888
9
010E24593CAD21E27CE9E15AD82E2152
10
35AB08041AC46F6E19B8BF8A0BCA6684
11
0E3B7288699BDB9F7E81A85F3152E761
12
61AEFEFCBF9F8F5A067161DBDF48D9EE
13
E7091DEAA6C7D78CEC1E5831E3372A98
14
15
Dercrypted
16
2F2F0B6E530400426EB80182016E8401
17
C2016E320182026ED800C2026E5E0082
18
036E8D01C2036E8D0182046E7401C204
19
6E740182056E4501C2056E430182066E
20
4301C2066E430182076E4301C2076E43
21
0182086EB800C2086E340002FD170000
Du mußt in Deinem Java Code die richtige Repräsentation der Bytes beachten, z.B. der Hex-String "ABCD" ist etwas anderes als die beiden Bytes 0xAB 0xCD.
Du mußt in Deinem Java Code die richtige Repräsentation der Bytes
beachten, z.B. der Hex-String "ABCD" ist etwas anderes als die beiden
Bytes 0xAB 0xCD.
Dass ich da irgendwo Murks mache, hatte ich schon mal vermutet.
Mein IV ist ein Hex String den ich per Java Funktion in Bytes wandle und dem IvParameterSpec Konstruktor übergebe. Sollte OK sein.
Mit dem AES Key verfahre ich gleich: hex String nach Bytes für den Konstruktor.
Mein decrypteter Hex String ist ein anderer als der, der bei miller-alex.de/WMbus raus kommt. Ist also Müll.
Kann man ja kaum was falsch machen. Mist, Mist, Mist. Vielleicht versuche ich es in einer Kirche ;)
Ich verwende normalerweise kein Java. Main.java ist nur mal schnell zusammengestrickt und soll nicht als Referenz für guten Stil dienen, liefert aber das gewünschte Ergebnis:
Woher wisst ihr und miller-alex.de/WMbus, dass der encryptete Teil bei
3F1EC0BB52... anfängt?
So steht es in der OMS Spezifikation. Wenn man sich auf der "Miller Alex" Web Seite den PDF Report erstellen läßt sieht man alle Details.
Und was mache ich mit dem Hex am Ende, ist das dann immer
herstellerabhängig?
Meinst Du das letzte 0xFF? Die verschlüsselte Nachricht kann nur ein vielfaches der AES Blocklänge sein (16 Byte), daraus ergibt sich dass 0xFF nicht zur verschlüsselten Nachricht gehört.
So steht es in der OMS Spezifikation. Wenn man sich auf der "Miller
Alex" Web Seite den PDF Report erstellen läßt sieht man alle Details.
Und was mache ich mit dem Hex am Ende, ist das dann immer
herstellerabhängig?
Meinst Du das letzte 0xFF? Die verschlüsselte Nachricht kann nur ein
vielfaches der AES Blocklänge sein (16 Byte), daraus ergibt sich dass
0xFF nicht zur verschlüsselten Nachricht gehört.
Jetzt sehe ich klar. Mir wurden lauter verschiedene Hersteller Dokumente gegeben, die zeigen wo welche Daten sind. U.a. ist in diesen Dokumenten der Start des encrypteten Teils unterschiedlich. Was mir dazu noch so alles erzählt wurde, will ich erst gar nicht dran denken.
Blocklänge ok, das verstehe ich :)
Denke jetzt bin ich durch: Mein Problem waren die hexToByte und ByteToHex Geschichten und ein riesen Berg Datenmüll gepaart mit Dünnpfiff Laberei.
Oft wird da nicht in Hex (bzw. Sedezimal) kodiert, sondern in BCD (die Serienummer zB. bei MBus).
Die Verschlüsselung ist auch nur "partial", d.h. da gibt es Records/Blöcke die verschlüsselt sind, enthalten meist die Messwerte (inkl. historischer Messwerte).
Status Informationen wie das MBus Status Byte sind nicht verschlüsselt (Sensor Daten).
Damit kann man zumindest sehen ob alles passt oder ob es Probleme gibt.
Oft wird da nicht in Hex (bzw. Sedezimal) kodiert, sondern in BCD (die
Serienummer zB. bei MBus).
...du meinst den unverschlüsselten Teil!?!?
Die Verschlüsselung ist auch nur "partial", d.h. da gibt es
Records/Blöcke die verschlüsselt sind, enthalten meist die Messwerte
(inkl. historischer Messwerte).
Status Informationen wie das MBus Status Byte sind nicht verschlüsselt
(Sensor Daten).
Damit kann man zumindest sehen ob alles passt oder ob es Probleme gibt.
Die unverschlüsselten Daten stehen immer am Anfang, oder?
Die unverschlüsselten Daten stehen immer am Anfang, oder?
Ich habe ja oben bereits auf die OMS Spezifikation verwiesen, da steht es drinnen. Und es gibt auch noch den "Annex N" dazu mit vielen Beispielen. Man muß wirklich nur mal reinschauen...