Wie benutze ich GnuPG, um die kleinstmögliche Ausgabe zu erhalten (symmetrische Verschlüsselung)?

720
Daan Bakker

Ich versuche, sehr kleine, mit OpenPGP verschlüsselte Dateien zu erzeugen, die in QR-Codes eingebettet werden können.

Im Vergleich zu beispielsweise OpenSSL scheint GnuPG jedoch sehr große Ergebnisse für eine einfache Eingabe von 'a' zu erzeugen:

$ echo -n a|openssl enc -aes-256-ctr|wc -c  17 $ echo -n a|gpg --symmetric -o-|wc -c 71 

Beim Lesen des Handbuchs besteht einer der Unterschiede darin, dass OpenSSL standardmäßig nur einen 8-Byte-Header und einen 8-Byte-Salt enthält, während GnuPG auch ein Salt, Prüfsummen und Komprimierung enthält. Wenn diese deaktiviert sind, ist die Dateigröße niedriger, aber immer noch hoch:

$ echo -n a|gpg --symmetric --compress-algo none --disable-mdc --s2k-mode 0 -o-|wc -c 35 

Gibt es eine Möglichkeit, die OpenPGP-verschlüsselte Nachricht noch weiter zu optimieren (während AES aktiviert bleibt)?

5

1 Antwort auf die Frage

6
Jens Erat

Das binäre Format von GnuPG ist zwar platzsparend, es ist jedoch auf Flexibilität ausgelegt, nicht auf absolut minimale Nachrichtengrößen (normalerweise ist die eigentliche Nachricht viel größer als einige Bytes). Die minimale "übliche" OpenPGP-Nachricht ist 31 Bytes groß, aber Sie können immer noch mit etwas zusätzlichem Aufwand auf 26 Bytes reduzieren, was die kleinste mögliche OpenPGP v4-Nachricht für Einzelbyte-Inhalte ist.

Eine OpenPGP-Nachricht zerlegen, Bytes zählen

Wenn Sie sich RFC 4880 ansehen, können Sie eine minimale Länge einer Nachricht ableiten, die Sie nicht unterschreiten dürfen.

Schauen wir uns die Ausgabe des von Ihnen erstellten Befehls an:

$ echo -n a|gpg --symmetric --compress-algo none --disable-mdc --s2k-mode 0 -o-|gpg --list-packets gpg: Note: simple S2K mode (0) is strongly discouraged gpg: AES encrypted data gpg: encrypted with 1 passphrase gpg: WARNING: message was not integrity protected 

Das erste Paket ist ein mit einem symmetrischen Schlüssel verschlüsseltes Sitzungsschlüsselpaket . Es enthält eine Kopie des Sitzungsschlüssels, verschlüsselt durch die Passphrase unter Verwendung der String-to-Key-Mechanik. OpenSSL tut dies nicht, aber Sie können dies nicht überspringen, wenn Sie nicht den Passphrase, sondern den Sitzungsschlüssel angeben und den Sitzungsschlüssel separat angeben (siehe unten). Dieses Paket ist sechs Byte groß und besteht aus:

# off=0 ctb=8c tag=3 hlen=2 plen=4 :symkey enc packet: version 4, cipher 7, s2k 0, hash 10 

Nun beginnen die verschlüsselten Datenpakete. Es beinhaltet:

  • 2 Byte Paketkopf (Tag und Länge)
  • Zufälliges Präfix mit 18 Bytes (anstelle von 0 Bytes IV verwendet OpenPGP CFB ein zufälliges Präfix in der Größe des Chiffrierblocks und wiederholt die ersten beiden Bytes; AES verwendet 128 Bits = 16 Bytes als Chipherblocklänge.)
# off=6 ctb=c9 tag=9 hlen=2 plen=26 new-ctb :encrypted data packet: length: 26 

OpenPGP speichert die Nachricht immer in einem literalen Datenpaket, wodurch einige Metadaten hinzugefügt werden. Durch das Deaktivieren der Komprimierung werden zumindest die zusätzlichen Komprimierungsheader entfernt. Dieses Paket fügt schließlich weitere 9 Bytes hinzu:

  • 2 Byte Paketkopf (Tag und Länge)
  • 1 Byte Datenformat
  • 1 Byte Dateinamen-Stringlänge (Wert Null, kein Dateiname folgt)
  • 4 Byte Zeitstempel
  • 1 Byte Inhalt
# off=26 ctb=cb tag=11 hlen=2 plen=6 new-ctb :literal data packet: mode b (62), created 1503680075, name="", raw data: 0 bytes 

Zum Schluss: Sie können kein einzelnes weiteres Byte speichern - es sei denn, Sie lassen die String-to-Key-Ableitung weg und verwenden direkt den Sitzungsschlüssel anstelle einer Passphrase.

Die String-to-Key-Funktion auslassen

