Rheinwerk Computing < openbook > Rheinwerk Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.
 
Inhaltsverzeichnis
Vorwort
1 Neues in Java 8 und Java 7
2 Fortgeschrittene String-Verarbeitung
3 Threads und nebenläufige Programmierung
4 Datenstrukturen und Algorithmen
5 Raum und Zeit
6 Dateien, Verzeichnisse und Dateizugriffe
7 Datenströme
8 Die eXtensible Markup Language (XML)
9 Dateiformate
10 Grafische Oberflächen mit Swing
11 Grafikprogrammierung
12 JavaFX
13 Netzwerkprogrammierung
14 Verteilte Programmierung mit RMI
15 RESTful und SOAP-Web-Services
16 Technologien für die Infrastruktur
17 Typen, Reflection und Annotationen
18 Dynamische Übersetzung und Skriptsprachen
19 Logging und Monitoring
20 Sicherheitskonzepte
21 Datenbankmanagement mit JDBC
22 Java Native Interface (JNI)
23 Dienstprogramme für die Java-Umgebung
Stichwortverzeichnis

Jetzt Buch bestellen
Ihre Meinung?

Spacer
<< zurück
Java SE 8 Standard-Bibliothek von Christian Ullenboom
Das Handbuch für Java-Entwickler
Buch: Java SE 8 Standard-Bibliothek

Java SE 8 Standard-Bibliothek
Pfeil 20 Sicherheitskonzepte
Pfeil 20.1 Zentrale Elemente der Java-Sicherheit
Pfeil 20.1.1 Sichere Java Virtual Machine
Pfeil 20.1.2 Der Sandkasten (Sandbox)
Pfeil 20.1.3 Security-API der Java SE
Pfeil 20.1.4 Cryptographic Service Providers
Pfeil 20.2 Sicherheitsmanager (Security-Manager)
Pfeil 20.2.1 Der Sicherheitsmanager bei Applets
Pfeil 20.2.2 Sicherheitsmanager aktivieren
Pfeil 20.2.3 Rechte durch Policy-Dateien vergeben
Pfeil 20.2.4 Erstellen von Rechtedateien mit dem grafischen Policy-Tool
Pfeil 20.2.5 Kritik an den Policies
Pfeil 20.3 Signierung
Pfeil 20.3.1 Warum signieren?
Pfeil 20.3.2 Digitale Ausweise und die Zertifizierungsstelle
Pfeil 20.3.3 Mit keytool Schlüssel erzeugen
Pfeil 20.3.4 Signieren mit jarsigner
Pfeil 20.4 Kryptografische Hashfunktion
Pfeil 20.4.1 Die MDx-Reihe
Pfeil 20.4.2 Secure Hash Algorithm (SHA)
Pfeil 20.4.3 Mit der Security-API einen Fingerabdruck berechnen
Pfeil 20.4.4 Die Klasse MessageDigest
Pfeil 20.5 Verschlüsseln von Daten(-strömen) *
Pfeil 20.5.1 Den Schlüssel, bitte
Pfeil 20.5.2 Verschlüsseln mit Cipher
Pfeil 20.5.3 Verschlüsseln von Datenströmen
Pfeil 20.6 Zum Weiterlesen
 
Zum Seitenanfang

20.4Kryptografische Hashfunktion Zur vorigen ÜberschriftZur nächsten Überschrift

Bei der kryptografischen Hashfunktion geht es darum, aus Dokumenten einen »Fingerabdruck« (auch Message-Digest genannt) in Form einer Zahl zu berechnen. So etwas ist notwendig, wenn Änderungen an wichtigen Dokumenten erkannt werden sollen. Ändern wir etwa die Kontoverbindungen einer Rechnung, soll dies nicht unbemerkt bleiben; eine Änderung des Dokuments soll zu einer Änderung des Fingerabdrucks führen. Anders gesagt: Die Fingerabdrücke dienen dazu, veränderte Botschaften zu bemerken, und sind wichtig zur Erzeugung digitaler Unterschriften (elektronischer Signaturen) für Dokumente.

Wir haben ähnliche Funktionen schon beim Hash-Verfahren kennengelernt. Die meisten Klassen überschreiben die Methode hashCode() der Oberklasse Object, um ein int (also 32 Bit) als Identifizierer zu liefern. Allerdings soll so eine Hashfunktion möglichst schnell sein und muss nicht unbedingt sicher sein – ganz anders sieht das bei kryptografischen Hashfunktionen aus. Der berechnende Algorithmus ist auch wieder eine Einwegfunktion und liefert aus einer Botschaft beliebiger Länge einen Wert, aber nicht nur 32 Bit, sondern etwa bei SHA-256-Verfahren 256 Bit, also das Achtfache eines int.

