diff options
Diffstat (limited to 'Master/Reference Architectures and Patterns/hjp5/html/k100303.html')
| -rw-r--r-- | Master/Reference Architectures and Patterns/hjp5/html/k100303.html | 1660 |
1 files changed, 1660 insertions, 0 deletions
diff --git a/Master/Reference Architectures and Patterns/hjp5/html/k100303.html b/Master/Reference Architectures and Patterns/hjp5/html/k100303.html new file mode 100644 index 0000000..c5cb46a --- /dev/null +++ b/Master/Reference Architectures and Patterns/hjp5/html/k100303.html @@ -0,0 +1,1660 @@ +<html>
+<head>
+<title>
+Handbuch der Java-Programmierung, 5. Auflage
+</title>
+</head>
+<body>
+<a name="startofbody"></a>
+<script language="JavaScript" src="hjp4lib.js">
+</script>
+<script language="JavaScript">
+installKbdHandler("97,#startofbody;101,#endofbody;116,cover.html;122,k100003.html;115,search.html;105,index.html;100,JDKDOCS;112,APIDOCS;104,k100302.html;106,k100302.html;107,k100304.html;108,k100307.html");
+</script>
+<table border=0 cellpadding=0 cellspacing=1 width="100%">
+<tr bgcolor="#EEFFCC">
+<td width="7%" align=center bgcolor="#DDCC99"><a href="cover.html"> Titel </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100003.html"> Inhalt </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="search.html"> Suchen </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="index.html"> Index </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="../jdkdocs/index.html" onClick="this.href=getDocIndex()"> DOC </a>
+<td align="right">Handbuch der Java-Programmierung, 5. Auflage
+<tr bgcolor="#EEFFCC">
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100302.html"> << </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100302.html"> < </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100304.html"> > </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100307.html"> >> </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="../jdkdocs/api/index.html" onClick="this.href=getApiIndex()"> API </a>
+<td align="right">Kapitel 48 - Sicherheit und Kryptographie
+</table>
+<hr>
+
+
+<!-- Section -->
+<a name="sectlevel2id048001"></a>
+<h2>48.1 Kryptografische Grundlagen </h2>
+<hr>
+<ul>
+<li><a href="k100303.html#sectlevel2id048001">48.1 Kryptografische Grundlagen</a>
+<ul>
+<li><a href="k100303.html#sectlevel3id048001001">48.1.1 Wichtige Begriffe</a>
+<li><a href="k100303.html#sectlevel3id048001002">48.1.2 Einfache Verschlüsselungen</a>
+<ul>
+<li><a href="k100303.html#sectlevel4id048001002001">Substitution</a>
+<li><a href="k100303.html#sectlevel4id048001002002">Exklusiv-ODER</a>
+<li><a href="k100303.html#sectlevel4id048001002003">Vorsicht!</a>
+</ul>
+<li><a href="k100303.html#messagedigests">48.1.3 Message Digests</a>
+<ul>
+<li><a href="k100303.html#sectlevel4id048001003001">Authentifizierung</a>
+<li><a href="k100303.html#sectlevel4id048001003002">»Unwissende« Beweise</a>
+<li><a href="k100303.html#sectlevel4id048001003003">Fingerprints</a>
+</ul>
+<li><a href="k100303.html#kryptozufallszahlen">48.1.4 Kryptografische Zufallszahlen</a>
+<li><a href="k100303.html#publickeykrypto">48.1.5 Public-Key-Verschlüsselung</a>
+<li><a href="k100303.html#digitaleunterschriften">48.1.6 Digitale Unterschriften</a>
+<ul>
+<li><a href="k100303.html#sectlevel4id048001006001">Erzeugen und Verwalten von Schlüsseln mit dem JDK</a>
+<li><a href="k100303.html#sectlevel4id048001006002">Erstellen einer digitalen Unterschrift</a>
+<li><a href="k100303.html#sectlevel4id048001006003">Verifizieren einer digitalen Unterschrift</a>
+</ul>
+<li><a href="k100303.html#zertifikate">48.1.7 Zertifikate</a>
+</ul>
+</ul>
+<hr>
+
+
+<!-- Section -->
+<a name="sectlevel3id048001001"></a>
+<h3>48.1.1 Wichtige Begriffe </h3>
+
+<p>
+Thema dieses Kapitels ist es, die in Java verfügbaren Sicherheitsmechanismen
+vorzustellen. Wir werden dabei zunächst auf allgemeine Konzepte
+aus dem Gebiet der Kryptographie und ihre Implementierung in Java
+eingehen. Anschließend werden die eingebauten Sicherheitsmechanismen
+von Java vorgestellt. Zum Abschluss zeigen wir, wie signierte Applets
+erstellt und verwendet werden, und wie mit ihrer Hilfe eine fein differenzierte
+Sicherheitspolitik etabliert werden kann. Zunächst sollen allerdings
+wichtige Begriffe erläutert werden, die für das Verständnis
+der nachfolgenden Abschnitte von Bedeutung sind.
+
+<p>
+Angenommen, ein <i>Sender</i> will eine Nachricht an einen <i>Empfänger</i>
+übermitteln. Soll das geschehen, ohne dass ein Dritter, dem die
+Nachricht in die Hände fallen könnte, diese entziffern kann,
+könnte sie <a name="ixa103440"><i>verschlüsselt</i></a>
+werden. Der ursprüngliche Nachrichtentext (der als <a name="ixa103441"><i>Klartext</i></a>
+bezeichnet wird) wird dabei mit Hilfe eines dem Sender bekannten Verfahrens
+unkenntlich gemacht. Das als <a name="ixa103442"><i>Schlüsseltext</i></a>
+bezeichnete Ergebnis wird an den Empfänger übermittelt und
+mit Hilfe eines ihm bekannten Verfahrens wieder in den Klartext zurückverwandelt
+(was als <a name="ixa103443"><i>entschlüsseln</i></a> bezeichnet
+wird).
+<p>
+<a name="imageid048001"></a>
+<img src="images/Verschluesseln.gif">
+<p>
+
+<p><i>
+Abbildung 48.1: Verschlüsseln einer Nachricht</i></p>
+
+<p>
+Solange der Algorithmus zum Entschlüsseln geheim bleibt, ist
+die Nachricht sicher. Selbst wenn sie auf dem Übertragungsweg
+entdeckt wird, kann kein Dritter sie entschlüsseln. Wird das
+Entschlüsselungsverfahren dagegen entdeckt, kann die Nachricht
+(und mit ihr alle anderen Nachrichten, die mit demselben Verfahren
+verschlüsselt wurden) entziffert werden.
+
+<p>
+Um den Schaden durch das Entdecken eines Verschlüsselungsverfahrens
+gering zu halten, werden die Verschlüsselungsalgorithmen in aller
+Regel parametrisiert. Dazu wird beim Verschlüsseln eine als <a name="ixa103444"><i>Schlüssel</i></a>
+bezeichnete Ziffern- oder Zeichenfolge angegeben, mit der die Nachricht
+verschlüssel wird. Der Empfänger benötigt dann zusätzlich
+zur Kenntnis des Verfahrens noch den vom Sender verwendeten Schlüssel,
+um die Nachricht entziffern zu können.
+
+<p>
+Die Wissenschaft, die sich mit dem Verschlüsseln und Entschlüsseln
+von Nachrichten und eng verwandten Themen beschäftigt, wird als
+<a name="ixa103445"><i>Kryptographie</i></a> bezeichnet. Liegt der
+Schwerpunkt mehr auf dem Entschlüsseln, (insbesondere dem Entziffern
+geheimer Botschaften), wird dies als <a name="ixa103446"><i>Kryptoanalyse</i></a>
+bezeichnet. Die <a name="ixa103447"><i>Kryptologie</i></a> schließlich
+bezeichnet den Zweig der Mathematik, der sich mit den formal-mathematischen
+Aspekten der Kryptographie und Kryptoanalyse beschäftigt.
+
+<!-- Section -->
+
+<a name="sectlevel3id048001002"></a>
+<h3>48.1.2 Einfache Verschlüsselungen </h3>
+
+
+<!-- Section -->
+<a name="sectlevel4id048001002001"></a>
+<h4>Substitution </h4>
+
+<p>
+Seit dem Altertum sind einfache Verschlüsselungsverfahren bekannt.
+Zu ihnen zählen beispielsweise die Substitutions-Verschlüsselungen,
+bei denen einzelne Buchstaben systematisch durch andere ersetzt werden.
+Angenommen, Klartexte bestehen nur aus den Buchstaben A bis Z, so
+könnte man sie dadurch verschlüsseln, dass jeder Buchstabe
+des Klartextes durch den Buchstaben ersetzt wird, der im Alphabet
+um eine feste Anzahl Zeichen verschoben ist. Als Schlüssel <i>k</i>
+kann beispielsweise die Länge der Verschiebung verwendet werden.
+Ist <i>k</i> beispielsweise 3, so würde jedes A durch ein D,
+jedes B durch ein E, jedes W durch ein Z, jedes X durch ein A usw.
+ersetzt werden.
+
+<p>
+Dieses einfache Verfahren wurde beispielweise bereits von Julius Cäsar
+verwendet, um seinen Generälen geheime Nachrichten zu übermitteln.
+Es wird daher auch als <a name="ixa103448"><i>Cäsarische Verschlüsselung</i></a>
+bezeichnet. Das folgende Listing zeigt eine einfache Implementierung
+dieses Verfahrens, bei dem Schlüssel und Klartext als Argument
+übergeben werden müssen:
+<a name="listingid048001"></a>
+
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#DDDDDD">
+<tr>
+<td valign=top>
+<font color="#000055">
+<pre>
+<font color="#555555">001 </font><font color="#00AA00">/* Listing4801.java */</font>
+<font color="#555555">002 </font>
+<font color="#555555">003 </font><font color="#0000AA">public</font> <font color="#0000AA">class</font> Listing4801
+<font color="#555555">004 </font>{
+<font color="#555555">005 </font> <font color="#0000AA">public</font> <font color="#0000AA">static</font> <font color="#006699">void</font> main(String[] args)
+<font color="#555555">006 </font> {
+<font color="#555555">007 </font> <font color="#006699">int</font> key = Integer.parseInt(args[0]);
+<font color="#555555">008 </font> String msg = args[1];
+<font color="#555555">009 </font> <font color="#0000AA">for</font> (<font color="#006699">int</font> i = 0; i < msg.length(); ++i) {
+<font color="#555555">010 </font> <font color="#006699">int</font> c = (msg.charAt(i) - <font color="#0000FF">'A'</font> + key) % 26 + <font color="#0000FF">'A'</font>;
+<font color="#555555">011 </font> System.out.print((<font color="#006699">char</font>)c);
+<font color="#555555">012 </font> }
+<font color="#555555">013 </font> }
+<font color="#555555">014 </font>}</pre>
+</font>
+</td>
+<td valign=top align=right>
+<a href="../examples/Listing4801.java"><font color="#000055" size=-1>Listing4801.java</font></a></td>
+</tr>
+</table>
+<i>
+Listing 48.1: Verschlüsselung durch Substitution</i></p>
+
+<p>
+Um die Nachricht zu entschlüsseln, verwendet der Empfänger
+dasselbe Verfahren, allerdings mit dem Schlüssel 26 - <i>k</i>:
+<font color="#333300">
+<pre>
+---><b>java Test2 3 HALLO</b>
+KDOOR
+---><b>java Test2 23 KDOOR</b>
+HALLO
+</pre>
+</font>
+
+
+<!-- Section -->
+<a name="sectlevel4id048001002002"></a>
+<h4>Exklusiv-ODER </h4>
+
+<p>
+Ein ähnlich weitverbreitetes Verfahren besteht darin, jedes Zeichen
+des Klartexts mit Hilfe des Exklusiv-ODER-Operators mit dem Schlüssel
+zu verknüpfen. Durch dessen Anwendung werden alle Bits invertiert,
+die zu einem gesetztem Bit im Schlüssel korrespondieren, alle
+anderen bleiben unverändert. Das Entschlüsseln erfolgt durch
+erneute Anwendung des Verfahrens mit demselben Schlüssel.
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100%>
+<tr>
+<td width=1 align=left valign=top bgcolor="#000077"><img src="trp1_1.gif"></td>
+<td><img src="trp1_1.gif" width=2></td>
+<td valign=top width=1000>
+
+<p>
+Ein Verfahren, bei dem Ver- und Entschlüsselung mit demselben
+Algorithmus und Schlüssel durchgeführt werden, wird als
+<a name="ixa103449"><i>symmetrische Verschlüsselung</i></a> bezeichnet.</td>
+<td><img src="trp1_1.gif" width=2></td>
+<td valign=top>
+<table border=0 cellspacing=0 cellpadding=1 width=100% bgcolor="#000077">
+<tr>
+<td><font color="#FFFFFF"> Hinweis </font></td>
+</tr>
+</table>
+</td>
+<td width=1 align=left valign=top bgcolor="#000077"><img src="trp1_1.gif"></td>
+</tr>
+</table>
+
+<p>
+Eine einfache Implementierung der Exklusiv-ODER-Verschlüsselung
+zeigt folgendes Listing:
+<a name="listingid048002"></a>
+
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#DDDDDD">
+<tr>
+<td valign=top>
+<font color="#000055">
+<pre>
+<font color="#555555">001 </font><font color="#00AA00">/* Listing4802.java */</font>
+<font color="#555555">002 </font>
+<font color="#555555">003 </font><font color="#0000AA">public</font> <font color="#0000AA">class</font> Listing4802
+<font color="#555555">004 </font>{
+<font color="#555555">005 </font> <font color="#0000AA">public</font> <font color="#0000AA">static</font> <font color="#006699">void</font> main(String[] args)
+<font color="#555555">006 </font> {
+<font color="#555555">007 </font> <font color="#006699">int</font> key = Integer.parseInt(args[0]);
+<font color="#555555">008 </font> String msg = args[1];
+<font color="#555555">009 </font> <font color="#0000AA">for</font> (<font color="#006699">int</font> i = 0; i < msg.length(); ++i) {
+<font color="#555555">010 </font> System.out.print((<font color="#006699">char</font>)(msg.charAt(i) ^ key));
+<font color="#555555">011 </font> }
+<font color="#555555">012 </font> }
+<font color="#555555">013 </font>}</pre>
+</font>
+</td>
+<td valign=top align=right>
+<a href="../examples/Listing4802.java"><font color="#000055" size=-1>Listing4802.java</font></a></td>
+</tr>
+</table>
+<i>
+Listing 48.2: Verschlüsselung mit Exklusiv-ODER</i></p>
+
+<p>
+Ein Anwendungsbeispiel könnte so aussehen:
+<font color="#333300">
+<pre>
+---><b>java Test2 65 hallo</b>
+) --.
+---><b>java Test2 65 ") --."</b>
+hallo
+</pre>
+</font>
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100%>
+<tr>
+<td width=1 align=left valign=top bgcolor="#CC0000"><img src="trp1_1.gif"></td>
+<td><img src="trp1_1.gif" width=1></td>
+<td width=1 align=left valign=top bgcolor="#CC0000"><img src="trp1_1.gif"></td>
+<td><img src="trp1_1.gif" width=2></td>
+<td valign=top width=1000>
+
+<p>
+Daß die Rückkonvertierung über die Kommandozeile hier
+geklappt hat, liegt daran, dass die Verschlüsselung keine nicht-darstellbaren
+Sonderzeichen produziert hat (der Schlüssel 65 kippt lediglich
+2 Bits in jedem Zeichen). Im allgemeinen sollte der zu ver- oder entschlüsselnde
+Text aus einer Datei gelesen und das Resultat auch wieder in eine
+solche geschrieben werden. Dann können alle 256 möglichen
+Bitkombinationen je Byte zuverlässig gespeichert und übertragen
+werden.</td>
+<td><img src="trp1_1.gif" width=2></td>
+<td valign=top>
+<table border=0 cellspacing=0 cellpadding=1 width=100% bgcolor="#CC0000">
+<tr>
+<td><font color="#FFFFFF"> Warnung </font></td>
+</tr>
+</table>
+</td>
+<td width=1 align=left valign=top bgcolor="#CC0000"><img src="trp1_1.gif"></td>
+</tr>
+</table>
+
+
+<!-- Section -->
+<a name="sectlevel4id048001002003"></a>
+<h4>Vorsicht! </h4>
+
+<p>
+Derart einfache Verschlüsselungen wie die hier vorgestellten
+sind zwar weit verbreitet, denn sie sind einfach zu implementieren.
+Leider bieten sie aber nicht die geringste Sicherheit gegen ernsthafte
+Krypto-Attacken. Einige der in letzter Zeit bekannt gewordenen (und
+für die betroffenen Unternehmen meist peinlichen, wenn nicht
+gar kostspieligen) Fälle von Einbrüchen in Softwaressysteme
+waren darauf zurückzuführen, dass zu einfache Sicherheitssysteme
+verwendet wurden.
+
+<p>
+Wir wollen diesen einfachen Verfahren nun den Rücken zuwenden,
+denn seit dem JDK 1.2 gibt es in Java Möglichkeiten, professionelle
+Sicherheitskonzepte zu verwenden. Es ist ein großer Vorteil
+der Sprache, dass auf verschiedenen Ebenen Sicherheitsmechanismen
+fest eingebaut wurden, und eine missbräuchliche Anwendung der
+Sprache erschwert wird. In den folgenden Abschnitten werden wir die
+wichtigsten dieser Konzepte vorstellen.
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100%>
+<tr>
+<td width=1 align=left valign=top bgcolor="#000077"><img src="trp1_1.gif"></td>
+<td><img src="trp1_1.gif" width=2></td>
+<td valign=top width=1000>
+
+<p>
+Allerdings sollte dieser Abschnitt nicht als umfassende Einführung
+in die Grundlagen der Kryptographie missverstanden werden. Das Thema
+ist ausgesprochen vielschichtig, mathematisch anspruchsvoll, und es
+erfordert in seiner Detailfülle weitaus mehr Raum als hier zur
+Verfügung steht. Wir werden neue Begriffe nur soweit einführen,
+wie sie für das Verständnis der entsprechenden Abschnitte
+erforderlich sind. Für Details sei auf weiterführende Literatur
+verwiesen. Ein sehr gelungenes Buch ist »Applied Cryptography«
+von Bruce Schneier<a name="ixa103450"></a>. Es bietet einen umfassenden
+und dennoch verständlichen Einblick in die gesamte Materie und
+ist interessant zu lesen. Gleichermaßen unterhaltsam wie lehrreich
+ist auch die in »Geheime Botschaften« von Simon Singh dargestellte
+Geschichte der Kryptographie.</td>
+<td><img src="trp1_1.gif" width=2></td>
+<td valign=top>
+<table border=0 cellspacing=0 cellpadding=1 width=100% bgcolor="#000077">
+<tr>
+<td><font color="#FFFFFF"> Hinweis </font></td>
+</tr>
+</table>
+</td>
+<td width=1 align=left valign=top bgcolor="#000077"><img src="trp1_1.gif"></td>
+</tr>
+</table>
+
+
+<!-- Section -->
+<a name="messagedigests"></a>
+<h3>48.1.3 Message Digests<a name="ixa103451"></a> </h3>
+
+<p>
+Ein <i>Message Digest</i> ist eine Funktion, die zu einer gegebenen
+Nachricht eine Prüfziffer berechnet. Im Gegensatz zu ähnlichen
+Verfahren, die keine kryptografische Anwendung haben (siehe z.B. <a name="ixa103452"><a href="index_h.html#ixb100418"><font color=#000080><tt>hashCode</tt></font></a></a>
+in <a href="k100052.html#klasseobject">Abschnitt 8.1.2</a>), muss
+ein Message Digest zusätzlich folgende Eigenschaften besitzen:
+<ul>
+<li>Die Wahrscheinlichkeit, dass zwei unterschiedliche Nachrichten
+dieselbe Prüfsumme haben, muss vernachlässigbar gering sein.
+<li>Es muss praktisch unmöglich sein, aus der berechneten Prüfsumme
+auf die ursprüngliche Nachricht zurückzuschließen.
+</ul>
+
+<p>
+Ein Message Digest wird daher auch als <a name="ixa103453"><i>Einweg-Hashfunktion</i></a>
+bezeichnet. Er ist meist 16 oder 20 Byte lang und kann als eine Art
+komplizierte mathematische <i>Zusammenfassung</i> der Nachricht angesehen
+werden. Message Digests haben Anwendungen im Bereich digitaler Unterschriften
+und bei der Authentifizierung. Allgemein gesprochen werden sie dazu
+verwendet, sicherzustellen, dass eine Nachricht nicht verändert
+wurde. Bevor wir auf diese Anwendungen in den nächsten Abschnitten
+zurückkommen, wollen wir uns ihre Implementierung im JDK 1.2
+ansehen.
+
+<p>
+Praktisch alle wichtigen Sicherheitsfunktionen sind im Paket <a href="index_j.html#ixb100601"><font color=#000080><tt>java.security</tt></font></a>
+oder einem seiner Unterpakete untergebracht. Ein Message Digest wird
+durch die Klasse <a name="ixa103454"><a href="index_m.html#ixb102580"><font color=#000080><tt>MessageDigest</tt></font></a></a>
+implementiert. Deren Objekte werden nicht direkt instanziert, sondern
+mit der Methode <a href="index_g.html#ixb102581"><font color=#000080><tt>getInstance</tt></font></a>
+erstellt:
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#EEFFCC">
+<tr>
+<td valign=top width=100%>
+<font color="#660066">
+<pre>
+public static MessageDigest getInstance(String algorithm)
+ throws NoSuchAlgorithmException
+</pre>
+</font>
+</td>
+<td valign=top>
+<a href="../jdkdocs/api/java/security/MessageDigest.html" onClick="this.href=getApiDoc('java.security.MessageDigest')"><font color="#660066" size=-1>java.security.MessageDigest</font></a></td>
+</tr>
+</table>
+
+<p>
+Als Argument wird dabei die Bezeichnung des gewünschten Algorithmus
+angegeben. Im JDK 1.2 sind beispielsweise folgende Angaben möglich:
+<ul>
+<li>»SHA«<a name="ixa103455"></a>: Der 160-Bit lange »Secure
+Hash Algorithm« des amerikanischen <a name="ixa103456"><i>National Institute of Standards
+and Technology</i></a>
+<li>»MD5«<a name="ixa103457"></a>: Der 128-Bit lange »Message
+Digest 5« von Ron L. Rivest<a name="ixa103458"></a>
+</ul>
+
+<p>
+Nachdem ein <a href="index_m.html#ixb102580"><font color=#000080><tt>MessageDigest</tt></font></a>-Objekt
+erzeugt wurde, bekommt es die Daten, zu denen die Prüfziffer
+berechnet werden soll, in einzelnen Bytes oder Byte-Arrays durch fortgesetzten
+Aufruf der Methode <a name="ixa103459"><a href="index_u.html#ixb101747"><font color=#000080><tt>update</tt></font></a></a>
+übergeben:
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#EEFFCC">
+<tr>
+<td valign=top width=100%>
+<font color="#660066">
+<pre>
+public void update(byte input)
+public void update(byte[] input)
+public void update(byte[] input, int offset, int len)
+</pre>
+</font>
+</td>
+<td valign=top>
+<a href="../jdkdocs/api/java/security/MessageDigest.html" onClick="this.href=getApiDoc('java.security.MessageDigest')"><font color="#660066" size=-1>java.security.MessageDigest</font></a></td>
+</tr>
+</table>
+
+<p>
+Wurden alle Daten übergeben, kann durch Aufruf von <a name="ixa103460"><a href="index_d.html#ixb102586"><font color=#000080><tt>digest</tt></font></a></a>
+das Ergebnis ermittelt werden:
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#EEFFCC">
+<tr>
+<td valign=top width=100%>
+<font color="#660066">
+<pre>
+public byte[] digest()
+</pre>
+</font>
+</td>
+<td valign=top>
+<a href="../jdkdocs/api/java/security/MessageDigest.html" onClick="this.href=getApiDoc('java.security.MessageDigest')"><font color="#660066" size=-1>java.security.MessageDigest</font></a></td>
+</tr>
+</table>
+
+<p>
+Zurückgegeben wird ein Array von 16 bzw. 20 Byte (im Falle anderer
+Algorithmen möglicherweise auch andere Längen), in dem der
+Message Digest untergebracht ist. Ein Aufruf führt zudem dazu,
+dass der Message Digest zurückgesetzt, also auf den Anfangszustand
+initialisiert, wird.
+
+<p>
+Das folgende Listing zeigt, wie ein Message Digest zu einer beliebigen
+Datei erstellt wird. Sowohl Algorithmus als auch Dateiname werden
+als Kommandozeilenargumente übergeben:
+<a name="listingid048003"></a>
+
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#DDDDDD">
+<tr>
+<td valign=top>
+<font color="#000055">
+<pre>
+<font color="#555555">001 </font><font color="#00AA00">/* Listing4803.java */</font>
+<font color="#555555">002 </font>
+<font color="#555555">003 </font><font color="#0000AA">import</font> java.io.*;
+<font color="#555555">004 </font><font color="#0000AA">import</font> java.security.*;
+<font color="#555555">005 </font>
+<font color="#555555">006 </font><font color="#0000AA">public</font> <font color="#0000AA">class</font> Listing4803
+<font color="#555555">007 </font>{
+<font color="#555555">008 </font> <font color="#00AA00">/**
+<font color="#555555">009 </font> * Konvertiert ein Byte in einen Hex-String.
+<font color="#555555">010 </font> */</font>
+<font color="#555555">011 </font> <font color="#0000AA">public</font> <font color="#0000AA">static</font> String toHexString(<font color="#006699">byte</font> b)
+<font color="#555555">012 </font> {
+<font color="#555555">013 </font> <font color="#006699">int</font> value = (b & 0x7F) + (b < 0 ? 128 : 0);
+<font color="#555555">014 </font> String ret = (value < 16 ? <font color="#0000FF">"0"</font> : <font color="#0000FF">""</font>);
+<font color="#555555">015 </font> ret += Integer.toHexString(value).toUpperCase();
+<font color="#555555">016 </font> <font color="#0000AA">return</font> ret;
+<font color="#555555">017 </font> }
+<font color="#555555">018 </font>
+<font color="#555555">019 </font> <font color="#0000AA">public</font> <font color="#0000AA">static</font> <font color="#006699">void</font> main(String[] args)
+<font color="#555555">020 </font> {
+<font color="#555555">021 </font> <font color="#0000AA">if</font> (args.length < 2) {
+<font color="#555555">022 </font> System.out.println(
+<font color="#555555">023 </font> <font color="#0000FF">"Usage: java Listing4803 md-algorithm filename"</font>
+<font color="#555555">024 </font> );
+<font color="#555555">025 </font> System.exit(0);
+<font color="#555555">026 </font> }
+<font color="#555555">027 </font> <font color="#0000AA">try</font> {
+<font color="#555555">028 </font> <font color="#00AA00">//MessageDigest erstellen</font>
+<font color="#555555">029 </font> MessageDigest md = MessageDigest.getInstance(args[0]);
+<font color="#555555">030 </font> FileInputStream in = <font color="#0000AA">new</font> FileInputStream(args[1]);
+<font color="#555555">031 </font> <font color="#006699">int</font> len;
+<font color="#555555">032 </font> <font color="#006699">byte</font>[] data = <font color="#0000AA">new</font> <font color="#006699">byte</font>[1024];
+<font color="#555555">033 </font> <font color="#0000AA">while</font> ((len = in.read(data)) > 0) {
+<font color="#555555">034 </font> <font color="#00AA00">//MessageDigest updaten</font>
+<font color="#555555">035 </font> md.update(data, 0, len);
+<font color="#555555">036 </font> }
+<font color="#555555">037 </font> in.close();
+<font color="#555555">038 </font> <font color="#00AA00">//MessageDigest berechnen und ausgeben</font>
+<font color="#555555">039 </font> <font color="#006699">byte</font>[] result = md.digest();
+<font color="#555555">040 </font> <font color="#0000AA">for</font> (<font color="#006699">int</font> i = 0; i < result.length; ++i) {
+<font color="#555555">041 </font> System.out.print(toHexString(result[i]) + <font color="#0000FF">" "</font>);
+<font color="#555555">042 </font> }
+<font color="#555555">043 </font> System.out.println();
+<font color="#555555">044 </font> } <font color="#0000AA">catch</font> (Exception e) {
+<font color="#555555">045 </font> System.err.println(e.toString());
+<font color="#555555">046 </font> System.exit(1);
+<font color="#555555">047 </font> }
+<font color="#555555">048 </font> }
+<font color="#555555">049 </font>}</pre>
+</font>
+</td>
+<td valign=top align=right>
+<a href="../examples/Listing4803.java"><font color="#000055" size=-1>Listing4803.java</font></a></td>
+</tr>
+</table>
+<i>
+Listing 48.3: Erstellen eines Message Digests</i></p>
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100%>
+<tr>
+<td width=1 align=left valign=top bgcolor="#000077"><img src="trp1_1.gif"></td>
+<td><img src="trp1_1.gif" width=2></td>
+<td valign=top width=1000>
+
+<p>
+Im Paket <a href="index_j.html#ixb100601"><font color=#000080><tt>java.security</tt></font></a>
+gibt es zwei Klassen, die einen Message Digest mit einem Stream kombinieren.
+<a href="index_d.html#ixb101032"><font color=#000080><tt>DigestInputStream</tt></font></a>
+ist ein Eingabe-Stream, der beim Lesen von Bytes parallel deren Message
+Digest berechnet; <a href="index_d.html#ixb101031"><font color=#000080><tt>DigestOutputStream</tt></font></a>
+führt diese Funktion beim Schreiben aus. Beide übertragen
+die eigentlichen Bytes unverändert und können dazu verwendet
+werden, in einer Komposition von Streams »nebenbei« einen
+Message Digest zu berechnen.</td>
+<td><img src="trp1_1.gif" width=2></td>
+<td valign=top>
+<table border=0 cellspacing=0 cellpadding=1 width=100% bgcolor="#000077">
+<tr>
+<td><font color="#FFFFFF"> Hinweis </font></td>
+</tr>
+</table>
+</td>
+<td width=1 align=left valign=top bgcolor="#000077"><img src="trp1_1.gif"></td>
+</tr>
+</table>
+
+
+<!-- Section -->
+<a name="sectlevel4id048001003001"></a>
+<h4>Authentifizierung </h4>
+
+<p>
+Ein wichtiges Anwendungsgebiet von Message Digests ist die Authentifizierung,
+d.h. die Überprüfung, ob die Person oder Maschine, mit der
+kommuniziert werden soll, tatsächlich »echt« ist (also
+die ist, die sie vorgibt zu sein). Eine Variante, bei der ein Anwender
+sich mit einem Benutzernamen und Paßwort autorisiert, kann mit
+Hilfe eines Message Digests in folgender Weise realisiert werden:
+<ul>
+<li>Zunächst wird vom System ein Benutzername vergeben.
+<li>Beim ersten Anmelden gibt der Anwender den Benutzernamen und ein
+von ihm vergebenes Paßwort ein.
+<li>Das System berechnet den Message Digest für das Paßwort
+und speichert ihn zusammen mit dem Benutzernamen in der Benutzerdatenbank
+ab.
+<li>Bei jedem weiteren Anmeldeversuch berechnet das System den Message
+Digest zum eingegebenen Paßwort und vergleicht ihn mit dem in
+der Benutzerdatenbank zu diesem Benutzernamen gespeicherten. Sind
+beide identisch, wird der Zugang gewährt, andernfalls wird er
+verweigert.
+</ul>
+
+<p>
+Bemerkenswert daran ist, dass das System nicht die Paßwörter
+selbst speichert, auch nicht in verschlüsselter Form. Ein Angriff
+auf die Benutzerdatenbank mit dem Versuch, gespeicherte Paßwörter
+zu entschlüsseln, ist daher nicht möglich. Eine bekannte
+(und leider schon oft erfolgreich praktizierte) Methode des Angriffs
+besteht allerdings darin, Message Digests zu allen Einträgen
+in großen Wörterbüchern berechnen zu lassen, und sie
+mit den Einträgen der Benutzerdatenbank zu vergleichen. Das ist
+einer der Gründe dafür, weshalb als Paßwörter
+niemals Allerweltsnamen oder einfache, in Wörterbüchern
+verzeichnete, Begriffe verwendet werden sollten.
+
+<!-- Section -->
+
+<a name="sectlevel4id048001003002"></a>
+<h4>»Unwissende« Beweise </h4>
+
+<p>
+Eine weitere Anwendung von Message Digests besteht darin, die Existenz
+von Geheimnissen oder den Nachweis der Kenntnis bestimmter Sachverhalte
+nachzuweisen, ohne deren Inhalt preiszugeben - selbst nicht eigentlich
+vertrauenswürdigen Personen. Dies wird in Bruce Schneier's Buch
+als <a name="ixa103461"><i>Zero-Knowledge Proof</i></a> bezeichnet
+und funktioniert so:
+<ul>
+<li>A speichert das Geheimnis in elektronischer Form und berechnet
+den Message Digest dazu.
+<li>A deponiert das Geheimnis an einer Stelle, die für Dritte
+unerreichbar ist.
+<li>A übergibt den Message Digest zum Zeitpunkt X einem Notar,
+der Inhalt und Eingangsdatum bestätigt und urkundlich festhält.
+Alternativ kann A den Message Digest auch in der regionalen Tagespresse
+veröffentlichen und sich den Zeitungsausschnitt an die Wand hängen.
+</ul>
+
+<p>
+Das Geheimnis ist nicht veröffentlicht, der Nachweis für
+seine Existenz zum Zeitpunkt X aber erbracht. Muß A Jahre später
+die Existenz dieser Informationen nachweisen, holt es die Diskette
+mit dem Geheimnis aus dem Tresor, berechnet den Message Digest erneut
+und zeigt dessen Übereinstimmung mit dem seinerzeit in der Zeitung
+veröffentlichten.
+
+<!-- Section -->
+
+<a name="sectlevel4id048001003003"></a>
+<h4>Fingerprints<a name="ixa103462"></a><a name="ixa103463"></a> </h4>
+
+<p>
+Eine weitere Anwendung von Message Digests besteht im Erstellen von
+Fingerprints (also digitalen Fingerabdrücken) zu öffentlichen
+Schlüsseln (was das genau ist, wird in <a href="k100303.html#publickeykrypto">Abschnitt 48.1.5</a>
+erklärt). Um die Korrektheit eines öffentlichen Schlüssels
+nachzuweisen, wird daraus ein Message Digest berechnet und als digitaler
+Fingerabdruck an prominenter Stelle veröffentlicht (beispielsweise
+in den Signaturen der E-Mails des Schlüsselinhabers).
+
+<p>
+Soll vor der Verwendung eines öffentlichen Schlüssel überprüft
+werden, ob dieser auch wirklich dem gewünschten Inhaber gehört,
+ist lediglich der (durch das Schlüsselverwaltungsprogramm adhoc
+berechnete) Fingerprint des öffentlichen Schlüssels mit
+dem in der E-Mail veröffentlichten zu vergleichen. Stimmen beide
+überein, erhöht sich das Vertrauen in die Authentizität
+des öffentlichen Schlüssels und er kann verwendet werden.
+Stimmen sie nicht überein, sollte der Schlüssel auf keinen
+Fall verwendet werden. Wir werden in <a href="k100303.html#zertifikate">Abschnitt 48.1.7</a>
+noch einmal auf diese Problematik zurückkommen.
+
+<!-- Section -->
+
+<a name="kryptozufallszahlen"></a>
+<h3>48.1.4 Kryptografische Zufallszahlen </h3>
+
+<p>
+Zufallszahlen wurden bereits in <a href="k100108.html#zufallszahlen">Abschnitt 16.1</a>
+vorgestellt. In kryptografischen Anwendungen werden allerdings bessere
+Zufallszahlengeneratoren benötigt, als in den meisten Programmiersprachen
+implementiert sind. Einerseits sollte die Verteilung der Zufallszahlen
+besser sein, andererseits wird eine größere Periodizität
+gefordert (das ist die Länge der Zahlensequenz, nach der sich
+eine Folge von Zufallszahlen frühestens wiederholt). Zudem muss
+die nächste Zahl der Folge praktisch unvorhersagbar sein - selbst
+wenn deren Vorgänger bekannt sind.
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100%>
+<tr>
+<td width=1 align=left valign=top bgcolor="#000077"><img src="trp1_1.gif"></td>
+<td><img src="trp1_1.gif" width=2></td>
+<td valign=top width=1000>
+
+<p>
+Es ist bekannt, dass sich mit deterministischen Maschinen (wie Computerprogramme
+es beispielsweise sind) keine <i>echten</i> Zufallszahlen erzeugen
+lassen. Eigentlich müssten wir daher von <a name="ixa103464"><i>Pseudo-Zufallszahlen</i></a>
+sprechen, um darauf hinzuweisen, dass unsere Zufallszahlengeneratoren
+stets deterministische Zahlenfolgen erzeugen. Mit der zusätzlichen
+Forderung kryptografischer Zufallszahlen, praktisch unvorhersagbare
+Zahlenfolgen zu generieren, wird diese Unterscheidung an dieser Stelle
+unbedeutend. Tatsächlich besteht der wichtigste Unterschied zu
+»echten« Zufallsgeneratoren nur noch darin, dass deren Folgen
+nicht zuverlässig <i>reproduziert</i> werden können (was
+bei unseren Pseudo-Zufallszahlen sehr wohl der Fall ist). Wir werden
+im folgenden daher den Begriff »Zufallszahl« auch dann verwenden,
+wenn eigentlich »Pseudo-Zufallszahl« gemeint ist.</td>
+<td><img src="trp1_1.gif" width=2></td>
+<td valign=top>
+<table border=0 cellspacing=0 cellpadding=1 width=100% bgcolor="#000077">
+<tr>
+<td><font color="#FFFFFF"> Hinweis </font></td>
+</tr>
+</table>
+</td>
+<td width=1 align=left valign=top bgcolor="#000077"><img src="trp1_1.gif"></td>
+</tr>
+</table>
+
+<p>
+Die Klasse <a name="ixa103465"><a href="index_s.html#ixb102591"><font color=#000080><tt>SecureRandom</tt></font></a></a>
+des Pakets <a href="index_j.html#ixb100601"><font color=#000080><tt>java.security</tt></font></a>
+implementiert einen Generator für kryptografische Zufallszahlen,
+der die oben genannten Eigenschaften besitzt. Er wird durch Aufruf
+der Methode <a name="ixa103466"><a href="index_g.html#ixb102581"><font color=#000080><tt>getInstance</tt></font></a></a>
+ähnlich instanziert wie ein Message Digest:
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#EEFFCC">
+<tr>
+<td valign=top width=100%>
+<font color="#660066">
+<pre>
+public static SecureRandom getInstance(String algorithm)
+ throws NoSuchAlgorithmException
+</pre>
+</font>
+</td>
+<td valign=top>
+<a href="../jdkdocs/api/java/security/MessageDigest.html" onClick="this.href=getApiDoc('java.security.MessageDigest')"><font color="#660066" size=-1>java.security.MessageDigest</font></a></td>
+</tr>
+</table>
+
+<p>
+Als Algorithmus ist beispielsweise »SHA1PRNG« im JDK 1.2
+implementiert. Hierbei entstehen die Zufallszahlen aus der Berechnung
+eines Message Digests für eine Pseudonachricht, die aus einer
+Kombination aus Initialwert und fortlaufendem Zähler besteht.
+Die Klasse <a href="index_s.html#ixb102591"><font color=#000080><tt>SecureRandom</tt></font></a>
+stellt weiterhin die Methoden <a name="ixa103467"><a href="index_s.html#ixb102592"><font color=#000080><tt>setSeed</tt></font></a></a>
+und <a name="ixa103468"><a href="index_n.html#ixb102593"><font color=#000080><tt>nextBytes</tt></font></a></a>
+zur Verfügung:
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#EEFFCC">
+<tr>
+<td valign=top width=100%>
+<font color="#660066">
+<pre>
+public void setSeed(long seed)
+
+public void nextBytes(byte[] bytes)
+</pre>
+</font>
+</td>
+<td valign=top>
+<a href="../jdkdocs/api/java/security/MessageDigest.html" onClick="this.href=getApiDoc('java.security.MessageDigest')"><font color="#660066" size=-1>java.security.MessageDigest</font></a></td>
+</tr>
+</table>
+
+<p>
+Mit <a href="index_s.html#ixb102592"><font color=#000080><tt>setSeed</tt></font></a>
+wird der Zufallszahlengenerator initialisiert. Die Methode sollte
+nach der Konstruktion einmal aufgerufen werden, um den Initialwert
+festzulegen (andernfalls macht es der Generator selbst). Gleiche Initialwerte
+führen auch zu gleichen Folgen von Zufallszahlen. Mit <a href="index_n.html#ixb102593"><font color=#000080><tt>nextBytes</tt></font></a>
+wird eine beliebig lange Folge von Zufallszahlen erzeugt und in dem
+als Argument übergebenen Byte-Array zurückgegeben.
+
+<p>
+Das folgende Listing instanziert einen Zufallszahlengenerator und
+erzeugt zehn Folgen zu je acht Bytes Zufallszahlen, die dann auf dem
+Bildschirm ausgegeben werden:
+<a name="listingid048004"></a>
+
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#DDDDDD">
+<tr>
+<td valign=top>
+<font color="#000055">
+<pre>
+<font color="#555555">001 </font><font color="#00AA00">/* Listing4804.java */</font>
+<font color="#555555">002 </font>
+<font color="#555555">003 </font><font color="#0000AA">import</font> java.security.*;
+<font color="#555555">004 </font>
+<font color="#555555">005 </font><font color="#0000AA">public</font> <font color="#0000AA">class</font> Listing4804
+<font color="#555555">006 </font>{
+<font color="#555555">007 </font> <font color="#00AA00">/**
+<font color="#555555">008 </font> * Konvertiert ein Byte in einen Hex-String.
+<font color="#555555">009 </font> */</font>
+<font color="#555555">010 </font> <font color="#0000AA">public</font> <font color="#0000AA">static</font> String toHexString(<font color="#006699">byte</font> b)
+<font color="#555555">011 </font> {
+<font color="#555555">012 </font> <font color="#006699">int</font> value = (b & 0x7F) + (b < 0 ? 128 : 0);
+<font color="#555555">013 </font> String ret = (value < 16 ? <font color="#0000FF">"0"</font> : <font color="#0000FF">""</font>);
+<font color="#555555">014 </font> ret += Integer.toHexString(value).toUpperCase();
+<font color="#555555">015 </font> <font color="#0000AA">return</font> ret;
+<font color="#555555">016 </font> }
+<font color="#555555">017 </font>
+<font color="#555555">018 </font> <font color="#0000AA">public</font> <font color="#0000AA">static</font> <font color="#006699">void</font> main(String[] args)
+<font color="#555555">019 </font> {
+<font color="#555555">020 </font> <font color="#0000AA">try</font> {
+<font color="#555555">021 </font> <font color="#00AA00">//Zufallszahlengenerator erstellen</font>
+<font color="#555555">022 </font> SecureRandom rand = SecureRandom.getInstance(<font color="#0000FF">"SHA1PRNG"</font>);
+<font color="#555555">023 </font> <font color="#006699">byte</font>[] data = <font color="#0000AA">new</font> <font color="#006699">byte</font>[8];
+<font color="#555555">024 </font> <font color="#00AA00">//Startwert initialisieren</font>
+<font color="#555555">025 </font> rand.setSeed(0x123456789ABCDEF0L);
+<font color="#555555">026 </font> <font color="#0000AA">for</font> (<font color="#006699">int</font> i = 0; i < 10; ++i) {
+<font color="#555555">027 </font> <font color="#00AA00">//Zufallszahlen berechnen</font>
+<font color="#555555">028 </font> rand.nextBytes(data);
+<font color="#555555">029 </font> <font color="#00AA00">//Ausgeben</font>
+<font color="#555555">030 </font> <font color="#0000AA">for</font> (<font color="#006699">int</font> j = 0; j < 8; ++j) {
+<font color="#555555">031 </font> System.out.print(toHexString(data[j]) + <font color="#0000FF">" "</font>);
+<font color="#555555">032 </font> }
+<font color="#555555">033 </font> System.out.println();
+<font color="#555555">034 </font> }
+<font color="#555555">035 </font> } <font color="#0000AA">catch</font> (Exception e) {
+<font color="#555555">036 </font> System.err.println(e.toString());
+<font color="#555555">037 </font> System.exit(1);
+<font color="#555555">038 </font> }
+<font color="#555555">039 </font> }
+<font color="#555555">040 </font>}</pre>
+</font>
+</td>
+<td valign=top align=right>
+<a href="../examples/Listing4804.java"><font color="#000055" size=-1>Listing4804.java</font></a></td>
+</tr>
+</table>
+<i>
+Listing 48.4: Erzeugen kryptografischer Zufallszahlen</i></p>
+
+
+<!-- Section -->
+<a name="publickeykrypto"></a>
+<h3>48.1.5 <a name="ixa103469">Public-Key-Verschlüsselung</a></h3>
+
+<p>
+Eines der Hauptprobleme bei der Anwendung symmetrischer Verschlüsselungen
+ist das der <i>Schlüsselübertragung</i>. Eine verschlüsselte
+Nachricht kann nämlich nur dann sicher übertragen werden,
+wenn der Schlüssel auf einem sicheren Weg vom Sender zum Empfänger
+gelangt. Je nach räumlicher, technischer oder organisatorischer
+Distanz zwischen beiden Parteien kann das unter Umständen sehr
+schwierig sein.
+
+<p>
+Mit der Erfindung der Public-Key-Kryptosysteme wurde dieses Problem
+Mitte der siebziger Jahre entscheidend entschärft. Bei einem
+solchen System wird nicht ein einzelner Schlüssel verwendet,
+sondern diese treten immer paarweise auf. Einer der Schlüssel
+ist öffentlich und dient dazu, Nachrichten zu verschlüsseln.
+Der anderen Schlüssel ist privat. Er dient dazu, mit dem öffentlichen
+Schlüssel verschlüsselte Nachrichten zu entschlüsseln.
+
+<p>
+Das Schlüsselübertragungsproblem wird nun dadurch gelöst,
+dass ein potentieller Empfänger verschlüsselter Nachrichten
+seinen öffentlichen Schlüssel an allgemein zugänglicher
+Stelle publiziert. Seinen privaten Schlüssel hält er dagegen
+geheim. Will ein Sender eine geheime Nachricht an den Empfänger
+übermitteln, verwendet er dessen allgemein bekannten öffentlichen
+Schlüssel und überträgt die verschlüsselte Nachricht
+an den Empfänger. Nur mit Hilfe seines privaten Schlüssels
+kann dieser nun die Nachricht entziffern.
+
+<p>
+Das Verfahren funktioniert natürlich nur, wenn der öffentliche
+Schlüssel nicht dazu taugt, die mit ihm verschlüsselte Nachricht
+zu entschlüsseln. Auch darf es nicht möglich sein, mit vertretbarem
+Aufwand den privaten Schlüssel aus dem öffentlichen herzuleiten.
+Beide Probleme sind aber gelöst, und es gibt sehr leistungsfähige
+und sichere Verschlüsselungsverfahren, die auf dem Prinzip der
+Public-Key-Kryptographie beruhen. Bekannte Beispiele für solche
+Systeme sind <a name="ixa103470"><i>RSA</i></a> (benannt nach ihren
+Erfindern Rivest, Shamir und Adleman) und <a name="ixa103471"><i>DSA</i></a>
+(<a name="ixa103472"><i>Digital Signature Architecture</i></a>).
+
+<p>
+Asymmetrische Kryptosysteme haben meist den Nachteil, sehr viel langsamer
+zu arbeiten als symmetrische. In der Praxis kombiniert man daher beide
+Verfahren und kommt so zu hybriden Kryptosystemen <a name="ixa103473"></a>.
+Um eine geheime Nachricht von A nach B zu übertragen, wird dabei
+in folgenden Schritten vorgegangen:
+<ul>
+<li>Mit Hilfe eines kryptografischen Zufallszahlengenerators erzeugt
+A einen Einmalschlüssel (der auch als <i>Session Key</i> bezeichnet
+wird).
+<li>A verschlüsselt die geheime Nachricht mit Hilfe des Session
+Keys und eines (schnellen) symmetrischen Verfahrens.
+<li>A verschlüsselt den Session-Key mit dem öffentlichen
+Schlüssel von B auf der Basis des vereinbarten Public-Key-Kryptoverfahrens
+und sendet ihn zusammen mit der verschlüsselten Nachricht an
+B.
+<li>B entschlüsselt den Session-Key mit seinem privaten Schlüssel.
+<li>B entschlüsselt die geheime Nachricht mit dem Session Key.
+</ul>
+
+<p>
+Fast alle Public-Key-Kryptosysteme arbeiten in dieser Weise als Hybridsysteme.
+Andernfalls würde das Ver- und Entschlüsseln bei großen
+Nachrichten viel zu lange dauern. Ein bekanntes Beispiel für
+ein solches System ist <a name="ixa103474"><i>PGP</i></a> (<a name="ixa103475"><i>Pretty
+Good Privacy</i></a>) von Phil Zimmermann.
+Es wird vorwiegend beim Versand von E-Mails verwendet und gilt als
+sehr sicher. Freie Implementierungen stehen für viele Plattformen
+zu Verfügung.
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100%>
+<tr>
+<td width=1 align=left valign=top bgcolor="#000077"><img src="trp1_1.gif"></td>
+<td><img src="trp1_1.gif" width=2></td>
+<td valign=top width=1000>
+
+<p>
+Das Ver- und Entschlüsseln von Daten mit Hilfe von asymmetrischen
+Verfahren war bis zur Version 1.3 nicht im JDK enthalten. Zwar gab
+es als Erweiterung zum JDK die <a name="ixa103476"><i>JCE</i></a>
+(<a name="ixa103477"><i>JAVA Cryptography Extension</i></a>), doch
+diese durfte nur in den USA und Kanada verwendet werden. Mit dem JDK
+1.4 wurden die JCE, sowie die <a name="ixa103478"><i>Java Secure Socket Extension</i></a>
+(<a name="ixa103479"><i>JSSE</i></a>) und der <a name="ixa103480"><i>Java Authentication
+and Authorization Service</i></a> (<a name="ixa103481"><i>JAAS</i></a>)
+fester Bestandteil des JDK. Dennoch gibt es nach wie vor einige Einschränkungen
+in der Leistungsfähigkeit der einzelnen Pakete, die auf US-Exportbeschränkungen
+zurückzuführen sind. Details können in der Dokumentation
+zum JDK 1.4 oder neueren Versionen nachgelesen werden.</td>
+<td><img src="trp1_1.gif" width=2></td>
+<td valign=top>
+<table border=0 cellspacing=0 cellpadding=1 width=100% bgcolor="#000077">
+<tr>
+<td><font color="#FFFFFF"> Hinweis </font></td>
+</tr>
+</table>
+</td>
+<td width=1 align=left valign=top bgcolor="#000077"><img src="trp1_1.gif"></td>
+</tr>
+</table>
+
+
+<!-- Section -->
+<a name="digitaleunterschriften"></a>
+<h3>48.1.6 Digitale Unterschriften<a name="ixa103482"></a> </h3>
+
+<p>
+Ein großer Vorteil der Public-Key-Kryptosysteme ist es, dass
+sie Möglichkeiten zum Erstellen und Verifizieren von <i>digitalen
+Unterschriften</i> bieten. Eine digitale Unterschrift besitzt folgende
+wichtige Eigenschaften:
+<ul>
+<li>Sie stellt sicher, dass eine Nachricht von einem ganz bestimmten
+und eindeutig identifizierbaren Absender stammt.
+<li>Sie stellt sicher, dass die Nachricht intakt ist und nicht während
+der Übertragung verändert wurde.
+</ul>
+
+<p>
+Beide Eigenschaften sind für den elektronischen Datenverkehr
+so fundamental wie die Verschlüsselung selbst. Technisch basieren
+sie darauf, dass die Funktionsweise eines Public-Key-Kryptosystems
+sich umkehren läßt. Daß es also möglich ist,
+Nachrichten, die mit einem privaten Schlüssel verschlüsselt
+wurden, mit Hilfe des korrespondierenden öffentlichen Schlüssels
+zu entschlüsseln.
+
+<p>
+Im Prinzip funktioniert eine digitale Unterschrift so:
+
+<p>
+Will A eine Nachricht signieren, so verschlüsselt er sie mit
+seinem privaten Schlüssel. Jeder, der im Besitz des öffentlichen
+Schlüssel von A ist, kann sie entschlüsseln. Da nur A seinen
+eigenen privaten Schlüssel kennt, <i>muss</i> die Nachricht von
+ihm stammen. Da es keinem Dritten möglich ist, die entschlüsselte
+Nachricht zu modifizieren und sie erneut mit dem privaten Schlüssel
+von A zu verschlüsseln, ist auch die Integrität der Nachricht
+sichergestellt. Den Vorgang des Überprüfens der Integrität
+und Authentizität bezeichnet man als <i>Verifizieren</i> einer
+digitalen Unterschrift.
+
+<p>
+In der Praxis sind die Dinge wieder einmal etwas komplizierter, denn
+die Langsamkeit der asymmetrischen Verfahren erfordert eine etwas
+aufwändigere Vorgehensweise. Statt die komplette Nachricht zu
+verschlüsseln, berechnet A zunächst einen Message Digest
+der Nachricht. Diesen verschlüsselt A mit seinem privaten Schlüssel
+und versendet ihn als Anhang zusammen mit der Nachricht. Ein Empfänger
+wird die Nachricht lesen, ihren Message Digest bilden, und diesen
+dann mit dem (mit Hilfe des öffentlichen Schlüssels von
+A entschlüsselten) Original-Message-Digest vergleichen. Stimmen
+beide überein, ist die Signatur gültig. Die Nachricht stammt
+dann sicher von A und wurde nicht verändert. Stimmen sie nicht
+überein, wurde sie ver- oder gefälscht.
+
+<p>
+Das JDK stellt Klassen zum Erzeugen und Verifizieren digitaler Unterschriften
+zur Verfügung. Wir wollen uns beide Verfahren in den folgenden
+Abschnitten ansehen. Zuvor wird allerdings ein Schlüsselpaar
+benötigt, dessen Generierung im nächsten Abschnitt besprochen
+wird.
+
+<!-- Section -->
+
+<a name="sectlevel4id048001006001"></a>
+<h4>Erzeugen und Verwalten von Schlüsseln mit dem JDK </h4>
+
+<p>
+Um digitale Unterschriften erzeugen und verifizieren zu können,
+müssen Schlüsselpaare erzeugt und verwaltet werden. Seit
+dem JDK 1.2 wird dazu eine Schlüsseldatenbank verwendet, auf
+die mit Hilfe des Hilfsprogramms <a name="ixa103483"><a href="index_k.html#ixb102608"><font color=#000080><tt>keytool</tt></font></a></a>
+zugegriffen werden kann. <a href="index_k.html#ixb102608"><font color=#000080><tt>keytool</tt></font></a>
+kann Schlüsselpaare erzeugen, in der Datenbank speichern und
+zur Bearbeitung wieder herausgeben. Zudem besitzt es die Fähigkeit,
+Zertifikate (siehe <a href="k100303.html#zertifikate">Abschnitt 48.1.7</a>)
+zu importieren und in der Datenbank zu verwalten. Die Datenbank hat
+standardmäßig den Namen ».keystore«<a name="ixa103484"></a>
+und liegt im Home-Verzeichnis des angemeldeten Benutzers (bzw. im
+Verzeichnis <font color="#660099">\windows</font> eines Windows-95/98-Einzelplatzsystems).
+
+<p>
+<a href="index_k.html#ixb102608"><font color=#000080><tt>keytool</tt></font></a>
+ist ein kommandozeilenbasiertes Hilfsprogramm, das eine große
+Anzahl an Funktionen bietet. Wir wollen hier nur die für den
+Umgang mit digitalen Unterschriften benötigten betrachten. Eine
+vollständige Beschreibung findet sich in der Tool-Dokumentation
+des JDK.
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100%>
+<tr>
+<td width=1 align=left valign=top bgcolor="#FF9900"><img src="trp1_1.gif"></td>
+<td><img src="trp1_1.gif" width=1></td>
+<td width=1 align=left valign=top bgcolor="#FF9900"><img src="trp1_1.gif"></td>
+<td><img src="trp1_1.gif" width=2></td>
+<td valign=top width=1000>
+
+<p>
+Im JDK 1.1 gab es <a href="index_k.html#ixb102608"><font color=#000080><tt>keytool</tt></font></a>
+noch nicht. Statt dessen wurde das Programm <a name="ixa103485"><a href="index_j.html#ixb102610"><font color=#000080><tt>javakey</tt></font></a></a>
+zur Schlüsselverwaltung verwendet. Hier soll nur das Security-API
+des JDK 1.2 und darüber betrachtet werden. Wir wollen daher auf
+<a href="index_j.html#ixb102610"><font color=#000080><tt>javakey</tt></font></a>
+und andere Eigenschaften der Prä-1.2-JDKs nicht eingehen.</td>
+<td><img src="trp1_1.gif" width=2></td>
+<td valign=top>
+<table border=0 cellspacing=0 cellpadding=1 width=100% bgcolor="#FF9900">
+<tr>
+<td><font color="#FFFFFF"> JDK1.1-6.0 </font></td>
+</tr>
+</table>
+</td>
+<td width=1 align=left valign=top bgcolor="#FF9900"><img src="trp1_1.gif"></td>
+</tr>
+</table>
+
+<p>
+Um ein neues Schlüsselpaar zu erzeugen, ist <a href="index_k.html#ixb102608"><font color=#000080><tt>keytool</tt></font></a>
+mit dem Kommando <font color="#000077"><tt>-genkey</tt></font> aufzurufen.
+Zusätzlich müssen weitere Parameter angegeben werden:
+<ul>
+<li>Mit <font color="#000077"><tt>-alias</tt></font> wird der Aliasname
+des neu zu generierenden Eintrags angegeben. Er dient als eindeutiger
+Bezeichner und wird künftig immer dann gebraucht, wenn auf diesen
+Eintrag zugegriffen werden soll.
+<li>Mit <font color="#000077"><tt>-dname</tt></font> wird ein strukturierter
+Name für den Schlüsselbesitzer angegeben. Er besteht aus
+mehreren Teilen, die durch Kommata voneinander getrennt sind. Jeder
+einzelne Teil besteht aus einer mnemonischen Bezeichnung, gefolgt
+von einem Gleichheitszeichen und dem zugehörigen Wert. Einzelne
+Bestandteile können ausgelassen werden. Der strukturierte Name
+kann folgende Teile enthalten :
+<ul>
+<li><font color="#000077"><tt>CN</tt></font>: Üblicher Name (Common
+Name)
+<li><font color="#000077"><tt>OU</tt></font>: Organisatorische Einheit
+(Organisational Unit)
+<li><font color="#000077"><tt>O</tt></font>: Unternehmen/Organisation
+(Organisation)
+<li><font color="#000077"><tt>L</tt></font>: Stadt (Location)
+<li><font color="#000077"><tt>S</tt></font>: Bundesstaat (State)
+<li><font color="#000077"><tt>C</tt></font>: Land (Countrycode)
+</ul>
+</ul>
+
+<p>
+Die Optionen für den Schlüssel- und Signaturtyp (<font color="#000077"><tt>-keyalg</tt></font>
+und <font color="#000077"><tt>-sigalg</tt></font>) sowie die Schlüssellänge
+(<font color="#000077"><tt>-keysize</tt></font>) und die Gültigkeitsdauer
+(<font color="#000077"><tt>-validity</tt></font>) sollen unspezifiziert
+bleiben (und daher gemäß den eingebauten Voreinstellungen
+belegt werden). Zusätzlich besitzt jede Schlüsseldatenbank
+ein Zugriffspaßwort, das mit der Option <font color="#000077"><tt>-storepass</tt></font>
+(oder alternativ in der Eingabezeile) angegeben wird. Schließlich
+besitzt jeder private Schlüssel ein Schlüsselpaßwort,
+das mit der Option <font color="#000077"><tt>-keypass</tt></font>
+(oder über die Eingabezeile) angegeben wird.
+
+<p>
+Wir wollen zunächst ein Schlüsselpaar mit dem Aliasnamen
+»hjp3« erzeugen und mit dem Paßwort »hjp3key«
+vor unberechtigtem Zugriff schützen. Die Schlüsseldatenbank
+wird beim Anlegen des ersten Schlüssel automatisch erzeugt und
+bekommt das Paßwort »hjp3ks« zugewiesen. Wir verwenden
+dazu folgendes Kommando (bitte haben Sie etwas Geduld, das Programm
+benötigt eine ganze Weile):
+<font color="#333300">
+<pre>
+c:\--><b>keytool -genkey -alias hjp3 -dname
+ "CN=Guido Krueger,O=Computer Books,C=de"</b>
+Enter keystore password: <b>hjp3ks</b>
+Enter key password for <hjp3>
+ (RETURN if same as keystore password): <b>hjp3key</b>
+</pre>
+</font>
+
+<p>
+Nun wird ein DSA-Schlüsselpaar der Länge 1024 mit einer
+Gültigkeitsdauer von 90 Tagen erzeugt. Zur Überprüfung
+kann das Kommando <font color="#000077"><tt>-list</tt></font> (in
+Kombination mit <font color="#000077"><tt>-v</tt></font>) angegeben
+werden:
+<font color="#333300">
+<pre>
+C:\---><b>keytool -alias hjp3 -list -v</b>
+Enter keystore password: <b>hjp3ks</b>
+Alias name: hjp3
+Creation date: Sun Dec 26 17:11:36 GMT+01:00 1999
+Entry type: keyEntry
+Certificate chain length: 1
+Certificate[1]:
+Owner: CN=Guido Krueger, O=Computer Books, C=de
+Issuer: CN=Guido Krueger, O=Computer Books, C=de
+Serial number: 38663e2d
+Valid from: Sun Dec 26 17:11:25 GMT+01:00 1999 until: Sat Mar 25 17:11:25 GMT+01:00 2000
+Certificate fingerprints:
+ MD5: D5:73:AB:06:25:16:7F:36:27:DF:CF:9D:C9:DE:AD:35
+ SHA1: E0:A4:39:65:60:06:48:61:82:5E:8C:47:8A:2B:04:A4:6D:43:56:05
+</pre>
+</font>
+
+<p>
+Gleichzeitig wird ein <a name="ixa103486"><i>Eigenzertifikat</i></a>
+für den gerade generierten öffentlichen Schlüssel erstellt.
+Es kann dazu verwendet werden, digitale Unterschriften zu verifizieren.
+Jedes Zertifikat in der Schlüsseldatenbank (und damit jeder eingebettete
+öffentliche Schlüssel) gilt im JDK automatisch als vertrauenswürdig.
+
+
+<!-- Section -->
+<a name="sectlevel4id048001006002"></a>
+<h4>Erstellen einer digitalen Unterschrift </h4>
+
+<p>
+Wie erwähnt, entsteht eine digitale Unterschrift zu einer Nachricht
+durch das Verschlüsseln des Message Digests der Nachricht mit
+dem privaten Schlüssel des Unterzeichnenden. Nachdem wir nun
+ein Schlüsselpaar erstellt haben, können wir es nun dazu
+verwenden, beliebige Dateien zu signieren.
+
+<p>
+Dazu wird die Klasse <a name="ixa103487"><a href="index_s.html#ixb102612"><font color=#000080><tt>Signature</tt></font></a></a>
+des Pakets <a href="index_j.html#ixb100601"><font color=#000080><tt>java.security</tt></font></a>
+verwendet. Ihre Programmierschnittstelle ähnelt der der Klasse
+<a href="index_m.html#ixb102580"><font color=#000080><tt>MessageDigest</tt></font></a>:
+zunächst wird ein Objekt mit Hilfe einer Factory-Methode beschafft,
+dann wird es initialisiert, und schließlich werden die Daten
+durch wiederholten Aufruf von <a href="index_u.html#ixb101747"><font color=#000080><tt>update</tt></font></a>
+übergeben. Nachdem alle Daten angegeben wurden, berechnet ein
+letzter Methodenaufruf das Resultat.
+
+<p>
+Ein <a href="index_s.html#ixb102612"><font color=#000080><tt>Signature</tt></font></a>-Objekt
+kann wahlweise zum Signieren oder zum Verifizieren verwendet werden.
+Welche der beiden Funktionen aktiviert wird, ist nach der Instanzierung
+durch den Aufruf einer Initialisierungsmethode festzulegen. Ein Aufruf
+von <a name="ixa103488"><a href="index_i.html#ixb102613"><font color=#000080><tt>initSign</tt></font></a></a>
+initialisiert das Objekt zum Signieren, ein Aufruf von <a name="ixa103489"><a href="index_i.html#ixb102614"><font color=#000080><tt>initVerify</tt></font></a></a>
+zum Verifizieren.
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#EEFFCC">
+<tr>
+<td valign=top width=100%>
+<font color="#660066">
+<pre>
+public static Signature getInstance(String algorithm)
+ throws NoSuchAlgorithmException
+
+public final void initSign(PrivateKey privateKey)
+ throws InvalidKeyException
+
+public final void initVerify(PublicKey publicKey)
+ throws InvalidKeyException
+</pre>
+</font>
+</td>
+<td valign=top>
+<a href="../jdkdocs/api/java/security/Signature.html" onClick="this.href=getApiDoc('java.security.Signature')"><font color="#660066" size=-1>java.security.Signature</font></a></td>
+</tr>
+</table>
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100%>
+<tr>
+<td width=1 align=left valign=top bgcolor="#000077"><img src="trp1_1.gif"></td>
+<td><img src="trp1_1.gif" width=2></td>
+<td valign=top width=1000>
+
+<p>
+Als Argument von <a href="index_g.html#ixb102581"><font color=#000080><tt>getInstance</tt></font></a>
+wird der gewünschte Signier-Algorithmus übergeben. Auch
+hier wird - wie an vielen Stellen im Security-API des JDK - eine Strategie
+verfolgt, nach der die verfügbaren Algorithmen konfigurier- und
+austauschbar sind. Dazu wurde ein <i>Provider-Konzept</i><a name="ixa103490"></a>
+entwickelt, mit dessen Hilfe dem API Klassenpakete zur Verfügung
+gestellt werden können, die Funktionalitäten des Security-Pakets
+teilweise oder ganz austauschen. Falls der Provider beim Aufruf von
+<a href="index_g.html#ixb102581"><font color=#000080><tt>getInstance</tt></font></a>
+nicht angegeben wird, benutzt die Methode den Standard-Provider »SUN«,
+der zusammen mit dem JDK ausgeliefert wird. Der zu dem von uns generierten
+Schlüssel passende Algorithmus ist »SHA/DSA«.</td>
+<td><img src="trp1_1.gif" width=2></td>
+<td valign=top>
+<table border=0 cellspacing=0 cellpadding=1 width=100% bgcolor="#000077">
+<tr>
+<td><font color="#FFFFFF"> Hinweis </font></td>
+</tr>
+</table>
+</td>
+<td width=1 align=left valign=top bgcolor="#000077"><img src="trp1_1.gif"></td>
+</tr>
+</table>
+
+<p>
+Die zum Aufruf der init-Methoden benötigten Schlüssel können
+aus der Schlüsseldatenbank beschafft werden. Auf sie kann mit
+Hilfe der Klasse <a name="ixa103491"><a href="index_k.html#ixb102616"><font color=#000080><tt>KeyStore</tt></font></a></a>
+des Pakets <a href="index_j.html#ixb100601"><font color=#000080><tt>java.security</tt></font></a>
+zugegriffen werden. Dazu wird zunächst ein <a href="index_k.html#ixb102616"><font color=#000080><tt>KeyStore</tt></font></a>-Objekt
+instanziert und durch Aufruf von <a href="index_l.html#ixb100707"><font color=#000080><tt>load</tt></font></a>
+mit den Daten aus der Schlüsseldatenbank gefüllt. Mit <a href="index_g.html#ixb100751"><font color=#000080><tt>getKey</tt></font></a>
+kann auf einen privaten Schlüssel zugegriffen werden, mit <a href="index_g.html#ixb102617"><font color=#000080><tt>getCertificate</tt></font></a>
+auf einen öffentlichen:
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#EEFFCC">
+<tr>
+<td valign=top width=100%>
+<font color="#660066">
+<pre>
+public static KeyStore getInstance(String type)
+ throws KeyStoreException
+
+public final Key getKey(String alias, char[] password)
+ throws KeyStoreException,
+ NoSuchAlgorithmException,
+ UnrecoverableKeyException
+
+public final Certificate getCertificate(String alias)
+ throws KeyStoreException
+</pre>
+</font>
+</td>
+<td valign=top>
+<a href="../jdkdocs/api/java/security/KeyStore.html" onClick="this.href=getApiDoc('java.security.KeyStore')"><font color="#660066" size=-1>java.security.KeyStore</font></a></td>
+</tr>
+</table>
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100%>
+<tr>
+<td width=1 align=left valign=top bgcolor="#CC0000"><img src="trp1_1.gif"></td>
+<td><img src="trp1_1.gif" width=1></td>
+<td width=1 align=left valign=top bgcolor="#CC0000"><img src="trp1_1.gif"></td>
+<td><img src="trp1_1.gif" width=2></td>
+<td valign=top width=1000>
+
+<p>
+Das von <a name="ixa103492"><a href="index_g.html#ixb102617"><font color=#000080><tt>getCertificate</tt></font></a></a>
+zurückgegebene Objekt vom Typ <a name="ixa103493"><a href="index_c.html#ixb102618"><font color=#000080><tt>Certificate</tt></font></a></a>
+stammt nicht aus dem Paket <a href="index_j.html#ixb100601"><font color=#000080><tt>java.security</tt></font></a>,
+sondern <a name="ixa103494"><a href="index_j.html#ixb102619"><font color=#000080><tt>java.security.cert</tt></font></a></a>.
+Das in <a href="index_j.html#ixb100601"><font color=#000080><tt>java.security</tt></font></a>
+vorhandene gleichnamige Interface wurde bis zum JDK 1.1 verwendet,
+ab 1.2 aber als <a name="ixa103495"><a href="index_d.html#ixb100161"><font color=#000080><tt>deprecated</tt></font></a></a>
+markiert. Wenn nicht mit qualifizierten Klassennamen gearbeitet wird,
+muss daher die <a href="index_i.html#ixb100169"><font color=#000080><tt>import</tt></font></a>-Anweisung
+für <a href="index_c.html#ixb102618"><font color=#000080><tt>java.security.cert.Certificate</tt></font></a>
+im Quelltext <i>vor</i> der <a href="index_i.html#ixb100169"><font color=#000080><tt>import</tt></font></a>-Anweisung
+von <a href="index_c.html#ixb102618"><font color=#000080><tt>java.security.Certificate</tt></font></a>
+stehen.</td>
+<td><img src="trp1_1.gif" width=2></td>
+<td valign=top>
+<table border=0 cellspacing=0 cellpadding=1 width=100% bgcolor="#CC0000">
+<tr>
+<td><font color="#FFFFFF"> Warnung </font></td>
+</tr>
+</table>
+</td>
+<td width=1 align=left valign=top bgcolor="#CC0000"><img src="trp1_1.gif"></td>
+</tr>
+</table>
+
+<p>
+Die Klasse <a href="index_c.html#ixb102618"><font color=#000080><tt>Certificate</tt></font></a>
+besitzt eine Methode <a name="ixa103496"><a href="index_g.html#ixb102620"><font color=#000080><tt>getPublicKey</tt></font></a></a>,
+mit der auf den im Zertifikat enthaltenen öffentlichen Schlüssel
+zugegriffen werden kann:
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#EEFFCC">
+<tr>
+<td valign=top width=100%>
+<font color="#660066">
+<pre>
+public PublicKey getPublicKey()
+</pre>
+</font>
+</td>
+<td valign=top>
+<a href="../jdkdocs/api/java/security/cert/Certificate.html" onClick="this.href=getApiDoc('java.security.cert.Certificate')"><font color="#660066" size=-1>java.security.cert.Certificate</font></a></td>
+</tr>
+</table>
+
+<p>
+Ist das <a href="index_s.html#ixb102612"><font color=#000080><tt>Signature</tt></font></a>-Objekt
+initialisiert, wird es durch Aufruf von <a href="index_u.html#ixb101747"><font color=#000080><tt>update</tt></font></a>
+mit Daten versorgt. Nachdem alle Daten übergeben wurden, kann
+mit <a name="ixa103497"><a href="index_s.html#ixb102621"><font color=#000080><tt>sign</tt></font></a></a>
+die Signatur abgefragt werden. Wurde das Objekt zum Verifizieren initialisiert,
+kann das Ergebnis durch Aufruf von <a name="ixa103498"><a href="index_v.html#ixb102622"><font color=#000080><tt>verify</tt></font></a></a>
+abgefragt werden:
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#EEFFCC">
+<tr>
+<td valign=top width=100%>
+<font color="#660066">
+<pre>
+public final byte[] sign()
+ throws SignatureException
+
+public final boolean verify(byte[] signature)
+ throws SignatureException
+</pre>
+</font>
+</td>
+<td valign=top>
+<a href="../jdkdocs/api/java/security/Signature.html" onClick="this.href=getApiDoc('java.security.Signature')"><font color="#660066" size=-1>java.security.Signature</font></a></td>
+</tr>
+</table>
+
+<p>
+Nach diesen Vorüberlegungen können wir uns nun das Programm
+zum Erstellen einer digitalen Unterschrift ansehen. Es erwartet zwei
+Kommandozeilenargumente: den Namen der zu signierenden Datei und den
+Namen der Datei, in den die digitale Unterschrift ausgegeben werden
+soll.
+<a name="listingid048005"></a>
+
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#DDDDDD">
+<tr>
+<td valign=top>
+<font color="#000055">
+<pre>
+<font color="#555555">001 </font><font color="#00AA00">/* DigitalSignature.java */</font>
+<font color="#555555">002 </font>
+<font color="#555555">003 </font><font color="#0000AA">import</font> java.io.*;
+<font color="#555555">004 </font><font color="#0000AA">import</font> java.security.cert.Certificate;
+<font color="#555555">005 </font><font color="#0000AA">import</font> java.security.*;
+<font color="#555555">006 </font>
+<font color="#555555">007 </font><font color="#0000AA">public</font> <font color="#0000AA">class</font> DigitalSignature
+<font color="#555555">008 </font>{
+<font color="#555555">009 </font> <font color="#0000AA">static</font> <font color="#0000AA">final</font> String KEYSTORE = <font color="#0000FF">"c:\\windows\\.keystore"</font>;
+<font color="#555555">010 </font> <font color="#0000AA">static</font> <font color="#0000AA">final</font> <font color="#006699">char</font>[] KSPASS = {<font color="#0000FF">'h'</font>,<font color="#0000FF">'j'</font>,<font color="#0000FF">'p'</font>,<font color="#0000FF">'3'</font>,<font color="#0000FF">'k'</font>,<font color="#0000FF">'s'</font>};
+<font color="#555555">011 </font> <font color="#0000AA">static</font> <font color="#0000AA">final</font> String ALIAS = <font color="#0000FF">"hjp3"</font>;
+<font color="#555555">012 </font> <font color="#0000AA">static</font> <font color="#0000AA">final</font> <font color="#006699">char</font>[] KEYPASS = {<font color="#0000FF">'h'</font>,<font color="#0000FF">'j'</font>,<font color="#0000FF">'p'</font>,<font color="#0000FF">'3'</font>,<font color="#0000FF">'k'</font>,<font color="#0000FF">'e'</font>,<font color="#0000FF">'y'</font>};
+<font color="#555555">013 </font>
+<font color="#555555">014 </font> <font color="#0000AA">public</font> <font color="#0000AA">static</font> <font color="#006699">void</font> main(String[] args)
+<font color="#555555">015 </font> {
+<font color="#555555">016 </font> <font color="#0000AA">try</font> {
+<font color="#555555">017 </font> <font color="#00AA00">//Laden der Schlüsseldatenbank</font>
+<font color="#555555">018 </font> KeyStore ks = KeyStore.getInstance(<font color="#0000FF">"JKS"</font>);
+<font color="#555555">019 </font> FileInputStream ksin = <font color="#0000AA">new</font> FileInputStream(KEYSTORE);
+<font color="#555555">020 </font> ks.load(ksin, KSPASS);
+<font color="#555555">021 </font> ksin.close();
+<font color="#555555">022 </font> <font color="#00AA00">//Privaten Schlüssel "hjp3" lesen</font>
+<font color="#555555">023 </font> Key key = ks.getKey(ALIAS, KEYPASS);
+<font color="#555555">024 </font> <font color="#00AA00">//Signatur-Objekt erstellen</font>
+<font color="#555555">025 </font> Signature signature = Signature.getInstance(<font color="#0000FF">"SHA/DSA"</font>);
+<font color="#555555">026 </font> signature.initSign((PrivateKey)key);
+<font color="#555555">027 </font> <font color="#00AA00">//Eingabedatei einlesen</font>
+<font color="#555555">028 </font> FileInputStream in = <font color="#0000AA">new</font> FileInputStream(args[0]);
+<font color="#555555">029 </font> <font color="#006699">int</font> len;
+<font color="#555555">030 </font> <font color="#006699">byte</font>[] data = <font color="#0000AA">new</font> <font color="#006699">byte</font>[1024];
+<font color="#555555">031 </font> <font color="#0000AA">while</font> ((len = in.read(data)) > 0) {
+<font color="#555555">032 </font> <font color="#00AA00">//Signatur updaten</font>
+<font color="#555555">033 </font> signature.update(data, 0, len);
+<font color="#555555">034 </font> }
+<font color="#555555">035 </font> in.close();
+<font color="#555555">036 </font> <font color="#00AA00">//Signatur berechnen</font>
+<font color="#555555">037 </font> <font color="#006699">byte</font>[] result = signature.sign();
+<font color="#555555">038 </font> <font color="#00AA00">//Signatur ausgeben</font>
+<font color="#555555">039 </font> FileOutputStream out = <font color="#0000AA">new</font> FileOutputStream(args[1]);
+<font color="#555555">040 </font> out.write(result, 0, result.length);
+<font color="#555555">041 </font> out.close();
+<font color="#555555">042 </font> } <font color="#0000AA">catch</font> (Exception e) {
+<font color="#555555">043 </font> System.err.println(e.toString());
+<font color="#555555">044 </font> System.exit(1);
+<font color="#555555">045 </font> }
+<font color="#555555">046 </font> }
+<font color="#555555">047 </font>}</pre>
+</font>
+</td>
+<td valign=top align=right>
+<a href="../examples/DigitalSignature.java"><font color="#000055" size=-1>DigitalSignature.java</font></a></td>
+</tr>
+</table>
+<i>
+Listing 48.5: Erstellen einer digitalen Unterschrift</i></p>
+
+<p>
+Will beispielsweise der Benutzer, dessen privater Schlüssel unter
+dem Aliasnamen »hjp3« in der Schlüsseldatenbank gespeichert
+wurde, die Datei <font color="#660099">DigitalSignature.java</font>
+signieren und das Ergebnis in der Datei <font color="#660099">ds1.sign</font>
+abspeichern, so ist das Programm wie folgt aufzurufen:
+<font color="#333300">
+<pre>
+C:\---><b>java DigitalSignature DigitalSignature.java ds1.sign</b>
+</pre>
+</font>
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100%>
+<tr>
+<td width=1 align=left valign=top bgcolor="#000077"><img src="trp1_1.gif"></td>
+<td><img src="trp1_1.gif" width=2></td>
+<td valign=top width=1000>
+
+<p>
+Die Laufzeit des Programms ist beträchtlich. Das Verschlüsseln
+des Message Digest kann auf durchschnittlichen Rechnern durchaus etwa
+30 Sekunden dauern. Glücklicherweise ist die Laufzeit nicht nennenswert
+von der Dateilänge abhängig, denn das Berechnen des Message
+Digests erfolgt sehr schnell.</td>
+<td><img src="trp1_1.gif" width=2></td>
+<td valign=top>
+<table border=0 cellspacing=0 cellpadding=1 width=100% bgcolor="#000077">
+<tr>
+<td><font color="#FFFFFF"> Hinweis </font></td>
+</tr>
+</table>
+</td>
+<td width=1 align=left valign=top bgcolor="#000077"><img src="trp1_1.gif"></td>
+</tr>
+</table>
+
+
+<!-- Section -->
+<a name="sectlevel4id048001006003"></a>
+<h4>Verifizieren einer digitalen Unterschrift </h4>
+
+<p>
+Das Programm zum Verifizieren arbeitet ähnlich wie das vorige.
+Statt mit <a href="index_i.html#ixb102613"><font color=#000080><tt>initSign</tt></font></a>
+wird das <a href="index_s.html#ixb102612"><font color=#000080><tt>Signature</tt></font></a>-Objekt
+nun mit <a href="index_i.html#ixb102614"><font color=#000080><tt>initVerify</tt></font></a>
+initialisiert und das Ergebnis wird nicht durch Aufruf von <a href="index_s.html#ixb102621"><font color=#000080><tt>sign</tt></font></a>,
+sondern durch Aufruf von <a href="index_v.html#ixb102622"><font color=#000080><tt>verify</tt></font></a>
+ermittelt.
+<a name="listingid048006"></a>
+
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#DDDDDD">
+<tr>
+<td valign=top>
+<font color="#000055">
+<pre>
+<font color="#555555">001 </font><font color="#00AA00">/* VerifySignature.java */</font>
+<font color="#555555">002 </font>
+<font color="#555555">003 </font><font color="#0000AA">import</font> java.io.*;
+<font color="#555555">004 </font><font color="#0000AA">import</font> java.security.cert.Certificate;
+<font color="#555555">005 </font><font color="#0000AA">import</font> java.security.*;
+<font color="#555555">006 </font>
+<font color="#555555">007 </font><font color="#0000AA">public</font> <font color="#0000AA">class</font> VerifySignature
+<font color="#555555">008 </font>{
+<font color="#555555">009 </font> <font color="#0000AA">static</font> <font color="#0000AA">final</font> String KEYSTORE = <font color="#0000FF">"c:\\windows\\.keystore"</font>;
+<font color="#555555">010 </font> <font color="#0000AA">static</font> <font color="#0000AA">final</font> <font color="#006699">char</font>[] KSPASS = {<font color="#0000FF">'h'</font>,<font color="#0000FF">'j'</font>,<font color="#0000FF">'p'</font>,<font color="#0000FF">'3'</font>,<font color="#0000FF">'k'</font>,<font color="#0000FF">'s'</font>};
+<font color="#555555">011 </font> <font color="#0000AA">static</font> <font color="#0000AA">final</font> String ALIAS = <font color="#0000FF">"hjp3"</font>;
+<font color="#555555">012 </font>
+<font color="#555555">013 </font> <font color="#0000AA">public</font> <font color="#0000AA">static</font> <font color="#006699">void</font> main(String[] args)
+<font color="#555555">014 </font> {
+<font color="#555555">015 </font> <font color="#0000AA">try</font> {
+<font color="#555555">016 </font> <font color="#00AA00">//Laden der Schlüsseldatenbank</font>
+<font color="#555555">017 </font> KeyStore ks = KeyStore.getInstance(<font color="#0000FF">"JKS"</font>);
+<font color="#555555">018 </font> FileInputStream ksin = <font color="#0000AA">new</font> FileInputStream(KEYSTORE);
+<font color="#555555">019 </font> ks.load(ksin, KSPASS);
+<font color="#555555">020 </font> ksin.close();
+<font color="#555555">021 </font> <font color="#00AA00">//Zertifikat "hjp3" lesen</font>
+<font color="#555555">022 </font> Certificate cert = ks.getCertificate(ALIAS);
+<font color="#555555">023 </font> <font color="#00AA00">//Signature-Objekt erstellen</font>
+<font color="#555555">024 </font> Signature signature = Signature.getInstance(<font color="#0000FF">"SHA/DSA"</font>);
+<font color="#555555">025 </font> signature.initVerify(cert.getPublicKey());
+<font color="#555555">026 </font> <font color="#00AA00">//Eingabedatei lesen</font>
+<font color="#555555">027 </font> FileInputStream in = <font color="#0000AA">new</font> FileInputStream(args[0]);
+<font color="#555555">028 </font> <font color="#006699">int</font> len;
+<font color="#555555">029 </font> <font color="#006699">byte</font>[] data = <font color="#0000AA">new</font> <font color="#006699">byte</font>[1024];
+<font color="#555555">030 </font> <font color="#0000AA">while</font> ((len = in.read(data)) > 0) {
+<font color="#555555">031 </font> <font color="#00AA00">//Signatur updaten</font>
+<font color="#555555">032 </font> signature.update(data, 0, len);
+<font color="#555555">033 </font> }
+<font color="#555555">034 </font> in.close();
+<font color="#555555">035 </font> <font color="#00AA00">//Signaturdatei einlesen</font>
+<font color="#555555">036 </font> in = <font color="#0000AA">new</font> FileInputStream(args[1]);
+<font color="#555555">037 </font> len = in.read(data);
+<font color="#555555">038 </font> in.close();
+<font color="#555555">039 </font> <font color="#006699">byte</font>[] sign = <font color="#0000AA">new</font> <font color="#006699">byte</font>[len];
+<font color="#555555">040 </font> System.arraycopy(data, 0, sign, 0, len);
+<font color="#555555">041 </font> <font color="#00AA00">//Signatur ausgeben</font>
+<font color="#555555">042 </font> <font color="#006699">boolean</font> result = signature.verify(sign);
+<font color="#555555">043 </font> System.out.println(<font color="#0000FF">"verification result: "</font> + result);
+<font color="#555555">044 </font> } <font color="#0000AA">catch</font> (Exception e) {
+<font color="#555555">045 </font> System.err.println(e.toString());
+<font color="#555555">046 </font> System.exit(1);
+<font color="#555555">047 </font> }
+<font color="#555555">048 </font> }
+<font color="#555555">049 </font>}</pre>
+</font>
+</td>
+<td valign=top align=right>
+<a href="../examples/VerifySignature.java"><font color="#000055" size=-1>VerifySignature.java</font></a></td>
+</tr>
+</table>
+<i>
+Listing 48.6: Verifizieren einer digitalen Unterschrift</i></p>
+
+<p>
+Soll die Datei <font color="#660099">DigitalSignature.java</font>
+mit der im vorigen Beispiel erstellten Signatur verifiziert werden,
+kann das durch folgendes Kommando geschehen:
+<font color="#333300">
+<pre>
+C:\---><b>java VerifySignature DigitalSignature.java ds1.sign</b>
+verification result: true
+</pre>
+</font>
+
+<p>
+Wird nur ein einziges Byte in <font color="#660099">DigitalSignature.java</font>
+verändert, ist die Verifikation negativ und das Programm gibt
+<font color="#000077"><tt>false</tt></font> aus. Durch eine erfolgreich
+verifizierte digitale Unterschrift können wir sicher sein, dass
+die Datei nicht verändert wurde. Zudem können wir sicher
+sein, dass sie mit dem privaten Schlüssel von »hjp3«
+signiert wurde, denn wir haben sie mit dessen öffentlichen Schlüssel
+verifiziert.
+
+<!-- Section -->
+
+<a name="zertifikate"></a>
+<h3>48.1.7 Zertifikate </h3>
+
+<p>
+Ein großes Problem bei der Public-Key-Kryptographie besteht
+darin, die Authentizität von öffentlichen Schlüsseln
+sicherzustellen. Würde beispielsweise B einen öffentlichen
+Schlüssel publizieren, der glaubhaft vorgibt, A zu gehören,
+könnte dies zu verschiedenen Unannehmlichkeiten führen:
+<ul>
+<li>Angenommen, C will eine verschlüsselte Nachricht an A schicken
+und verwendet dazu versehentlich den öffentlichen Schlüssel
+von B (den es für den von A hält). B kann nun mit seinem
+eigenen privaten Schlüssel die vertrauliche Nachricht lesen.
+Um weiterhin unentdeckt zu bleiben, könnte B die Nachricht anschließend
+sogar mit dem echten öffentlichen Schlüssel von A verschlüsseln
+und an A weitersenden.
+<li>Noch folgenreicher ist die Umkehrung. B könnte (als A getarnt)
+Dokumente mit einer digitalen Unterschrift versenden, die für
+die von A gehalten wird und so im Namen von A beispielsweise geschäftliche
+oder rechtlich relevante Transaktionen auslösen. A wäre
+anschließend in der unangenehmen Sitution, nachweisen zu müssen,
+dass ihm der von B verwendete private Schlüssel nie gehörte
+und bekannt war.
+</ul>
+
+<p>
+Einen Schutz gegen derartigen Missbrauch bringen <a name="ixa103499"><i>Zertifikate</i></a>.
+Ein Zertifikat ist eine Art Echtheitsbeweis für einen öffentlichen
+Schlüssel, das damit ähnliche Aufgaben erfüllt wie
+ein Personalausweis oder Reisepass. Ein Zertifikat besteht meist aus
+folgenden Teilen:
+<ul>
+<li>Dem öffentlichen Schlüssel des Zertifikatsinhabers.
+<li>Identitätsmerkmalen des Inhabers (beispielsweise Name, Wohnort,
+Firma, einem Photo etc...).
+<li>Der Bezeichnung des Zertifikatsausstellers.
+<li>Der digitalen Signatur des Ausstellers.
+<li>Der digitalen Signatur des Inhabers.
+</ul>
+
+<p>
+Die Glaubwürdigkeit des Zertifikats hängt von der Glaubwürdigkeit
+des Ausstellers ab. Wird dieser als vertrauenswürdig angesehen,
+d.h. kann man seiner digitialen Unterschrift trauen, so wird man auch
+dem Zertifikat trauen und den darin enthaltenen öffentlichen
+Schlüssel akzeptieren.
+
+<p>
+Dieses Vertrauen kann einerseits darauf basieren, dass der Aussteller
+eine anerkannte Zertifizierungsautorität ist (auch <a name="ixa103500"><i>Certification
+Authority</i></a>, kurz <a name="ixa103501"><i>CA</i></a>,
+genannt), deren öffentlicher Schlüssel bekannt und deren
+Seriösität institutionell manifestiert ist. Mit anderen
+Worten: dessen eigenes Zertifikat in der eigenen Schlüsselverwaltung
+bekannt und als vertrauenswürdig deklariert ist. Andererseits
+kann das Vertrauen in das Zertifikat daher stammen, dass der Aussteller
+persönlich bekannt ist, sein öffentlicher Schlüssel
+eindeutig nachgewiesen ist, und seiner Unterschrift Glauben geschenkt
+wird.
+
+<p>
+Der erste Ansatz wird beispielsweise bei X.509-Zertifikaten <a name="ixa103502"></a>
+verfolgt. Institute, die derartige Zertifikate ausstellen, werden
+meist staatlich authorisiert und geprüft. Beispiele dafür
+sind <a name="ixa103503"><i>VeriSign</i></a>, <a name="ixa103504"><i>Thawte</i></a>
+oder das <a name="ixa103505"><i>TA Trustcenter</i></a>. Der zweite
+Ansatz liegt beispielsweise den Zertifikaten in PGP zugrunde. Hier
+ist es sogar möglich, öffentliche Schlüssel mit mehreren
+digitalen Unterschriften unterschiedlicher Personen zu signieren und
+so die Glaubwürdigkeit (bzw. ihre Reichweite) zu erhöhen.
+
+<p>
+Zertifizierungsinstitute stellen meist auch Schlüsseldatenbanken
+zur Verfügung, aus denen Zertifikate abgerufen werden können.
+Diese dienen auch als Anlaufstelle, um ungültig gewordene oder
+unbrauchbare Zertifikate zu registrieren. Lokale Schlüsselverwaltungen
+können sich mit diesen Informationen synchronisieren, um ihren
+eigenen Schlüsselbestand up-to-date zu halten.
+<hr>
+<table border=0 cellpadding=0 cellspacing=1 width="100%">
+<tr bgcolor="#EEFFCC">
+<td width="7%" align=center bgcolor="#DDCC99"><a href="cover.html"> Titel </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100003.html"> Inhalt </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="search.html"> Suchen </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="index.html"> Index </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="../jdkdocs/index.html" onClick="this.href=getDocIndex()"> DOC </a>
+<td align="right">Handbuch der Java-Programmierung, 5. Auflage, Addison
+Wesley, Version 5.0.1
+<tr bgcolor="#EEFFCC">
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100302.html"> << </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100302.html"> < </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100304.html"> > </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100307.html"> >> </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="../jdkdocs/api/index.html" onClick="this.href=getApiIndex()"> API </a>
+<td align="right">© 1998, 2007 Guido Krüger & Thomas
+Stark, <a href="http://www.javabuch.de">http://www.javabuch.de</a>
+</table>
+<a name="endofbody"></a>
+</body>
+</html>
|