GnuPG ermöglicht das Lesen und Einstellen des Sitzungsschlüssels mit --show-session-keyund --override-session-key. Beim Lesen des Kapitels zur Nachrichtenzusammensetzung war ich tatsächlich überrascht, dass gültige OpenPGP-Nachrichten überhaupt kein Paket erfordern, das die Verschlüsselung des Sitzungsschlüssels definiert. GnuPG unterstützt zwar diese Art der Operation, aber ich würde nicht auf andere Implementierungen setzen, da dies eine sehr esoterische Art ist, OpenPGP zu verwenden.

 OpenPGP Message :- Encrypted Message | Signed Message | Compressed Message | Literal Message. Encrypted Message :- Encrypted Data | ESK Sequence, Encrypted Data. Encrypted Data :- Symmetrically Encrypted Data Packet | Symmetrically Encrypted Integrity Protected Data Packet 

Dadurch sollten die 6 Bytes des mit einem symmetrischen Schlüssel verschlüsselten Sitzungsschlüsselpakets gespeichert werden.

Erstellen einer OpenPGP-Nachricht ohne mit Symmetric-Key verschlüsseltes Sitzungsschlüsselpaket

Ich habe keinen Weg gefunden, GnuPG dazu zu bringen, einen vordefinierten Sitzungsschlüssel zu verwenden. Sie können jedoch eine symmetrisch verschlüsselte Nachricht generieren, den Sitzungsschlüssel während der Entschlüsselung extrahieren und dann die Nachricht aufteilen.

Nachricht verschlüsseln:

$ echo -n a|gpg --symmetric --compress-algo none --disable-mdc --s2k-mode 0 -o message.gpg 

Extrahieren des Sitzungsschlüssels (fragt nach der Passphrase):

$ gpg --show-session-key 0 --decrypt message.gpg gpg: AES encrypted data gpg: encrypted with 1 passphrase gpg: session key: '7:F7FBBA6E0636F890E56FBBF3283E524C' agpg: WARNING: message was not integrity protected 

Teilen Sie die OpenPGP-Nachricht in einzelne Pakete auf:

$ gpgsplit message.gpg 

Der Ordner enthält jetzt vier Dateien: das verschlüsselte message.gpg, das unverschlüsselte message, das mit dem symmetrischen Schlüssel verschlüsselte Sitzungsschlüsselpaket 000001-003.sym_encund schließlich das verschlüsselte Datenpaket 000002-009.encrypted.

$ ls -l total 16 -rw-r--r-- 1 jenserat jenserat 6 Aug 25 19:36 000001-003.sym_enc -rw-r--r-- 1 jenserat jenserat 29 Aug 25 19:36 000002-009.encrypted -rw-r--r-- 1 jenserat jenserat 1 Aug 25 19:04 message -rw-r--r-- 1 jenserat jenserat 35 Aug 25 19:33 message.gpg 

Sie können auch catdie einzelnen Paketdateien konfigurieren, um zurück zu gelangen message.gpg- diese beiden Dateien sind nur Teile davon message.gpg. Beachten Sie die Dateigrößen, die genau den oben diskutierten Größen entsprechen (während natürlich die Größe des literalen Datenpakets im verschlüsselten Datenpaket enthalten ist, da gpgsplitdie Passphrase nicht bekannt ist)!

Entschlüsseln eines separaten verschlüsselten Datenpakets

Dieser Schritt ist ziemlich einfach:

$ gpg --override-session-key '7:F7FBBA6E0636F890E56FBBF3283E524C' --decrypt 000002-009.encrypted  agpg: WARNING: message was not integrity protected 

Übersehen Sie nicht die avor der Warnmeldung, die die Ausgabe ist.

Bedeutung der Warnmeldungen

GnuPG druckte zwei Warnmeldungen.

gpg: Hinweis: Der einfache S2K-Modus (0) wird dringend empfohlen

Dies liegt daran, dass der einfache S2K-Modus Brute-Force- und Wörterbuch-Angriffe auf die Passphrase kostengünstig und einfach macht, da kein Hashing und kein Salz verwendet wird.

Letzteres ermöglicht natürlich die Verwendung desselben Sitzungsschlüssels für mehrere Dateien, die mit derselben Passphrase verschlüsselt sind. Beachten Sie jedoch die Konsequenzen.

gpg: WARNUNG: Die Nachricht wurde nicht vor Integrität geschützt

Diese Warnmeldung weist darauf hin, dass die Nachricht möglicherweise von einem Angreifer geändert wurde, ohne dass der entschlüsselnde Teilnehmer davon Kenntnis nehmen kann. Dies liegt an --disable-mdc-, das natürlich einige Bytes für die verschlüsselte Prüfsumme der Datei speichert. Sie können es selbst ausprobieren, indem Sie das letzte Byte in einem Hex-Editor ändern.