Zum Umfeld kryptografischer Hashfunktionen gibt es weitere Synonyme und verwandte Begriffe: Kompressionsfunktion, Kontraktionsfunktion, kryptografische Prüfsumme (falls die Unterschrift zusätzlich verschlüsselt ist), Integritätsprüfung von Nachrichten (Message Integrity Check, MIC) oder Erkennung von Manipulationen (Manipulation Detection Code, MDC). Ist dem Fingerabdruck ein Schlüssel beigefügt, fällt auch der Begriff Message Authentication Code (MAC).

 
Zum Seitenanfang

20.4.1Die MDx-Reihe Zur vorigen ÜberschriftZur nächsten Überschrift

Die Firma RSA[ 145 ](Programmiert wurde es von Ron Rivest, einem der Mitentwickler des RSA-Public-Key-Verfahrens. Daher auch das »R«. Die Kollegen waren Adi Shamir und Leonard Adleman.)Data Security entwickelte mit der Reihe MD2, MD4 und MD5 drei Verfahren zur Berechnung kryptografischer Prüfsummen. MD5 produziert 128-Bit-Hashwerte; das ist eine 32-stellige Hexadezimalzahl. Während sich bei MD2 (1989) und MD4 (1990) relativ schnell Schwächen zeigten, dauerte es beim MD5-Verfahren (1991) mehr als 10 Jahre, bis im August 2004 von der Arbeitsgruppe um Xiaoyun Wang Methoden zur Kollision und von Patrick Stach[ 146 ](http://www.stachliu.com/collisions.html) ein Kollisionsgenerator entwickelt wurden. Wir haben uns schon beim Hashing in Kapitel 3, »Threads und nebenläufige Programierung«, mit Kollisionen beschäftigt. Da ein MD5-Hashwert 128 Bit lang ist, kann er 2^128 verschiedene Ausgabewerte annehmen. Zwangsläufig sind unter 2^128 + 1 verschiedenen Nachrichten mindestens zwei Texte mit gleichem Hashwert. Die Wahrscheinlichkeit, dass eine beliebige Nachricht den gleichen Hashwert wie eine vorgegebene Nachricht hat, liegt bei 0,000 000 000 000 000 000 000 000 000 000 000 000 029 % (1/2^128). (Die Wahrscheinlichkeit, dass zwei beliebig gewählte unterschiedliche Nachrichten den gleichen Hashwert haben, ist jedoch deutlich höher. Dieses Phänomen heißt Geburtstagsparadoxon.)

Die chinesische Arbeitsgruppe führte einen erfolgreichen Kollisionsangriff vor und generierte zwei Dokumente mit dem gleichen MD5-Hash. Am 1. März 2005 konnten zwei X.509-Zertifikate erstellt werden, die den gleichen MD5-Hash besaßen, aber unterschiedliche öffentliche Schlüssel. Dabei hat die Forschergruppe lediglich Kommentarfelder mit unterschiedlichen Werten belegt. Dabei ist ein Kollisionsangriff der einfachere Fall, denn hier müssen lediglich zwei verschiedene Nachrichten mit gleichem MD5-Hash gefunden werden. Spannender ist ein Preimage-Angriff, bei dem zu einem gegebenen Hashwert (etwa von einem X.509-Zertifikat) ein neues Dokument (also wieder ein X.509-Zertifikat) mit gleichem MD5-Hashwert erzeugt wird. Doch ein Preimage-Angriff ist für X.509-Zertifikate bisher nicht bekannt, und daher geht von MD5 im Moment auch keine echte Gefahr für digitale Signaturen aus.

 
Zum Seitenanfang

20.4.2Secure Hash Algorithm (SHAZur vorigen ÜberschriftZur nächsten Überschrift

Das National Institute of Standards and Technology (http://www.nist.gov) entwickelte im Secure Hash Standard (SHS) den Secure Hash Algorithm (SHA)[ 147 ](Eine Beschreibung des Algorithmus ist unter http://www.itl.nist.gov/fipspubs/fip180-1.htm abgelegt. FIPS ist die Abkürzung für Federal Information Processing Standards Publication – ich glaube nicht, dass es eine Verwandtschaft mit Heinz Erhardts Fips gibt.) mit einem Hashwert von 160 Bit. Der Secure-Hash-Standard ist Teil des Digital-Signature-Standards (DSS), und dieser wiederum ist Teil des Capstone-Projekts. Dieses Projekt definiert Standards für öffentlich verfügbare Kryptografie. Es besteht aus vier Hauptkomponenten. Dazu gehören ein symmetrischer Verschlüsselungsalgorithmus (Skipjack, auch Clipper genannt), ein Schlüsselaustauschprotokoll (bisher nicht öffentlich, ein Diffie-Hellman-Verfahren), ein Hash-Algorithmus (SHA) und ein Algorithmus für die digitale Unterschrift (DSA, die SHA benutzt). Die Auswahl der Algorithmen treffen das NIST und die NSA.

Die erste Version von SHA hatte eine undokumentierte Schwachstelle, die in einer neuen Implementierung, SHA-1, nicht mehr vorhanden ist. Wir nennen SHA-1 im Folgenden einfach SHA und beziehen uns damit auf die neueste Version. Im Vergleich zu MD5 generiert SHA einen Hashwert von 160 Bit, was Brute-Force-Angriffe erschwert. Die Analysen von Xiaoyun Wang, Yiqun Lisa Yin und Hongbo Yu zeigten jedoch auch Schwächen von SHA-1 auf. Das Team konnte die Anzahl der Kollisionsberechnungen von Brute-Force-Angriffen von 2^80 auf 2^69 und später auf 2^63 senken – Security-Guru Bruce Schneier vermeldet auf seiner Webseite[ 148 ](http://www.schneier.com/blog/archives/2005/08/new_cryptanalyt.html und http://www.schneier.com/blog/archives/2005/02/sha1_broken.html), dass SHA-1 damit mehr oder weniger geknackt sei.

 
Zum Seitenanfang

20.4.3Mit der Security-API einen Fingerabdruck berechnen Zur vorigen ÜberschriftZur nächsten Überschrift

Der Einstiegspunkt für Fingerabdrücke ist eine statische Methode, MessageDigest.getInstance(String), die ein Exemplar eines konkreten kryptografischen Algorithmus liefert. Das Argument ist ein Name für den Algorithmus, etwa MD5 oder SHA. Das JDK implementiert den DSA-Algorithmus NIST Digital Signature Algorithm und für digitale Signaturen SHA-1 und MD5. Da wir uns etwas näher mit Signaturen beschäftigt haben, wollen wir zunächst die Klasse MessageDigest für digitale Fingerabdrücke untersuchen.

 
Zum Seitenanfang

20.4.4Die Klasse MessageDigest Zur vorigen ÜberschriftZur nächsten Überschrift

Mit der statischen Methode getInstance(String) bekommen wir einen Algorithmus, der eine bestimmte Berechnungsfunktion implementiert. Als Namen sind etwa möglich:

  • SHA-512

  • MD2

  • MD5

[zB]Beispiel

Erzeuge ein MessageDigest-Objekt für SHA:

MessageDigest md = MessageDigest.getInstance( "SHA" );

Die Methode getInstance(…) gibt es in zwei Varianten. Beiden gemeinsam ist der Name des Algorithmus im Methodenparameter. Eine zweite Variante spezifiziert den Provider, also die Implementierungsvariante, näher, wobei als zweiter Parametertyp entweder String oder java.security.Provider in Frage kommt.

[zB]Beispiel

Es soll die Implementierung vom Provider »SUN« kommen:

MessageDigest digest = MessageDigest.getInstance( "SHA", "SUN" );

Die explizite Provider-Angabe ist nur dann nötig, wenn ein eigener Provider verwendet werden soll.

Ist der Algorithmus nicht bekannt, bekommen wir eine NoSuchAlgorithmException. Ein unbekannter Hersteller führt zu einer NoSuchProviderException.

Welche MessageDigest-Algorithmen werden unterstützt?

Die Java-API bietet keine direkte Anfragemethode, die alle MD-Algorithmen liefert. Diese sind jedoch unter http://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html dokumentiert. Bei Java 8 sind dies:

  • MD2, MD5

  • SHA-1, SHA-224, SHA-256, SHA-384, SHA-512

Wer sich zur Laufzeit dennoch eine Aufzählung wünscht, kann einen Trick anwenden. Am Anfang des Kapitels kam schon zur Sprache, dass Security.getProviders() alle Provider liefert, und alle Provider für kryptografische Hashfunktionen sind auch darunter. Wir können also ganz gezielt die Sammlung nach einem MD filtern, denn deren String-Repräsentation beginnt mit »MessageDigest.« bzw. »Alg.Alias.MessageDigest«.

Den Fingerabdruck berechnen

Nun können wir eine Nachricht kodieren. Dafür gibt es zwei Möglichkeiten: Die Nachricht wird als Ganzes übergeben, oder sie wird Schritt für Schritt kodiert. Die Funktionsweise erinnert sehr an die Schnittstelle java.util.zip.Checksum.

[zB]Beispiel

Die folgenden Zeilen berechnen den Hashwert für eine Zeichenkette:

MessageDigest md = MessageDigest.getInstance( "SHA" );
md.update( "Hello".getBytes( StandardCharsets.UTF_8 ) );

Die update(byte)-Methode ist auch für ein einzelnes Byte deklariert. Für große Dateien ist es besser, immer wieder update(byte[]) oder update(byte[], int, int) auf größeren Blöcken aufzurufen, anstatt die ganze Datei auf einmal zu übergeben, da dafür die Datei vollständig im Speicher stehen müsste. Schritt für Schritt nehmen wir mit update(…) immer mehr von der Nachricht hinzu.

Ein Beispiel: Berechne den Hashwert für alle Daten eines Eingabestroms:

Listing 20.7com/tutego/security/digest/MessageDigestDemo.java, messageDigest()

static byte[] messageDigest( InputStream in, String algo ) throws Exception {
MessageDigest messageDigest = MessageDigest.getInstance( algo );
byte[] md = new byte[ 8192 ];

for ( int n = 0; (n = in.read( md )) > –1; )
messageDigest.update( md, 0, n );

return messageDigest.digest();
}

Den Fingerabdruck auslesen

Nach dem Sammeln berechnet die Methode digest() die Signatur. Sie hat eine bestimmte Länge in Byte, die wir mit getDigestLength() erfragen können. Da digest() ein Byte-Array zurückliefert, ist der Wert von getDigestLength() mit der Länge des Arrays identisch. digest(byte[]) und digest(byte[], int, int) gibt es auch, und sie zeigen, dass wir der Methode auch direkt ein Byte-Feld für den Abschluss übergeben lassen können. Ein einfaches SHA-Programm für den String sieht daher so aus:

Listing 20.8com/tutego/security/digest/SHATest.java, main()

MessageDigest md = MessageDigest.getInstance( "SHA" );
byte[] digest1 = md.digest( "abc".getBytes( StandardCharsets.UTF_8 ) );
System.out.printf( "%032X%n", new BigInteger( 1, digest1 ) );
byte[] digest2 = md.digest( "Abc".getBytes( StandardCharsets.UTF_8 ) );
System.out.printf( "%032X%n", new BigInteger( 1, digest2 ) );
byte[] digest3 = md.digest( "abd".getBytes( StandardCharsets.UTF_8 ) );
System.out.printf( "%032X%n", new BigInteger( 1, digest3 ) );

Das Programm erzeugt in der ersten Zeile:

A9993E364706816ABA3E25717850C26C9CD0D89D // abc

Schon eine einfache Veränderung wirkt sich global aus. Statt »abc« kodieren wir jetzt »Abc« und »abd«. Einmal ändert sich der Kleinbuchstabe in einen Großbuchstaben, und im anderen Fall nehmen wir einfach das nachfolgende Zeichen im Alphabet. Kein Byte bleibt gleich:

915858AFA2278F25527F192038108346164B47F2 // Abc
CB4CC28DF0FDBE0ECF9D9662E294B118092A5735 // abd

 


Ihre Meinung

Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.

<< zurück
Zum Rheinwerk-Shop
Zum Rheinwerk-Shop: Java SE 8 Standard-Bibliothek Java SE 8 Standard-Bibliothek
Jetzt Buch bestellen

 Buchempfehlungen
Zum Rheinwerk-Shop: Java ist auch eine Insel
Java ist auch eine Insel


Zum Rheinwerk-Shop: Professionell entwickeln mit Java EE 8
Professionell entwickeln mit Java EE 8


Zum Rheinwerk-Shop: Besser coden
Besser coden


Zum Rheinwerk-Shop: Entwurfsmuster
Entwurfsmuster


Zum Rheinwerk-Shop: IT-Projektmanagement
IT-Projektmanagement


 Lieferung
Versandkostenfrei bestellen in Deutschland, Österreich und der Schweiz
InfoInfo

 
 


Copyright © Rheinwerk Verlag GmbH 2018
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das Openbook denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt.
Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.

 
Nutzungsbestimmungen | Datenschutz | Impressum

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de

Cookie-Einstellungen ändern