Um einen gesicherten Datenaustausch in Web-Applikationen, gerade zunehmend auch im Kontext von IoT (Internet of Thins), zu gewährleisten gilt es, einige Dinge zu beachten. Anhand der von mir entwickelten Applikation "Interrogato", eine Lernplattform, die es erlaubt Möglichkeiten zu nutzen, ohne Kurse in sog, Klassenräumen wahrnehmen zu müssen (Distance Learning) , um sich auf Prüfungen vorbereiten zu können. Hierfür stellt der "Interrogator" via Web-Services Lernmodule zur Verfügung, in denen Multiple-Choice-Fragen hinterlegt sind. Im Nachfolgenden werden hier die notwendigen Sachverhalte für eine gesicherte Web-Kommunikatiuon skizziert.
Die Datenkommunikation zwischen der in HTML und JAVASCRIPT geschriebenen Web-Applikation und dem Web-Server erfolgt mithilfe der üblichen HTTP-Methode POST zustandslos, d.h. dass der Web-Server keinen Kontext resp. Zustand (z. B. mithilfe von Cookies)über die anwendungsbezogeneInteraktion mit der Web-Applikation, und basiert auf einer Rest(Representational State Transfer)-Architektur, die auch unter der Bezeichnung RESTful API bekannt ist. Der Web-Server stellt sog. Web-Services in Form von Servlets zur Disposition – der verwendete Begriff "Servlets" ist hier nicht als JAVA-Klassen zu verstehen, sondern repräsentiert kleine in PERL geschriebene serverseitige Anwendungsroutinen, die innerhalb des Webservers Anfragen vom Client entgegennehmen und beantworten.
HINWEIS: Für die Veranschaulichung der jeweiligen Sacheverhalte werden sog. Code-Schnipsel sowohl in Javascript als auch in Perl aufgeführt, die leicht, da ohne Berücksichtigung des entsprechenden Kontextes, modifiziert dem Original-Programmcode entnommen wurden. Diese Code-Schnipsel unterliegen dem Copyright by HK Businessconsulting, Hamburg (www.hk-businessconsulting.de) Sie können unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weitergeben und/oder modifizieren werden, entweder gemäß Version 3 der Lizenz oder jeder späteren Version. Die Veröffentlichung dieser Code-Schnipsel erfolgt in der Hoffnung, daß sie von Nutzen sein werden, aber OHNE IRGENDEINE GARANTIE, sogar ohne die implizite Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Details sind zufinden in der GNU Lesser General Public License (siehe http://www.gnu.org/licenses/)
Die verwendete Technik, die auf Seiten des Cient zur Anwendung kommt, ist ein spezielles Formular mit zwei INPUT-Feldern (s. setfield ) i. V. m. zwei Variablen, dem HEADER und PAYLOAD resp. Header und Payload, die zusammen den Daten-Frame ausmachen. Während HEADER der Aufnahme von Steuerungsinformationen dient, werden im Feld PAYLOAD die Nutzdaten hinterlegt. HEADER und PAYLOAD werden vor Versenden in eine Json-Format-Zeichenkette und dann einen Base64-Code (btoa), d.h. die 8-BitBinärdaten werden in eine Zeichenfolge, die nur aus lesbaren, Codepage-unabhängigen ASCII-Zeichen besteht, umgewandelt.
Das Formular wird via Browser an den Webserver über HTTP mit einer POST-Anforderung für die Datenressource /cgi-bin/servrogator.pl abgsendet. Der Webserver erkennt, dass es sich um ein sog. CGI-Script handelt, und führt es aus. Die in den Feldern des Formulars befindlichen Daten stehen dem CGI-Script zur Verarbeitung zur Verfügung.
Javascript Codeschnipsel:
// (c) HK Businessconsulting, Hamburg function setField (Form, Name) { var field = document.createElement("INPUT"); with (field) { type = "hidden"; value = ''; name = Name; } Form.appendChild(field); } var Form; with (document.body.appendChild(Form = document.createElement("FORM"))) { method = "POST"; enctype="multipart/form-data"; acceptCharset="utf-8"; // ISO-8859-1 ISO-8859-15 utf-8 acceptCharset="utf-8"; // utf-8 action = "/cgi-bin/servrogator.pl"; target = <Iframe-name> //The response is displayed in a named iframe; onsubmit=new Function('F',"return false;"); } setField (Form, 'HEADER'); setField (Form, 'PAYLOAD'); send = function(Header, Payload) { if (Header) { Header.value = btoa(Header,''); Payload.value = Payload ? btoa(Payload,'') : ''; Form.submit(); } else alert("Fatal Error"); }
Im Web-Server erfolgt die Datenübertragung auf ähnliche Art und Weise mit 2 Variablen ($Header und $Payload), nur dass hier anstelle des Formaulars eine generierte vom Client "angeforderte" HTML-Seite zur Anwendung kommt. Der Client resp. Browser empfängt die HTML-Seite und führt die via Formular an den Web-Server übergebene und die HTML-Seite eingebundene $Callee-Funktion aus, wodurch die Informationen im Header und Payload der Anwendung "Interrogator" zur Verfügung stehen.
Perl Codeschnipsel:
# (c) HK Businessconsulting, Hamburg sub sendFrame { my $cgi = CGI->new(); my ($Target, $Callee, $Header, $Payload) = @_; $Header = \encode_base64($Header,''); $$Payload = '' unless defined $Payload; $Payload = \encode_base64($$Payload,''); $| = 1; # flushes buffer STDOUT immediately print $cgi->header(-type=>'text/html',-expires=>'now'), $cgi->start_html( -dtd => '-//W3C//DTD HTML 4.01 Transitional//EN', -encoding => 'utf-8', -target => $Target, ); print <<ENDSCRIPT; ENDSCRIPT print $cgi->end_html; $| = 0; }
Für den symmetrisch Ende-zu-Ende-verschlüsselten Datenaustausch zwischen der im Browser laufenden Anwendungsinstanz "Interrogator" und der die Servlets bereitstellenden Instanz auf dem Web-Server "Servrogator" wird eine Verbindung resp. Sitzung zwischen Interrogator und Servrogator etabliert und anhand des sog.Diffie-Hellman-Schlüsselaustauschprotokolls, über das der für eine sichere Kommunikation geheime Sitzungsschlüssel vereinbart wird. Eine Ende-zu-Ende-Verschlüsselung wurde hier gewählt, da nicht immer eine auf Transport- resp. Netzwerkebene zugrundeliegende Verschlüsselung der Daten mittels SSL/TLS (Secure Sockets Layer/Transport Layer Security) durch Verwendung von z. B. HTTPS (Hypertext Transfer Protocol Secure) gegeben ist (z. B. in einem Intranet). Die Kommunikation zwischen Interrogator als Dienstbenutzer und Servrogator als Diensterbringer ist in der nachfolgenden Graphik mittels eines Ort-Zeit-Diagrammes und den Dienstprimitiven (auch Dienstelemente genannt) in Anlehnung an OSI (Open System Interconnection; s.auch ITU-T Recommendations X.210 ):
Hierfür ist eine nicht unbedingt geheime, aber sehr große Primzahl p identisch auf beiden Seiten (Interrogator und Servrogator) zu wählen. Gem. RFC3526 wird eine 6144 Bit große Primzahl p folgendermaßen bestimmt:
FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245 E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F 83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D 670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9 DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510 15728E5A 8AAAC42D AD33170D 04507A33 A85521AB DF1CBA64 ECFB8504 58DBEF0A 8AEA7157 5D060C7D B3970F85 A6E1E4C7 ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226 1AD2EE6B F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31 43DB5BFC E0FD108E 4B82D120 A9210801 1A723C12 A787E6D7 88719A10 BDBA5B26 99C32718 6AF4E23C 1A946834 B6150BDA 2583E9CA 2AD44CE8 DBBBC2DB 04DE8EF9 2E8EFC14 1FBECAA6 287C5947 4E6BC05D 99B2964F A090C3A2 233BA186 515BE7ED 1F612970 CEE2D7AF B81BDD76 2170481C D0069127 D5B05AA9 93B4EA98 8D8FDDC1 86FFB7DC 90A6C08F 4DF435C9 34028492 36C3FAB4 D27C7026 C1D4DCB2 602646DE C9751E76 3DBA37BD F8FF9406 AD9E530E E5DB382F 413001AE B06A53ED 9027D831 179727B0 865A8918 DA3EDBEB CF9B14ED 44CE6CBA CED4BB1B DB7F1447 E6CC254B 33205151 2BD7AF42 6FB8F401 378CD2BF 5983CA01 C64B92EC F032EA15 D1721D03 F482D7CE 6E74FEF6 D55E702F 46980C82 B5A84031 900B1C9E 59E7C97F BEC7E8F3 23A97A7E 36CC88BE 0F1D45B7 FF585AC5 4BD407B2 2B4154AA CC8F6D7E BF48E1D8 14CC5ED2 0F8037E0 A79715EE F29BE328 06A1D58B B7C5DA76 F550AA3D 8A1FBFF0 EB19CCB1 A313D55C DA56C9EC 2EF29632 387FE8D7 6E3C0468 043E8F66 3F4860EE 12BF2D5B 0B7474D6 E694F91E 6DCC4024 FFFFFFFF FFFFFFFF
Beide Seiten generieren jeweils eine 16 Bit große Zufallszahl als ihren geheimen PrivateKey und ihren PublicKey dergestalt, dass
Anhand der PublicKeys und PrivateKeys wird auf beiden Seiten jeweils der gemeinsame und identische 6144 Bit große Sitzungsschlüssel (SessionKey), der der Verschlüsselung der Nutzdaten (Payloads) dient, gebildet:
Für die Generierung wurde auf Seiten des Client die Javascript-Bibliothek "BigInt.js" ( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) und auf Seiten des Servers die Perl-Bibliothek "Math::BigInt" (https://perldoc.perl.org/Math::BigInt/) verwendet, um Zahlen größer als auf beiden Seiten analog verarbeiten zu können.
Javascript Codeschnipsel:
// (c) HK Businessconsulting, Hamburg var GENERATOR = '2'; var BITSIZE = 16; var PrivateKey1 = []; var PublicKey1 = []; var SessionKey = []; var Prime = []; var Generator = []; var getBigRandom = function(BitSize) { var ByteSize = Math.floor(BitSize/8+0.999); var array = []; while (ByteSize--) array.push (Math.floor(Math.random()*255).toString(16)); return array.join(""); } var PowMod = function (base, exponent, modulus) { result = 1; base = base % modulus; while (exponent) { if (exponent % 2 == 1) result = (result * base) % modulus; exponent = exponent >>> 1; base = (base * base) % modulus; } return result; } Prime = str2bigInt(PRIME, 16, 0); Generator = str2bigInt(GENERATOR, 16, 0); PrivateKey1 = str2bigInt(getBigRandom(BITSIZE),16,0); PublicKey1 = powMod(Generator, PrivateKey, Prime); ----- ----- buildSessionKey = function (PublicKey) { var str = bigInt2str(powMod(str2bigInt(PublicKey, 16, 0), PrivateKey, Prime),16); var length = str.length; var array = []; for (var i=0; i<length; i+=8) array.push ("0x"+str.substr(i, 8)); return SessionKey = array.join(","); } SessionKey = buildSessionKey(PublicKey2);
Perl Codeschnipsel:
# (c) HK Businessconsulting, Hamburg use Math::BigInt; use constant { GENERATOR => '02', BITSIZE => 16, }; my $PrivateKey2; my $PublicKey2; my $SessionKey; sub getBigRandom($) { my $ByteSize = int ($_[0]/8+0.999)-1; return \join ("", map (sprintf("%02x", rand(255)), 0 .. $ByteSize)); } sub BigPowMod { my ($base, $exponent, $modulus) = @_; return Math::BigInt->new("0x".$$base)->bmodpow(Math::BigInt->new("0x".$$exponent), Math::BigInt->new("0x".$$modulus))->as_hex(); } $PrivateKey2 = getBigRandom(BITSIZE); $PublicKey2 = BigPowMod(\GENERATOR, $PrivateKey2, \$Prime); ---- ---- sub buildSessionKey($$) { my ($PrivateKey, $PublicKey) = @_; my $Str = substr(BigPowMod($PublicKey, $PrivateKey, \$Prime),2); my $len = (length($Str)-1)/8; return join (",", map ("0x".substr( $Str, $_*8, 8), 0 .. $len)); } $SessionKey = buildSessionKey($PrivateKey2,$PublicKey1);
Um den Erfolg eines sog. MITM(Man-In-The-Middle)-Angriff zu unterbinden, wird das Diffie-Hellman-Protokoll um eine Authentizierungsmöglichkeit erweitert. Auf beiden Seiten werden jeweils Signaturen, Signature1 auf der einen und Signature2 auf der anderen, gebildet. Hiefür nutzen beide Seiten ein gemeinsames Geheimnis, den Authenifizierer, der beim Laden der entsprechenden Interrrogator-Seite (interrogator.shtml) an den Client übergeben wird. Die Signaturen werden durch Konkatenation von Authentifier und jeweiligem PublicKey mit anschließender Einwegverschlüssselung mittels eines sicheren Hash-Algorithmus (SHA256) hergestellt und an den jeweiligen Kommunikationspartner übermittelt.
Der auf beiden Seiten erzeugte, identische Sessionkey dient i.V.m. einem Verschlüsselungsverfahren der Verschlüssselung der zu übertragenden Nutzdaten (Payload). Die Wahl viel auf das kryptographische Verfahren 3DES (Data Encryption Standard), dass sich Seinerzeit musste sich aufs Altenteil begeben musste und durch andere allg. anerkannte Verfahren wie z. B. AES (Advanced Encryption Standard) abgelöst wurde. Ausschlaggebend hierfür war, dass in zunehmendem Maße von maßgeblichen Institutionen eine Verwendung des DES-Algorithmus, aufgrund fehlender Sicherheitskriterien nicht mehr als opportun für eine Verschlüsselung erachtet wurde. Vorrangige argumentative Faktoren, die immer wieder ins Feld geführt wurden und werden, sind:
Um darzulegen, dass ein der am besten analysierten Verschlüsselungsverfahren. doch noch nicht kategorisch "zum alten Eisen" gehört, soll im Folgenden gezeigt werden, wie mit einfachen Modifikationen den o. g. Schwachpunken begegnet werden kann.
Der DES-Algorithmus gehört zur Klasse der Feistel-Chiffren; beim 3DES (Triple DES) wird zuerst jeder 64-Bit Datenblock mittels des DES-Algorithmus und dem Schlüssel chiffriert, dann mit dechiffriert und abschließend mit erneut chiffriert:Die Entschlüsselung mit 3DES läuft im Wesentlichen analog in umgekehrter Reihenfolge ab:
Für jeden 64-Bit-Block wird eine sog. Initialpermutation durchgeführt und im Nachgang deren inverse Permutation , wobei:
Initialpermutation und deren inverse Permutation, die die ursprüngliche Reihenfolge der durch vertauschten Bits wieder herstellt, verbessern den Verschlüsselungsalgorithmus in Hinblick auf Sicherheit nicht, sondern erhöhen nur den Aufwand für die Implementation sowie den für die Ver- und Entschlüsselung, wodurch eine gleichzeitige Entfernung dieser beiden Permutationen opportun erscheint.
Für die Ver- resp. Entschlüsselung eines 64-Bit-Blocks wird die Feistelchiffre 16 mal durchlaufen. Hierfür werden über ein dem DES-Algorithmus immanenten Verfahren aus den 3 zur Anwendung kommenden Teilschlüsseln , und jeweils 16 sog. Rundenschlüssel generiert. Hieraus ist klar, dass nur die 3 Teilschlüssel , und mit einer Schlüssellänge von jeweils 56 Bits zur Sicherheit beitragen; der so resultierende Schlüsselraum beträgt: möglicher Schlüsselkombinationen
Bei einem Meet-in-the-middle-Angriff liegt genau hier, so die landläufige Meinung, die große Schwäche hinsichtlich der Schlüssellänge und damit bzgl. des Schlüsselraumes des 3DES-Algorithmus, denn der Meet-in-the-middle-Angriff greift zwei Schritte des Verfahrens einzeln an und dann werden in einem dritten Schritt, der revers ausgeführt wird, die Ergebnisse verglichen. Nota bene: dem Angreifer, muss,um den Angriff durchführen zu können, sowohl der Plaintext wie auch das Chiffrat bekannt sein!
Ein Angreifer entschlüsselt zunächst einen chiffrierten Block mal mit den möglichen Schlüsselkombinationen des Teilschlüssels und speichert die Ergebnisse zusammen mit dem jeweils korrelierenden Teilschlüssel ab:
Dann werden die () Zwischenergebnisse
Eine Möglichkeit den Schlüsselraum signifikant zu erhöhen, ohne den eigentlichen Ver- resp. Entschlüsselungsalgorithmus zu verändern, ist die Verwendung unabhängiger Rundenschlüssel; d.h. statt die 16 48-Bit-Rundenschlüssel aus einem 56-Bit-Schlüssel K zu generieren, werden die Rundenschlüssel willkürlich gewählt. Dies führt bei 3 Teilschlüsseln mit jeweils 768 Bit (16 x 48 Bit) zu einem rechnerischen Schlüsselraum mit der Größe von Schlüsseln. Da aber die Sicherheit des hier maßgeblich von der sog. Meet-In-The-Middle-Attacke bestimmt wird, reduziert sich der effektive, d.h. sicherheitsrelevante Schlüsselraum auf ungefähr (). Gefordert ist also ein gesamter, aus 3x16 48-Bit-Rundenschlüssel gebildeter Gesamtschlüssel mit der Mindestlänge von 2304 Bit (). Als Resultat während des Verbindungsaufbau wurde ein ausreichend großer Sessionkey (6144 Bit) generiert, der hier zur Verschlüsselung der Nutzdaten verwendet wird.
In diesem Zusammenhang sei kurz erwähnt, dass eine Verwendung von 4 Teilschlüsseln den Schlüsselraum nicht signifikant erhöhen würde, da auch hier die Meet-In-The-Middle-Attacke dazu führen würde, dass sich der sicherheitsrelevante Schlüsselraum nur auf (). belaufe. Erst eine Verwendung von 5 Teilschlüsseln würde den Schlüsselraum signifikant auf ungefähr () erhöhen.
Die Blockgröße des DES-Algorithmus beträgt 64 Bit; d.h. ein zu verschlüsselnder resp. zu entschlüsselnder Text wird in Blöcke zu jeweils 64 Bit zerlegt und jeder Block wird mit demselben vorgegebenen Schlüssel sowohl chiffriert als auch dechiffriert. Im Betriebsmodus ECB (Electronic Code Book) führt diese Vorgehensweise dazu, dass Blöcke eines Textes mit identischem Inhalt zu einem identischen Chiffrat und damit zu einer eingeschränkten Sicherheit führen. Der hier verwendete Betriebsmodus CBC (Cipher Block Chaining) hingegen versucht, die Sicherheitsdefizite des ECB-Modus zu reduzieren, indem das Chiffrat, also der chiffrierte Block, mit dem nächsten zu verschlüsselnden Klartextblock über eine Exklusiv-Oder-Funktion verknüpft wird und somit die Blöcke miteinander verkettet werden:
Um den ersten Block zu chiffrieren wird, da kein aktulles Chiffrat vorliegt, ein sog. Initialvektor (IV) eingeführt, der beiden Seiten bekannt sein muss. Dieser IV wird mit dem 1. zu verschlüsselnden Block mittels einer Exklusiv-ODER-Funktion verknüpft:
Um ein größere Blockgröße nachzuempfinden und den Schwachpunkt des 3SDES-Algorithmus, nämlich der der zu geringen Blockgröße, entgegenzuwirken, werden 2 konsekutive Blöcke logisch zusammengefasst und mit 6 unabhängigen Teilschlüsseln verschlüsselt. Hierdurch resultiert eine Blockgröße von 128 Bits, wodurch sich die Gesamtschlüssellänge auf 4608 Bit () verdoppelt, mit einem Schlüsselraum von ; auch diese geforderte Länge liefert der während des Verbindungsaufbaus generierter Sessionkey von 6144 Bit. Gleichzeitig liefert dieser Schlüssel den für den CBC-Betriebsmodus notwendigen Inititalvektor. Denn nach Verbrauch von 4608 Bit für den Schlüssel für die Verschlüsselumg verbleiben noch 1536 Bit, d.h. 48 mögliche Initialvektoren (). Mit oben aufgeführten Modifikationen wird aus dem 3DES-Algorithmus der ADES(Advanced Data Encryption Standard)-Algorithmus, bei dessen Implementierung die Vorlage der BSD-lizensierten DES-Algorithmus-Implementation von Paul Tero (Paul Tero, July 2001 http://www.tero.co.uk/des) sowie die Implementation des SSL-Pakets von Eric Young (Eric Young 1997 https://ftp.nluug.nl/security/coast/libs/libdes/) sehr inspirierend war.
Javascript Codeschnipsel:
// (c) HK Businessconsulting, Hamburg function ADES (SessionKey, message, encrypt, iv) { var cbcleft = iv[0]; var cbcright = iv[1]; var keys = SessionKey.split(","); var keys_len = SessionKey.length; var m=0, pass=0; var len = message.length; var looping = encrypt ? [[[64, 2], [62, -2], [0, 2]], [[128, 2], [126, -2], [64, 2]]] : [[[30, -2], [32, 2], [94, -2]], [[94, -2], [96, 2], [158, -2]]]; message += "\0\0\0\0\0\0\0\0"; //pad the message out with null bytes var result = []; var SPtrans_1 = [0x1010400,0,0x10000,0x1010404,0x1010004,0x10404,0x4,0x10000,0x400,0x1010400,0x1010404,0x400,0x1000404,0x1010004,0x1000000,0x4,0x404,0x1000400,0x1000400,0x10400,0x10400,0x1010000,0x1010000,0x1000404,0x10004,0x1000004,0x1000004,0x10004,0,0x404,0x10404,0x1000000,0x10000,0x1010404,0x4,0x1010000,0x1010400,0x1000000,0x1000000,0x400,0x1010004,0x10000,0x10400,0x1000004,0x400,0x4,0x1000404,0x10404,0x1010404,0x10004,0x1010000,0x1000404,0x1000004,0x404,0x10404,0x1010400,0x404,0x1000400,0x1000400,0,0x10004,0x10400,0,0x1010004]; var SPtrans_2 = [0x80108020,0x80008000,0x8000,0x108020,0x100000,0x20,0x80100020,0x80008020,0x80000020,0x80108020,0x80108000,0x80000000,0x80008000,0x100000,0x20,0x80100020,0x108000,0x100020,0x80008020,0,0x80000000,0x8000,0x108020,0x80100000,0x100020,0x80000020,0,0x108000,0x8020,0x80108000,0x80100000,0x8020,0,0x108020,0x80100020,0x100000,0x80008020,0x80100000,0x80108000,0x8000,0x80100000,0x80008000,0x20,0x80108020,0x108020,0x20,0x8000,0x80000000,0x8020,0x80108000,0x100000,0x80000020,0x100020,0x80008020,0x80000020,0x100020,0x108000,0,0x80008000,0x8020,0x80000000,0x80100020,0x80108020,0x108000]; var SPtrans_3 = [0x208,0x8020200,0,0x8020008,0x8000200,0,0x20208,0x8000200,0x20008,0x8000008,0x8000008,0x20000,0x8020208,0x20008,0x8020000,0x208,0x8000000,0x8,0x8020200,0x200,0x20200,0x8020000,0x8020008,0x20208,0x8000208,0x20200,0x20000,0x8000208,0x8,0x8020208,0x200,0x8000000,0x8020200,0x8000000,0x20008,0x208,0x20000,0x8020200,0x8000200,0,0x200,0x20008,0x8020208,0x8000200,0x8000008,0x200,0,0x8020008,0x8000208,0x20000,0x8000000,0x8020208,0x8,0x20208,0x20200,0x8000008,0x8020000,0x8000208,0x208,0x8020000,0x20208,0x8,0x8020008,0x20200]; var SPtrans_4 = [0x802001,0x2081,0x2081,0x80,0x802080,0x800081,0x800001,0x2001,0,0x802000,0x802000,0x802081,0x81,0,0x800080,0x800001,0x1,0x2000,0x800000,0x802001,0x80,0x800000,0x2001,0x2080,0x800081,0x1,0x2080,0x800080,0x2000,0x802080,0x802081,0x81,0x800080,0x800001,0x802000,0x802081,0x81,0,0,0x802000,0x2080,0x800080,0x800081,0x1,0x802001,0x2081,0x2081,0x80,0x802081,0x81,0x1,0x2000,0x800001,0x2001,0x802080,0x800081,0x2001,0x2080,0x800000,0x802001,0x80,0x800000,0x2000,0x802080]; var SPtrans_5 = [0x100,0x2080100,0x2080000,0x42000100,0x80000,0x100,0x40000000,0x2080000,0x40080100,0x80000,0x2000100,0x40080100,0x42000100,0x42080000,0x80100,0x40000000,0x2000000,0x40080000,0x40080000,0,0x40000100,0x42080100,0x42080100,0x2000100,0x42080000,0x40000100,0,0x42000000,0x2080100,0x2000000,0x42000000,0x80100,0x80000,0x42000100,0x100,0x2000000,0x40000000,0x2080000,0x42000100,0x40080100,0x2000100,0x40000000,0x42080000,0x2080100,0x40080100,0x100,0x2000000,0x42080000,0x42080100,0x80100,0x42000000,0x42080100,0x2080000,0,0x40080000,0x42000000,0x80100,0x2000100,0x40000100,0x80000,0,0x40080000,0x2080100,0x40000100]; var SPtrans_6 = [0x20000010,0x20400000,0x4000,0x20404010,0x20400000,0x10,0x20404010,0x400000,0x20004000,0x404010,0x400000,0x20000010,0x400010,0x20004000,0x20000000,0x4010,0,0x400010,0x20004010,0x4000,0x404000,0x20004010,0x10,0x20400010,0x20400010,0,0x404010,0x20404000,0x4010,0x404000,0x20404000,0x20000000,0x20004000,0x10,0x20400010,0x404000,0x20404010,0x400000,0x4010,0x20000010,0x400000,0x20004000,0x20000000,0x4010,0x20000010,0x20404010,0x404000,0x20400000,0x404010,0x20404000,0,0x20400010,0x10,0x4000,0x20400000,0x404010,0x4000,0x400010,0x20004010,0,0x20404000,0x20000000,0x400010,0x20004010]; var SPtrans_7 = [0x200000,0x4200002,0x4000802,0,0x800,0x4000802,0x200802,0x4200800,0x4200802,0x200000,0,0x4000002,0x2,0x4000000,0x4200002,0x802,0x4000800,0x200802,0x200002,0x4000800,0x4000002,0x4200000,0x4200800,0x200002,0x4200000,0x800,0x802,0x4200802,0x200800,0x2,0x4000000,0x200800,0x4000000,0x200800,0x200000,0x4000802,0x4000802,0x4200002,0x4200002,0x2,0x200002,0x4000000,0x4000800,0x200000,0x4200800,0x802,0x200802,0x4200800,0x802,0x4000002,0x4200802,0x4200000,0x200800,0,0x2,0x4200802,0,0x200802,0x4200000,0x800,0x4000002,0x4000800,0x800,0x200002]; var SPtrans_8 = [0x10001040,0x1000,0x40000,0x10041040,0x10000000,0x10001040,0x40,0x10000000,0x40040,0x10040000,0x10041040,0x41000,0x10041000,0x41040,0x1000,0x40,0x10040000,0x10000040,0x10001000,0x1040,0x41000,0x40040,0x10040040,0x10041000,0x1040,0,0,0x10040040,0x10000040,0x10001000,0x41040,0x40000,0x41040,0x40000,0x10041000,0x1000,0x40,0x10040040,0x1000,0x41040,0x10001000,0x40,0x10000040,0x10040000,0x10040040,0x10000000,0x40000,0x10001040,0,0x10041040,0x40040,0x10000040,0x10040000,0x10001000,0x10001040,0,0x10041040,0x41000,0x41000,0x1040,0x1040,0x40040,0x10000000,0x10041000]; while (m <len) { var temp, temp2, cbcleft2, cbcright2, left=((message.charCodeAt(m++)<<24)|(message.charCodeAt(m++)<<16)|(message.charCodeAt(m++)<<8)|message.charCodeAt(m++))&0xffffffff, right=((message.charCodeAt(m++)<<24)|(message.charCodeAt(m++)<<16)|(message.charCodeAt(m++)<<8)|message.charCodeAt(m++))&0xffffffff; if (encrypt) left^=cbcleft, right^=cbcright; else cbcleft2=cbcleft, cbcright2=cbcright, cbcleft=left, cbcright=right; var iterations = 3; while (iterations--) { var idx=looping[pass][iterations][0], inc=looping[pass][iterations][1], rounds = 16; //now go through and perform the encryption or decryption while (rounds--) { var right1=(right^(keys[idx % keys_len])), right2 = ((right >>> 4) | (right << 28)) ^ keys[(idx+1) % keys_len]; temp=left, left=right, right=temp^(SPtrans_2[(right1>>>24)&0x3f]|SPtrans_4[(right1>>>16)&0x3f]|SPtrans_6[(right1>>>8)&0x3f]|SPtrans_8[right1&0x3f] |SPtrans_1[(right2>>>24)&0x3f]|SPtrans_3[(right2>>>16)&0x3f]|SPtrans_5[(right2>>>8)&0x3f]|SPtrans_7[right2&0x3f]); idx+=inc; } temp=left, left=right, right=temp; //unreverse left and right } pass = pass ? 0 : 1; if (encrypt) cbcleft=left, cbcright=right; else left^=cbcleft2, right^=cbcright2; result.push(String.fromCharCode ((left>>>24), ((left>>>16) & 0xff), ((left>>>8) & 0xff), (left & 0xff), (right>>>24), ((right>>>16) & 0xff), ((right>>>8) & 0xff), (right & 0xff))); } return result.join(""); }
Perl Codeschnipsel:
# (c) HK Businessconsulting, Hamburg sub ADES { my ($SessionKey, $message, $encrypt, @iv)=@_; my @keys = split(',', $$SessionKey); my @msg = unpack 'N*', $$message ."\0\0\0\0\0\0\0\0"; #pad the message out with null bytes my ($keys_len, $msg_len, $m) = (scalar @keys, scalar @msg, 0); my ($cbcleft, $cbcright) = ($iv[0], $iv[1]); my $pass = 0; my @result = (); my @SPtrans_1 = (0x1010400,0,0x10000,0x1010404,0x1010004,0x10404,0x4,0x10000,0x400,0x1010400,0x1010404,0x400,0x1000404,0x1010004,0x1000000,0x4,0x404,0x1000400,0x1000400,0x10400,0x10400,0x1010000,0x1010000,0x1000404,0x10004,0x1000004,0x1000004,0x10004,0,0x404,0x10404,0x1000000,0x10000,0x1010404,0x4,0x1010000,0x1010400,0x1000000,0x1000000,0x400,0x1010004,0x10000,0x10400,0x1000004,0x400,0x4,0x1000404,0x10404,0x1010404,0x10004,0x1010000,0x1000404,0x1000004,0x404,0x10404,0x1010400,0x404,0x1000400,0x1000400,0,0x10004,0x10400,0,0x1010004); my @SPtrans_2 = (0x80108020,0x80008000,0x8000,0x108020,0x100000,0x20,0x80100020,0x80008020,0x80000020,0x80108020,0x80108000,0x80000000,0x80008000,0x100000,0x20,0x80100020,0x108000,0x100020,0x80008020,0,0x80000000,0x8000,0x108020,0x80100000,0x100020,0x80000020,0,0x108000,0x8020,0x80108000,0x80100000,0x8020,0,0x108020,0x80100020,0x100000,0x80008020,0x80100000,0x80108000,0x8000,0x80100000,0x80008000,0x20,0x80108020,0x108020,0x20,0x8000,0x80000000,0x8020,0x80108000,0x100000,0x80000020,0x100020,0x80008020,0x80000020,0x100020,0x108000,0,0x80008000,0x8020,0x80000000,0x80100020,0x80108020,0x108000); my @SPtrans_3 = (0x208,0x8020200,0,0x8020008,0x8000200,0,0x20208,0x8000200,0x20008,0x8000008,0x8000008,0x20000,0x8020208,0x20008,0x8020000,0x208,0x8000000,0x8,0x8020200,0x200,0x20200,0x8020000,0x8020008,0x20208,0x8000208,0x20200,0x20000,0x8000208,0x8,0x8020208,0x200,0x8000000,0x8020200,0x8000000,0x20008,0x208,0x20000,0x8020200,0x8000200,0,0x200,0x20008,0x8020208,0x8000200,0x8000008,0x200,0,0x8020008,0x8000208,0x20000,0x8000000,0x8020208,0x8,0x20208,0x20200,0x8000008,0x8020000,0x8000208,0x208,0x8020000,0x20208,0x8,0x8020008,0x20200); my @SPtrans_4 = (0x802001,0x2081,0x2081,0x80,0x802080,0x800081,0x800001,0x2001,0,0x802000,0x802000,0x802081,0x81,0,0x800080,0x800001,0x1,0x2000,0x800000,0x802001,0x80,0x800000,0x2001,0x2080,0x800081,0x1,0x2080,0x800080,0x2000,0x802080,0x802081,0x81,0x800080,0x800001,0x802000,0x802081,0x81,0,0,0x802000,0x2080,0x800080,0x800081,0x1,0x802001,0x2081,0x2081,0x80,0x802081,0x81,0x1,0x2000,0x800001,0x2001,0x802080,0x800081,0x2001,0x2080,0x800000,0x802001,0x80,0x800000,0x2000,0x802080); my @SPtrans_5 = (0x100,0x2080100,0x2080000,0x42000100,0x80000,0x100,0x40000000,0x2080000,0x40080100,0x80000,0x2000100,0x40080100,0x42000100,0x42080000,0x80100,0x40000000,0x2000000,0x40080000,0x40080000,0,0x40000100,0x42080100,0x42080100,0x2000100,0x42080000,0x40000100,0,0x42000000,0x2080100,0x2000000,0x42000000,0x80100,0x80000,0x42000100,0x100,0x2000000,0x40000000,0x2080000,0x42000100,0x40080100,0x2000100,0x40000000,0x42080000,0x2080100,0x40080100,0x100,0x2000000,0x42080000,0x42080100,0x80100,0x42000000,0x42080100,0x2080000,0,0x40080000,0x42000000,0x80100,0x2000100,0x40000100,0x80000,0,0x40080000,0x2080100,0x40000100); my @SPtrans_6 = (0x20000010,0x20400000,0x4000,0x20404010,0x20400000,0x10,0x20404010,0x400000,0x20004000,0x404010,0x400000,0x20000010,0x400010,0x20004000,0x20000000,0x4010,0,0x400010,0x20004010,0x4000,0x404000,0x20004010,0x10,0x20400010,0x20400010,0,0x404010,0x20404000,0x4010,0x404000,0x20404000,0x20000000,0x20004000,0x10,0x20400010,0x404000,0x20404010,0x400000,0x4010,0x20000010,0x400000,0x20004000,0x20000000,0x4010,0x20000010,0x20404010,0x404000,0x20400000,0x404010,0x20404000,0,0x20400010,0x10,0x4000,0x20400000,0x404010,0x4000,0x400010,0x20004010,0,0x20404000,0x20000000,0x400010,0x20004010); my @SPtrans_7 = (0x200000,0x4200002,0x4000802,0,0x800,0x4000802,0x200802,0x4200800,0x4200802,0x200000,0,0x4000002,0x2,0x4000000,0x4200002,0x802,0x4000800,0x200802,0x200002,0x4000800,0x4000002,0x4200000,0x4200800,0x200002,0x4200000,0x800,0x802,0x4200802,0x200800,0x2,0x4000000,0x200800,0x4000000,0x200800,0x200000,0x4000802,0x4000802,0x4200002,0x4200002,0x2,0x200002,0x4000000,0x4000800,0x200000,0x4200800,0x802,0x200802,0x4200800,0x802,0x4000002,0x4200802,0x4200000,0x200800,0,0x2,0x4200802,0,0x200802,0x4200000,0x800,0x4000002,0x4000800,0x800,0x200002); my @SPtrans_8 = (0x10001040,0x1000,0x40000,0x10041040,0x10000000,0x10001040,0x40,0x10000000,0x40040,0x10040000,0x10041040,0x41000,0x10041000,0x41040,0x1000,0x40,0x10040000,0x10000040,0x10001000,0x1040,0x41000,0x40040,0x10040040,0x10041000,0x1040,0,0,0x10040040,0x10000040,0x10001000,0x41040,0x40000,0x41040,0x40000,0x10041000,0x1000,0x40,0x10040040,0x1000,0x41040,0x10001000,0x40,0x10000040,0x10040000,0x10040040,0x10000000,0x40000,0x10001040,0,0x10041040,0x40040,0x10000040,0x10040000,0x10001000,0x10001040,0,0x10041040,0x41000,0x41000,0x1040,0x1040,0x40040,0x10000000,0x10041000); my @parameter = $encrypt ? ([[64, 2], [62, -2], [0, 2]], [[128, 2], [126, -2], [64, 2]]) : ([[30, -2], [32, 2], [94, -2]], [[94, -2], [96, 2], [158, -2]]); while ($m < $msg_len) { my ($temp, $temp2, $cbcleft2, $cbcright2); my ($left, $right) = ($msg[$m++], $msg[$m++]); if ($encrypt) { $left^=$cbcleft; $right^=$cbcright; } else { ($cbcleft2, $cbcright2, $cbcleft, $cbcright) = ($cbcleft, $cbcright, $left, $right); } my $iterations = 3; while ($iterations--) { my ($idx, $inc, $rounds) = ($parameter[$pass][$iterations][0], $parameter[$pass][$iterations][1], 16); while ($rounds--) { my ($right1,$right2)=(($right^hex $keys[$idx % $keys_len]), ((($right>>4)|($right<<28))^hex $keys[($idx+1) % $keys_len])); ($left, $right)=($right, $left^($SPtrans_2[($right1>>24)&0x3f]|$SPtrans_4[($right1>>16)&0x3f] |$SPtrans_6[($right1>>8)&0x3f]|$SPtrans_8[$right1&0x3f] |$SPtrans_1[($right2>>24)&0x3f]|$SPtrans_3[($right2>>16)&0x3f] |$SPtrans_5[($right2>>8)&0x3f]|$SPtrans_7[$right2&0x3f])); $idx+=$inc; } ($left, $right) = ($right, $left); } $pass = $pass ? 0 : 1; if ($encrypt) { ($cbcleft, $cbcright) = ($left, $right); } else { $left^=$cbcleft2; $right^=$cbcright2; } push (@result,pack('N*',($left, $right))); } return \join("",@result); }
Literatur:
[Andrew Nash et. al. 2002]: PKI - E-security implementieren; mitp-Verlag, Bonn 2002, ISBN 3-8266-0781-3
[BSI 2021a]: Technische Richtlinie 02102-1 Kryptographische Verfahren: Empfehlungen und Schlüssellängen;
Bundesamt für Sicherheit in der Informationstechnik 24. März 2021
[BSI 2021b]: Technische Richtlinie TR-02102-3 Kryptographische Verfahren: Empfehlungen und Schlüssellängen -
Teil 3 – Verwendung von Internet Protocol Security (IPsec) und Internet Key Exchange (IKEv2) - Version 2021-01;
Bundesamt für Sicherheit in der Informationstechnik 2021
[Helmut Kerner 1989]: Rechnernetze nach ISO-OSI, CCITT, Prentice-Hall, Wien 1989, ISBN 3-900934-10-X
[William Stallings 1995]: Sicherheit im Datennetz, Prentice-Hall, München 1995, ISBN 3-930436-29-9