Forum: Mikrocontroller und Digitale Elektronik Frage zu AES128 CBC Decryption


von Roderik (Gast)


Lesenswert?

Hallo Forum,

ich habe hier etwas, das funktioniert - ich denke das ist auch in 
Ordnung so, ich habe allerdings noch nicht verstanden warum:

Ich übertrage 16 (IV) + 32768 (Daten) Bytes via WLAN von einem PC auf 
einen ESP8266. Die Daten wurden vorher mittels AES128 CBC in python 
symmetrisch verschlüsselt (ich spare mir hier mal den Code drumherum):
1
from Crypto.Cipher import AES
2
3
cipher = AES.new(KEY, AES.MODE_CBC,IV)
4
data_enc = cipher.encrypt(data_dec) # data_dec: 32768 sized byte array

IV und data_enc werden übertragen und sowohl der ESP8266 als auch der PC 
kennen den KEY. Der Datenblock wird dann auf dem ESP entschlüsselt. Da 
hier der RAM limitiert ist und zu wenig Speicher für die ver- und 
entschlüsselten Daten gleichzeitig vorhanden ist, habe ich dies 
"Chunk-weise" (2048 Byte-Blöcke) mittels einer union umgesetzt:
1
#pragma pack(1)
2
union crypto_data {
3
  uint8_t full[32768+2048];
4
  char chunks_dec[17][2048];
5
  byte chunks_enc[17][2048];
6
};
7
8
union crypto_data data;

data_enc liegt nach dem Transfer in Element 2048 bis 32768+2048 von 
epd_data.full und wird dann nach der Entschlüsselung um 2048 bytes 
versetzt ab  Anfang des Speicherbereichs der union geschrieben 
(Kurzcode):
1
#include <AESLib.h>
2
AESLib aesLib;
3
4
for (uint8_t i = 0; i<17; i++){
5
  dec_bytes = aesLib.decrypt(&data.chunks_enc[i+1][0], 2048,  &data.chunks_dec[i][0], KEY, 16, iv);
6
}

Verwendet wird die in Arduino verfügbare AESLib 
(https://github.com/suculent/thinx-aes-lib).
Die so erhaltenen Daten (Byte 0 - 32768 in data.full) entsprechen den 
unverschlüsselten Ausgangsdaten auf dem PC.

Nach meinem Verständis hängen durch die Verschlüsselung mittels AES128 
CBC der Inhalt der verschlüsselten Blöcke (16 bytes(?)) immer von den 
jeweils vorangegangenen Blöcken ab. Wieso war es dann möglich 
(erfolgreich) chunk-weise zu entschlüsseln?

Ich habe gelesen, dass eine parallelisierte *Ent*schlüsselung von AES128 
CBC möglich ist, was ja vermutlich auch das "Ansetzen" an verschiedenen 
Stellen der verschlüsselten Daten notwendig macht.

Wie kann aesLib.decrypt den ersten Block eines Chunks entschlüsseln, 
ohne den vorangegangenen Block zu kennen? Hat jemand hier eine kurze 
(ohne an dieser Stelle den kompletten Algorithmus auseinanderzunehmen) 
Erklärung für mich? Das wäre toll! Ist die Chunk-Größe egal?


Danke!

von Hmmm (Gast)


Lesenswert?

Roderik schrieb:
> Nach meinem Verständis hängen durch die Verschlüsselung mittels AES128
> CBC der Inhalt der verschlüsselten Blöcke (16 bytes(?)) immer von den
> jeweils vorangegangenen Blöcken ab. Wieso war es dann möglich
> (erfolgreich) chunk-weise zu entschlüsseln?

Der Plaintext des jeweiligen Blocks wurde bei AES-CBC vor der 
Verschlüsselung mit dem Ciphertext des vorigen Blocks XORed, beim ersten 
Block wurde für den gleichen Zweck der IV verwendet.

Die Library überschreibt daher nach der Entschlüsselung eines Blocks den 
IV mit dem Ciphertext, siehe Zeile 449 von AES.cpp.

von Roderik (Gast)


Lesenswert?

Hi!

Vielen Dank für die schnelle Hilfe, ich habe Line 449 angeguckt und das 
erklärt es dann. :) Also geht es soweit ich es sehe mit der 
entspechenden Library, mit Chunks deren Länge ein Vielfaches der 
Blockgröße ist, und wenn die Reihenfolge der Chunks beibehalten wird. 
Wollte ich das ganze parallelisieren müsste ich den letzten 16 byte 
Block der vorangegangenen Chunk als IV für den Anfang der nächsten 
nutzen, korrekt?

Mein ursprünglicher Plan war die Daten vor der Übertragung im 
python-Client auch chunk-weise (mit dem gleichen IV) zu verschlüsseln. 
Das hatte ich dann aber vergessen anzupassen und war dann im nachhinein 
sehr verwundert, dass es trotzdem funktionierte. Ich nehme an, dass es 
so sogar besser ist, wenn der großen Datenblock mit Nutzung des IV am 
Anfang in einem verschlüsselt wird (um Muster im Cipher zu vermeiden, 
wenn chunk-weise auf Basis des IV verschlüsselt wird(?)).

von Hmmm (Gast)


Lesenswert?

Roderik schrieb:
> Wollte ich das ganze parallelisieren müsste ich den letzten 16 byte
> Block der vorangegangenen Chunk als IV für den Anfang der nächsten
> nutzen, korrekt?

Genau, beim Entschlüsseln reicht es, jeweils den aktuellen und den 
vorigen Block (bzw. im Fall des ersten Blocks den IV) zu haben.

Roderik schrieb:
> Mein ursprünglicher Plan war die Daten vor der Übertragung im
> python-Client auch chunk-weise (mit dem gleichen IV) zu verschlüsseln.

Keine gute Idee, das ist dann quasi AES-ECB, bloss mit zusätzlichem XOR 
mit einem bekannten Key.

Das sorgt dafür, dass identische Plaintext-Blöcke (z.B. 0x00 oder 0xff) 
auch einen identischen Ciphertext haben.

Du musst bei AES-CBC schon der Reihe nach verschlüsseln. Wenn das o.g. 
Problem für Dich nicht relevant ist, kannst Du auch AES-ECB nehmen und 
ersparst Dir den IV.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.