Die folgenden Kommandos sind bei der Analyse der signierten PGP-Nachricht nützlich.
# Kopieren aus dem PDF-Dokument (Adobe-Reader) oder einem OCR-Scan
cat > signedDocument.pgp
# Öffentlichen Schlüssel aus vertrauenswürdiger Quelle herunterladen
curl --output 9F7A3119DF9110EB.asc https://keys.openpgp.org/vks/v1/by-fingerprint/222E67EA2AA253A967408ABE9F7A3119DF9110EB
gpg --import 9F7A3119DF9110EB.asc
# Verifikation mit Warnung
gpg --verify signedDocument.pgp
# Ergänzen der Leerzeile
sed -i '1G' signedDocument.pgp
# Verifikation ohne Warnung
gpg --verify signedDocument.pgp
Erhält man bei der Signaturprüfung noch die Warnung
gpg: WARNING: This key is not certified with a trusted signature!
gpg: There is no indication that the signature belongs to the owner.
so könnte eine Tasse im Frühstücksraum der Fachschaft einen weiteren verläßlichen Hinweis liefern.
# Prüfen des signierten elektronischen Dokuments und zugleich Extrahieren der signierten Datei
gpg --output signedDocument.tex --yes --verify signedDocument.pgp
# Extraktion der Binärdaten aus der PGP-Nachricht
sed '/^[-=]/d;' signedDocument.pgp | base64 -d > signedDocument.bin
# Tag- (0xA3 = compressed) und Algorithmus-Byte (0x02 = zlib) auslesen
xxd -p -l2 -u signedDocument.bin
# Dekomprimieren nach RFC 1950 mit zpipe aus http://zlib.net/zlib-1.2.11.tar.gz
# cd /opt/zlib-1.2.11; ./configure; make; make install; cd examples; gcc zpipe.c -o zpipe -lz
tail -c+3 signedDocument.bin | /opt/zlib-1.2.11/examples/zpipe -d > signedDocument.dec
# Anzeigen der drei PGP-Pakete mit den Längen der Pakete
gpg -v --list-packets signedDocument.dec
# Extrahieren der signierten Rohdaten aus dem PGP-Paket (die Werte ergeben sich aus den Paket-Längen)
raw=$( gpg -v --list-packets signedDocument.dec | sed '/raw data:/!d;s/[^0-9]//g' )
tail -c+51 signedDocument.dec | head -c $raw > dtbs.bin
# Vergleich des extrahierten Dokuments mit den Rohdaten
diff -s signedDocument.tex dtbs.bin
# dtbs.bin durch die signierten Attribute aus dem Signaturpaket und
# den Trailer mit der Längeninformation ergänzen
sed 's/:.*//' << EOF | xxd -p -r >> dtbs.bin
04 00 13 08 : info bytes
001D : length bytes
16 21 04 222e67ea2aa253a967408abe9f7a3119df9110eb : signed attribute: the fingerprint
05 02 5f214fd2 : signed attribute: the signature creation time
04ff 00000023 : v4 trailer and length info
EOF
# Berechnen des SHA256-Hashwertes der data-to-be-signed
openssl sha256 -binary dtbs.bin > dtbs.hash
xxd -p -c32 dtbs.hash
# Öffentlichen Schlüssel eg.pub im ASN.1-Format erstellen
xxd -p -r <<< '3059301306072a8648ce3d020106082a8648ce3d030107034200' > eg.bin
sed '/^[-=]/d' 9F7A3119DF9110EB.asc | base64 -d | tail -c +20 | head -c65 >> eg.bin
openssl ec -inform der -pubin -in eg.bin -out eg.pub
# Vergleich der EC-Schlüssel im OpenPGP- und ASN.1-Format
gpg -v --list-packets 9F7A3119DF9110EB.asc | sed '/keyid/q'
openssl ec -text -noout -in eg.pub -pubin
gpg -v --list-packets 9F7A3119DF9110EB.asc | sed -n '/keyid/{g;s/.* //;p;q};h'
openssl ec -text -noout -in eg.pub -pubin 2>&1 | sed -n '/^ /H;${g;s/[ :\n]//g;s/[a-f]/\U&/g;p}'
# Rekonstruktion der Signatur (r,s) im ASN.1-Format aus der OpenPGP-Signatur
r=$( gpg -v --list-packets signedDocument.dec | sed 'h;N;$!d;x;s/.* //' )
s=$( gpg -v --list-packets signedDocument.dec | sed -n '${s/.* //;p}' )
# führende Null-Bytes sind nicht erforderlich, da die jeweiligen oberen Bit bei r und s nicht gesetzt sind
xxd -p -r <<< "30440220"$r"0220"$s > dtbs.sig
# rekonstruierte ASN.1-Signatur anzeigen und vergleichen
openssl asn1parse -i -inform der -in dtbs.sig
gpg -v --list-packets signedDocument.pgp | sed '1,/ctb=88/d'
# Verifikation der Signatur mit OpenSSL
openssl dgst -verify eg.pub -sha256 -signature dtbs.sig dtbs.bin
# PDF-Dokument aus dem elektronischen Dokument erstellen
pdflatex signedDocument.tex
# Logo-Datei nachladen und umbenennen
curl --output Huberlin-logo.png https://upload.wikimedia.org/wikipedia/commons/thumb/c/ce/Huberlin-logo.svg/240px-Huberlin-logo.svg.png
# Finales PDF-Dokument erstellen
pdflatex signedDocument.tex
Bei meinen Gutachten unterscheiden sich das aus dem base64-kodierten Text wieder erstellte lesbare signierte Dokument und das ursprüngliche PDF-Dokument nicht. Bei dem hier vorliegenden Dokument ist das ein wenig anders, denn schließlich nimmt das PDF auf der letzten Seite Bezug auf die konkreten Signaturdaten des bereits signierten PDF-Dokuments, die ja natürlich erst nach dem Signieren ins PDF übernommen werden konnten. Trotzdem habe ich mich bemüht, die Unterschiede so gering wie möglich zu halten. Man kann dazu die beiden PDF-Dokumente, das ursprüngliche ElektronischeGutachten.pdf und neu erzeugte signedDocument.pdf, miteinander vergleichen. Für mich war aber der Vergleich der beiden Quelltexte einfacher:
--- signedDocument.tex 2020-07-29 12:29:10.724178400 +0200
+++ ElektronischeGutachten.tex 2020-07-29 12:35:42.697152800 +0200
@@ -171,2 +171,2 @@
- data: 5C9AED534884C0707F92B75E3CECA6A74E2B3E7E01E0C6E34878E25BE1265032
- data: 5634C700FE38D1DFA826D22544617!EG!F1A184A2F2B8E816691C150F8C940FC
+ data: 5CE3EC00779E117EB08FCC6EA9AEA8B695AA82BF1189591A5B77DC211CB7459D
+ data: 5025C0FB23E4E9308DDF3FFE31E99019F7CFC13B525972D7F0E97B8F86C50110
@@ -200,2 +200,2 @@
-% 00ff 5c9aed534884c0707f92b75e3ceca6a74e2b3e7e01e0c6e34878e25be1265032
-% 00ff 5634c700fe38d1dfa826d22544617feb7f1a184a2f2b8e816691c150f8c940fc
+% 00ff 5ce3ec00779e117eb08fcc6ea9aea8b695aa82bf1189591a5b77dc211cb7459d
+% 00ff 5025c0fb23e4e9308ddf3ffe31e99019f7cfc13b525972d7f0e97b8f86c50110
@@ -228 +228 @@
- 6835268e692e5b03a805a657c47de9be3264af0a45438dfaaa60d49e84c0c264
+ 68353b221095706cf3ec4633fadcc5dab3b25f9062bea89f33777954aa682960
Wie man sieht, sind sogar die beiden oberen Bytes der Hashwerte der beiden Quelltexte gleich. Aber ansonsten unterscheiden sie sich nur in den Signaturdaten und im Rest des Hash-Werts. Hätte man in der Beschreibung auf die konkreten Werte verzichtet, wäre nur noch ein Unterschied in den extern nachzuladenden Logos vorhanden.
Ach ja, und natürlich auch im zusätzlich integrierten MP3 des Morse-Codes, das aber für den Inhalt des Artikels keine weitere Bedeutung hat, da sich die entsprechende Kodierung als Kommentar auch im signierten LaTeX-Quelltext befindet.