... [Seminar WWW und Java ] ... [ Thema Verschlüsselung im Internet ] ... [ Literaturverzeichnis ] ...
Zusammenfassung
Obwohl die Architektur der kryptographischen Klassen bereits im
JDK 1.1 teilweise vorgesehen war, wurden einige Klassen erweitert und
einige neue Klassen hinzugefügt. Die hier vorgestellten Konzepte
beziehen sich auf das JDK 1.2 beta4. Außerdem sind im JDK aus
rechtlichen Gründen (Exportbeschränkungen in den USA) nur
MessageDigest und Signatur-Algorithmen enthalten. Zur Verschlüsselung
von Daten wird zusätzlich die Java Cryptographic Extension (JCE)
benötigt.
Hinweis : Wenn man versucht, die JCE 'runterzuladen
wird nachgefragt, ob man in den USA lebt. Die hier geforderte Angabe
wird allerdings nicht überprüft (was will uns das nur
sagen...?)
Darüberhinaus gibt es auch andere
Implementierungen nach den Spezifikationen der JCE, die auch in
Europa frei verfügbar sind. Einige dieser Implementierungen
sollen auch das JDK 1.1 um die im JDK 1.2 hinzugefügten Klassen
erweitern. Dies habe ich allerdings nicht getestet, so daß bei
Bedarf die Funktionsfähigkeit dieses Features ausprobiert werden
muß....
Die Java Cryptography Architecture (JCA) ist ein Bestandteil der Java Security API. In dieser JCA hat Sun eine strikte Trennung von Konzepten (Cipher, MessageDigest und Signature), Algorithmen und den dazugehörigen Implementierungen festgelegt. Trotz der daraus resultierenden Komplexität (aber auch Flexibilität) dieser Architektur ist die Anwendung, wie man noch sehen wird, relativ einfach gehalten.
Service Provider Interfaces - SPI
Klassen, die ein Konzept-spezifisches SPI beerben, implementieren einen beliebigen Algorithmus, der jedoch zum Konzept 'passen' muß. Im JCA ist zu jedem Konzept eine (abstrakte) SPI-Klasse vorgesehen, also (die wichtigsten):
CipherSpi - SPI zur Implementierung eines Verschlüsselungsalgorithmus
SignatureSpi - SPI zur Implementierung von Signaturalgorithmen
MessageDigestSpi - SPI für MessageDigests
KeyGeneratorSpi - SPI zur Generierung geheimer Schlüssel
KeyPairGeneratorSpi - SPI zur Erzeugung ein private/public Schlüsselpaares
KeyFactorySpi - KeyFactories dienen der Übersetzung zwischen Schlüsselklassen und Schlüsseldaten
SecureRandomSpi - SPI zur Implementierung 'sicherer' Zufallszahlen
AlgorithmParametersSpi - Dient der Implementierung Algorithmus-spezifischer Parameter
Wenn man also beispielsweise seine eigene Implementierung des
DES-Algorithmus programmieren möchte, könnte der Kopf der
Klasse etwa so aussehen :class MyDESImplementation extends
CipherSpi {...}
Die Zuordnung der Implementierung zum Namen des Algorithmus erfolgt erst in den Providern.
Provider erfüllen zwei
Funktionen : Zum einen verwalten sie eine oder mehrere
Algorithmus-Implementierungen. Dabei ist zu beachten, daß jeder
Algorithmus nur einmal in einem Provider implementiert sein darf. Zum
anderen erfolgt in einem Provider die Zuordnung zwischen dem Namen
eines Algorithmus und der Implementierung. Provider beerben immer die
abstrakte Klasse java.security.Provider
. In dieser
Klasse sind Methoden vorgegeben, die dem Provider bestimmte
Implementierungen zuordnen. Ein eigener Provider könnte also
etwa so aussehen :class MyProvider extends
java.security.Provider {
MyProvider() {
// Aufruf des
super-Konstruktors mit den Parametern (Name, Version,
Beschreibung)
super ("MyProvider", 1.0 , "My own
Provider");
// Die obige Implementierung diesem Provider
zuordnen mit der Methode put(String Konzept.Algorithmus, String
Klasse)
put ("Cipher.DES", "MyDESImplementation");
}}
Jeder Provider muß nun noch der JavaVM bekanntgemacht werden. Dazu stellt die Klasse java.security.Security die statischen Methoden addProvider(Provider p), insertProviderAt(Provider p, int i) und removeProvider(Provider p) zur Verfügung. Java.security.Security verwaltet die Provider intern in einer Liste, die bei Bedarf der Reihe nach abgefragt wird. Das Erzeugen einer Instanz der MyDESImplementation Klasse erreicht man mit Hilfe der Konzept-Klassen (engines).
Konzept-Klassen runden die
JCA ab. Mit Hilfe dieser Klassen werden 'gebrauchsfertige' Instanzen
erzeugt, mit denen man auch etwas machen kann. Ebenso, wie es zu
jedem Konzept ein SPI gibt, gibt es zu jedem Konzept die dazugehörige
engine. Diese abstrakten engines stellen statische getInstance ()
Methoden zur Verfügung, die Instanzen des gewünschten
Konzeptes und des gewünschten Algorithmus zurückgeben. In
der Praxis sieht ein solcher getInstance() Aufruf so aus ://
Aufruf der getInstance() Fabrikmethode mit den Parametern (String
Algorithmus, String Provider)
// Die getInstanceMethode ist
mehrfach überladen, so daß man auch nur den Algorithmus
// oder auch weitere Paramter übergeben kann
Cipher
DESCipher = Cipher.getInstance(DES, MyProvider);
Obwohl die ganze Architektur etwas unübersichtlich wirkt, ist
sie für den Benutzer kryptographischer Algorithmen sehr einfach
zu verwenden. Die engines sind letztlich die Schnittstellen für
den Programmierer, um die darunterliegenden Provider und SPI braucht
er sich eigentlich nicht zu kümmern.
Der technische Ablauf im
Hintergrund ist etwa wie folgt darzustellen :
1. Die Anwendung
stellt eine Anfrage nach einem Algorithmus an die getInstance()
Methode der engine;
2. getInstance() reicht diese Anfrage an
java.security.Security weiter;
3. java.security.Security fragt
nacheinander bei den registrierten Providern nach, ob sie eine
Implenmentierung des Algorithmus anzubieten haben;
4. Der erste
Provider, der einen Algorithmus anzubieten hat, gibt den Namen der
Klasse zurück, die den Algorithmus implementiert;
5.
java.security.Security reicht diesen Namen an die engine weiter;
6.
Die engine gibt eine Instanz dieser Klasse an die Anwendung zurück;
import javax.crypto.*;
import java.security.*;
try {
KeyGenerator
kg=KeyGenerator.getInstance(AlgoString,ProviderString);
kg.init
(new SecureRandom());
SecretKey CryptoSecret =
kg.generateKey();
Cipher Vorgang = Cipher.getInstance(AlgoString,
ProviderString);
Vorgang.init (Cipher.ENCRYPT_MODE,
f.CDaten.getSecretKey());
byte[] raw =
Vorgang.doFinal(DataBytes);
}
catch (NoSuchProviderException
nspe) {System.out.println("Den angegebenen Provider gibt es
nicht");}
catch (NoSuchAlgorithmException nsae)
{System.out.println("Der Provider kann diesen Algorithmus nicht
bereitstellen");}
catch (Exception x)
{System.out.println("Hier gehen ganz, ganz andere Dinge vor");}
try {
MessageDigest
md=MessageDigest.getInstance(AlgoString,ProviderString);
md.update(DataBytes);
byte[] raw = md.digest();
}
catch (NoSuchProviderException
nspe) {System.out.println("Den angegebenen Provider gibt es
nicht");}
catch (NoSuchAlgorithmException nsae)
{System.out.println("Der Provider kann diesen Algorithmus nicht
bereitstellen");}
catch (Exception x)
{System.out.println("Hier gehen ganz, ganz andere Dinge vor");}
try {
Signature
sig=Signature.getInstance("SHA/DSA",ProviderString);
sig.initSign(MyPrivateAsymetricKey());
sig.update(DataBytes);
byte[] raw = sig.sign();
}
catch
(NoSuchProviderException nspe) {System.out.println("Den
angegebenen Provider gibt es nicht");}
catch
(NoSuchAlgorithmException nsae) {System.out.println("Der
Provider kann diesen Algorithmus nicht bereitstellen");}
catch
(Exception x) {System.out.println("Hier gehen ganz, ganz andere
Dinge vor");}
... [Seminar WWW und Java ] ... [ Thema Verschlüsselung im Internet ] ... [Kryptographie mit Java] ... [Literaturverzeichnis ] ...