Montag, 17. Mai 2010

RESTful Java Server Faces (JSF) - Und bist du nicht willig...

Hallo,

Nachdem ich mich nun schon eine kleine Weile mit RESTful webservices unter Java beschäftigt habe und evaluiert habe, was in diesem Zusammenhang an Frameworks vorhanden ist, stand ich vor einem kleinen Problem, welches ich nun, Gott sei Dank, lösen konnte und damit einen ersten Ansatz für RESTful Java Server Pages schaffen konnte.

Um RESTful webservices in Java zu implementieren, kennt Java die funkel-nagel-neue API 'jax-ws', welche es erlaubt verschiedene Java Beans über Annotations als Web-Resourcen zu verwenden.
Hierauf können nun verschiedene Methoden implementiert werden, welche die HTTP Methoden bedienen und so z.B. einen GET-Request auf die XML Representation einer Resource behandeln können.

Nun ist es natürlich nicht schwierig auf die selbe Weise eine GET methode für HTML zu definieren.
Problematisch wird es erst, wenn man nun auch noch auf die Idee kommt, doch gerne die vielfältigen Möglichkeiten der Java Server Faces für eben jene HTML Representation der Resource zu verwenden.


Hochzeit wider Willen


Um die JSF Engine aus einem bereits bestehenden JAX-WS Aufruf heraus zu bedienen müßte man verschiedene größere Hürden überwinden:

  • Starten der JSF Engine auserhalb ihres eigenen Servlets

  • Bekanntmachung des richtigen Templates (xhtml Seite) für die entsprechende Ressource

  • Anmeldung des bereits auf anderem Wege geladenen Datenobjects an die EL der Server Faces



Die JSF Engine manuel zu starten ist wichtig, denn zu dem Zeitpunkt an dem die Methode 'GET text/xhtml' auf dem jax-ws service aufgerufen wird, befinden wir uns bereits in einem Servlet-Context und wollen diesen auch gerne beibehalten.

Gott Sei Dank ist hier guter Rat nicht teuer und nach einem kurzen Blick in die Implementation der javax.faces.webapp.FacesServlet Klasse stand ein erster Rohbau der 'GET text/xhtml' Methode:

    @GET
    @Produces("text/html")
    public void getXHtml(
            @Context ServletConfig cfg,
            @Context HttpServletRequest req,
            @Context HttpServletResponse resp) throws IOException{

        LifecycleFactory lfactory = (LifecycleFactory)
            FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
        Lifecycle lc = lfactory.getLifecycle(
            LifecycleFactory.DEFAULT_LIFECYCLE);

        FacesContextFactory fcfactory = (FacesContextFactory)
            FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
        FacesContext fc = fcfactory.getFacesContext(
            cfg.getServletContext(),
            req,
            resp,
            lc);

        lc.execute(fc);
        lc.render(fc);
        fc.release();

        resp.flushBuffer();
    }


Ebenso wie das JSF Servlet, initialisiere ich hier die JSF Engine indem ich zuerst einen Lifecycle und einen FacesContext lade, um anschließend 'execute', 'render' und 'release' darauf auszuführen. Zuletzt muß nur noch der Responcepuffer geflashed werden. Da wir hier direkt auf einem HTTPServletResponse Object arbeiten, ist es auch nicht nötig irgendetwas zurück zu geben.

Nun haben wir zwar erfolgreich die JSF Engine aus einem JAX-WS Webservice heraus aufgerufen, da wir der JSF Engine allerdings noch nicht mitgeteilt haben, was wir den gerne rendern würden, allerdings noch kein verwertbares Ergebnis.

Der nächste Schritt wird daher, der JSF Engine eine JSF-Seite als Template mitzugeben.
Leider ist die JSF Engine hier so sehr in sich selbst gekapselt, daß es keine programative Schnittstelle gibt um dies zu tun, ohne auf die tatsächliche Implementation zurückgreifen zu können, was ich prinzipiell vermeiden will.
Ein Trick den wir hier verwenden können ist, den HTTPServletRequest den wir der Engine übergeben anzupassen und den Aufruf des JSF-Templates und der URI mitzuliefern.
Hierfür erstellen wir uns eine Wrapper Klasse für den Request:

import [...];

public class WrappedHttpRequest implements HttpServletRequest{

    private String template;
    private HttpServletRequest wrapped;

    public WrappedHttpRequest(
            HttpServletRequest wrapped,
            String template) {
        this.wrapped = wrapped;
        this.template = template;
    }

    /*
     * delegate all methods to the wrapped request
     */
    [...]
}


Auf diesem Wrapper überschreiben wir nun die Methode getPathInfo() welche für den Sub-Pfad unterhalb des Servlet-Pfades zuständig ist. Generel gesagt: Wenn ein Servlet mit dem Pfad: http:/server/servlet/somepage angesprochen wird, so liefert diese Methode: '/somepage' zurück.
In unserem Fall, soll die Methode den Pfad zu dem gewünschten JSF-Template zurückgeben.


    public String getPathInfo() {
        return template;
    }


Nun können wir der aufgerufenen JSF-Engine das gewünschte Template mit angeben, indem wir ihr einen WrappedHTTPRequest mit dem entsprechenden Template-Pfad übergeben. Unsere neue GET Methode sieht nun wie folgt aus:


    @GET
    @Produces("text/html")
    public void getXHtml(
            @Context ServletConfig cfg,
            @Context HttpServletRequest req,
            @Context HttpServletResponse resp) throws IOException{

        LifecycleFactory lfactory = (LifecycleFactory)
            FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
        Lifecycle lc = lfactory.getLifecycle(
            LifecycleFactory.DEFAULT_LIFECYCLE);

        FacesContextFactory fcfactory = (FacesContextFactory)
            FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
        FacesContext fc = fcfactory.getFacesContext(
            cfg.getServletContext(),
            new WrappedHttpRequest(req, "/template.xhtml"),
            resp,
            lc);

        lc.execute(fc);
        lc.render(fc);
        fc.release();

        resp.flushBuffer();
    }


So viel zum einfachen Teil der Übung. Wenn wir unser Servlet nun aufrufen, bekommen wir tatsächlich eine wunderschön gerenderte JSF Seite angezeigt, genau wie es gedacht war.

Um allerdings irgendeinen Nutzen aus der Aktion ziehen zu können, muß nun unser eigendliches Datenobject noch irgendwie in dem jeweiligen JSF-Template verwendbar werden.
Nach längerer Wühlarbeit durch die Analen der JSF-Spezifikation (schwääre Kost) hatte ich auch hierfür eine Lösung gefunden.

JSF bietet Zugriff auf bestimmte 'Backing Beans' über eine Scriptsprache namens 'Expression Language' (EL).
Leider können wir unser Datenobject nicht einfach als ManagedBean annotieren, da eine solche durch die JSF-Engine selbst initialisiert wird und wir so keine Kontrolle mehr über das Object selbst haben.
Allerdings erlaubt die EL, in einen scope-abhängigen ELContext Variablen als Implementationen der javax.el.ValueExpression Klasse einzubinden.
Nehmen wir nun den EL-Context des FacesContext, welcher grundsätzlich im Scope REQUEST liegt so können wir sicher sein, das unser Wrapper Objekt nur diese eine Anfrage überlebt.

Um dies zu implementieren, brauchen wir natürlich zuerst einen solchen Wrapper als ValueExpression:


import [...];

public class JsfManaged extends ValueExpression{

    private static final long serialVersionUID = 2254085359874699578L;
    private Object item;

    public JsfManaged(Object item){
        this.item = item;
    }

    @Override
    public Class getExpectedType() {
        return item.getClass();
    }

    @Override
    public Class getType(ELContext context) {
        return null;
    }

    @Override
    public Object getValue(ELContext context) {
        return item;
    }

    @Override
    public boolean isReadOnly(ELContext context) {
        return true;
    }

    @Override
    public void setValue(ELContext context, Object value) {}

    @Override
    public boolean equals(Object obj) {
        if (null != obj && obj instanceof JsfManaged){
            Object i = ((JsfManaged)obj).item;
            return null == i?null == item:i.equals(item);
        }
        return false;
    }

    @Override
    public String getExpressionString() {
        return "myobject";
    }

    @Override
    public int hashCode() {
        return item.hashCode();
    }

    @Override
    public boolean isLiteralText() {
        return false;
    }

}


Da dies eine Read-Only Expression sein soll, sind die meisten Methoden nicht von weiterem Interese. Lediglich die (fett markierten) Methoden getExpectedType, getValue und equals sollte man sich etwas genauer ansehen.

Hauptsächlich die getValue Methode ist von Interresse, da hier das tatsächliche Datenobject ausgegeben wird.

Um diesen Wrapper nun für einen bestimmten Request und ein bestimmtes Datenobject einzubauen, müßen wir wiederum unsere GET methode anpassen. Für unser Beispiel hier nehmen wir einfach einmal an, daß wir das tatsächliche Datenobject über getData() erlangen können.


    @GET
    @Produces("text/html")
    public void getXHtml(
            @Context ServletConfig cfg,
            @Context HttpServletRequest req,
            @Context HttpServletResponse resp) throws IOException{

        LifecycleFactory lfactory = (LifecycleFactory)
            FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
        Lifecycle lc = lfactory.getLifecycle(
            LifecycleFactory.DEFAULT_LIFECYCLE);

        FacesContextFactory fcfactory = (FacesContextFactory)
            FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
        FacesContext fc = fcfactory.getFacesContext(
            cfg.getServletContext(),
            new WrappedHttpRequest(req, "/template.xhtml"),
            resp,
            lc);

        Object data = getData();
        fc.getELContext().getVariableMapper().setVariable(
            "myobject",
            new JsfManaged(data));


        lc.execute(fc);
        lc.render(fc);
        fc.release();

        resp.flushBuffer();
    }


Nun kann in unserem JSF-Template unter verwendung der EL Expression #{myobject} immer auf das tatsächliche Datenobject zugegriffen werden.

Fazit


Es ist also möglich, mit geringem Aufwand die Vorteile der JSF Architektur auch innerhalb eines JAX-WS kontrollierten WebService auszunutzen.

Leider ist JSF immernoch sehr wenig kooperationswillig, weshalb es momentan noch einiger Trickserei bedarf. Da man dies aber trozdem bewerkstelligen kann, ohne auf die JSF Implementation selbst zugreifen zu müßen, halte ich diesen Ansatz dennoch für einen sehr gangbaren Weg.

Ich würde mir für zukünftige Versionen der JSF wünschen, daß man EL und Templaterendering auf einfachere Weise auch außerhalb eines vollen JSF Kontext verwenden kann, um keine derartigen Klimmzüge mehr machen zu müßen.

Glossar


Java Server Faces (JSF) - Spezifikation

JAX-RS - RESTful Webservice Implementation in Java. - Spezifikation

REST - "Representational State Transfer". Das Architektur Paradigma hinter HTTP und dem WWW. - Definition - Auserdem gibt es noch eine gar nicht mal so schlechte Erklärung in der engischen Wikipedia.


Auf Bald.

Sonntag, 13. April 2008

Ein ander Mal/PiratenVZ und tschüß

Leider werde Ich das Project PiratenVZ wieder aufgeben, oder zumindest für unbestimmte Zeit auf Eis legen müßen.

Dies hat zwei Gründe:



  • Erstens war meine anfängliche Begeisterung wohl der Blauäugigkeit zuzuschreiben, Leute die sich bereit erklärten in einem Team diverse Aufgaben zu übernehmen, würden wenn es dann Ernst wird keine kalten Füße bekommen.

    Tja, so wie es aussieht hat das Team, daß sich noch im Dezember zusammengefunden hat bei der Konkretisierung der Idee leider die Flucht ergriffen. :(


  • Zweitens hänge ich konzeptionel immer noch an einem Schlüßelproblem fest. Denn wenn ein solches Netzwerk mit den gegebenen Paradigmen (siehe hier unter 'Paradigmen') wirklich funktionieren soll, ist es unerlässlich, daß eine möglichst einfache und möglichst intelligente Datenaufteilung über verschiedene Klein-Server stattfindet (wenn man so will, eine Art rudimentäres Clustering).

    Da das Netzwerk sich auch noch möglichst selbst verwalten soll, ist diese Aufgabe mit mehr Problemen gespickt, als man anfänglich meinen sollte.

    Wenn dieses konzeptionale Problem gelöst ist, werde Ich vieleicht wieder nach Leuten Ausschau halten, mit denen eine Realisierung angegangen werden kann, aber bis dahin bleibt die Idee (so gut sie immer noch ist) erst einmal auf Eis gelegt.



Außerdem wird der Name so oder so das Zeitliche segnen, den seien wir mal ehrlich: Es hat zwar schon bescheuertere Namen gegeben, aber so viele sind das nicht. ;)


Auf Bald.

Mittwoch, 19. Dezember 2007

Nun kommen die Tage des PiratenVZ...

Ich bin ja wirklich hellauf begeistert. Einer überaus positive Resonanz auf meinen letzten Artikel, gepaart mit spontanem Tatendrang ist es zu verdanken, daß aus der kleinen Randbemerkung, eine solche Sozialnetzwerk-Seite könne nur als OpenSource unter Gewaltenteilung was Code, Datenhaltung und Moderation angeht funktionieren, tatsächlich der Anfang eines ambitionierten Projektes geworden ist.

Ein kleines Team hat sich zusammen gefunden und wir werden ab Januar 2008 mit der Implementierung einer Sozialnetzwerks-Software auf OpenSource Basis unter dem Arbeitstitel 'PiratenVZ' beginnen.
Vorab, hier schon einmal ein grobes Konzept:

Paradigmen



  • Ähnlich den populären Vorbildern soll PiratenVZ eine Platform zur persönlichen Präsentation, Kommunikation und Kontaktpflege werden.

  • Jeder Benutzer besitzt volle und möglichst fein granulare Kontrolle darüber, welche seiner pers. Daten von wem und in welchem Detail angezeigt werden dürfen.

  • Das Hauptaugenmerk der Entwicklung soll dabei auf der Sicherung der Übertragung und der Datenhaltung (z.B. durch die Verwendung passender Kryptoverfahren) liegen.

  • Softwarebereitstellung, technische Administration und inhaltliche Moderation sind soweit wie möglich getrennt zu halten und, wo sinnvoll, in die direkte Hand der Nutzerschaft zu legen, um Machtmonopolen im tatsächlichen Betrieb vorzubeugen.

  • Das Softwaredesign selbst muß solide und erweiterbar genug sein, um für einen langen Zeitraum im Code Bestand zu haben, ohne durch 'Abkürzungen' oder Hacks ad Absurdum geführt zu werden.



Datenstruktur



Hauptziel dieser Datenstruktur ist es, jedes Datenobjekt (auser Konfiguration, die hier bewußt außen vor gelassen wurde) eindeutig auf einen bestimmten Benutzer zurückführen zu können, so daß 'Besitzansprüche' an den einzelnen Datenfragmenten technisch eindeutig abgebildet werden.

Des weiteren ist das Objectdesign so angelegt, daß ein neu hinzukommenter Service (der meist auch neue Datentypen mitbringt) lediglich eine Erweiterung des Datenprofils darstellen, so daß alte Profile zu neuen Versionen der Software kompatibel bleiben.

Das Objektdesign gibt es hier.

Es gibt also pro Benutzer ein User Objekt, welches in der Lage ist, über login und email Adresse einen Benutzer eindeutig zu identifizieren.

Jeder User besitzt einen eigenen LoginContext. Dies ist zuerst einmal ein Interface, welches die Funktionen zum einloggen übernimmt. Jeder Benutzer kann somit später selbst entscheiden, auf welche Art und Weise er autentifiziert werden will.
Geplant ist sowohl eine Implementation als PasswordLoginContext welcher den Benutzer auf eine klasische User/Password hin einlässt, als auch eine Implementation als CypherLoginContext der eine Anmeldung per asynchron verschlüßeltem Handshake ermöglicht.

Des weiteren besitzt jeder User ein UserPreferences object, welches die persönlichen Einstellungen des Benutzers beinhaltet, sowie ein UserProfile Objekt, welches ein beliebig detailiertes Profil des Benutzers darstellt.

Für jeden Service (Social Networking, Blog, Messager, etc.) den der Benutzer verwendet, wird dem User ein ServiceContext Objekt zugeteilt, welches die Daten des Benutzers zu dem jeweiligen Service enthält. Die dargestellten Implementierungen eines ServiceContext Objekts im Bild sind hierbei hauptsächlich als Beispiel gedacht.
Jedes ServiceContext Objekt beinhaltet andere Daten, je nachdem, was durch den verwendeten Service benötigt wird.

Neben diesem Model wird es noch weitere Datentypen geben, welche verschiedene Inhalte (z.B. Bilder oder Texte) verkörpern und hauptsächlich in den einzelnen ServiceContext und UserProfile Objekten Verwendung finden. Welche das sind, wird sich aber erst später im Detail entscheiden.

Software-Komponenten



Das Design der Software-Komponenten ist, wie das Objektdesgin auch, darauf ausgerichtet, eine schmale ubnd solide Grundfunktionalität anzubieten und der Implementation neuer Services nicht im Wege zu stehen.

Zwar ist das Design mit einer typische Java-J2EE Anwendung auf Jboss oder ähnlichem im Hinterkopf geschrieben worden, es wäre aber auch beinahe jede andere gekappselte Serverlogik und Programmiersprache möglich.

Das Designbildchen findet sich hier.

Generel sind die Softwarekomponenten in 3 Teile unterteilt. Einen für die Anzeige, einen für die Logik und einen für die Datenhaltung. Soweit so klasisch.

Der Web Bereich der Anwendung wird über JPS's gestaltet, deren Logik wo es möglich ist in Taglibs und korrospondierende Bean-Klassen ausgelagert ist.
Mit der jeweiligen HTTP-Session können die Beans der einzelnen Tags nach Bedarf auf die Service-Schicht zugreifen.

Jeder Service für sich stellt vordergründig eine möglichst atomare Implementation einer in sich geschloßenen Anwendung dar. Jeder Service soll autark durch eine WebBean ansprechbar sein, Das bedeutet, daß sämtliche Abhängigkeiten der Services untereinander und zur Persistenz für die WebBean transparent sind.

Eine Ausnahme stellt hier der SecurityService dar, welcher in Korellation zum SessionMetadataService einzelne Zugriffe erlaubt oder verbietet und selbst nicht von auserhalb des Servicelayers ansprechbar ist, sondern lediglich von den anderen Services angesprochen wird.

Eine naheliegende Implementationsvariante dieser Services stellen SessionBeans dar. Der Ausnahmeservice SecurityService könnte am besten als singleton Klasse implementiert werden, so daß ein schneller und direkter Zugriff von allen Services aus jederzeit möglich ist.

Zu den einzelnen Services:

  • Der SecurityService besitzt die Möglichkeit über den SessionMetadataService auf die Attribute einzelner Sessions zuzugreifen und vergibt auf Basis dieser Informationen Berechtigungen für verschiedene Aktionen.
    Als einziger Service ist er lediglich durch andere Services ansprechbar und kann daher als singleton implementiert werden.
    Zusammen mit dem SessionMetadata- und UserDataService bildet er das Rückrad der Anwendung

  • Der SessionMetadataService hält sämtliche sessionrelevanten Daten vor. So zum Beispiel den eingeloggten Benutzer, die Berechtigungen dieses Benutzers, die SessionId sowie temporäre Daten anderer Services, die lediglich für diese eine Session Gültigkeit haben.
    Er ist auch die Stelle, an die eine Loginanfrage durch eine WebBean geschickt werden kann.
    Er bildet zusammen mit dem Security- und dem UserDataService das Rückrad der Anwendung.

  • der UserDataService stellt Benutzerprofile und andere benutzerbezogene Daten zur Verfügung. Entsprechen diese Daten denen des Session-Eigentümers, können sie auch geändert werden. So kann ein Benutzer zum Beispiel seine persönlichen Einstellungen ändern.
    Für's Protokoll: Dieser Service bildet zusammen mit dem Security- und dem SessionMetadataService das Rückrad der Anwendung.



Die restlichen Services in dem verlinkten Komponenten-Design stellen pro Service die Funktionalität eines bestimmten, von den Benutzer verwendbaren, Services dar.
So lassen sich zum Beispiel über den SocialNetworkService soziale Netze (analog zu StudiVZ, Wer-Kennt-Wen, etc.) pflegen. Über den BlogService kann ein Benutzer einen eigenen Blog pflegen, oder die Blogs anderer Benutzer anzeigen lassen und kommentieren. Über den PictureGallerieService könnten Bilder der einzelnen Benutzer abgelegt und angezeigt werden.
Diese Liste ist nach Bedarf erweiterbar oder streichbar. Welche Services wir für's Erste tatsächlich anbieten werden wird sic noch entscheiden.

Die Persistenzschicht ist denkbar einfach aufgebaut. Für jeden logisch zusammenhängenden Datenkomplex gibt es eine Implementation eines DataStore Interfaces, welche die relevanten Daten von der Datenbank läd, cached, zur Verfügung stellt und in die Datenbank zurückschreibt.

Freitag, 14. Dezember 2007

Wasser auf meine Mühlen

Manchmal tut es der eigenen Schadenfreude richtig gut, recht zu behalten.
So konnte ich mir zum Beispiel bei der jüngsten Meldung, StudiVZ habe seine AGBs geändert ein fieses Grinsen nicht verkneifen.

Zwar beschwört Dirk Hensen, der Pressesprecher von StudiVZ, daß die Benutzerdaten nicht weiter gegeben werden, sondern lediglich intern ausgewertet werden, aber die Handlungen des Vereins sprechen eine andere Sprache.
In den neuen AGBs, die einige Nutzer schon zugeschickt bekommen haben, heißt es zum Beispiel:


"Ich willige ein, dass StudiVZ Bestandsdaten und/oder Nutzungsdaten von mir an Dritte weitergibt, wenn und soweit die Übermittlung der Daten aufgrund gesetzlicher Vorschriften und/oder infolge von Gerichtsentscheidungen zulässig ist."

Wow, daß klingt gar nicht mehr so freundlich. Dazu kommt die Ankündigung, das Profile von abgemeldeten Benutzern nicht mehr gelöscht werden, sondern lediglich deaktiviert werden, was nur mit dem Wunsch, die Daten weiterzuverhökern erst Sinn ergibt.

Zumal das monolitische Portal bereits in der Vergangenheit negativ aufgefallen ist, was die technische Sicherung und den schlampigen Umgang mit Benutzerdaten angeht.

Die Brisanz gesammelter Informationen gerade über Kontakte und soziale Netzstruckturen, sollte spätestens seit den jüngsten Eskapaden unseres staatlichen Sicherheitsapparates jedem bewusst sein.
Wenn man dann solche Ankündigungen, die mangelhaften Sicherheitssysteme des StudiVZ und die geplante Vorratsdatenspeicherung zusammenzählt, erhält man ein wirklich erschreckendes Bild.

Zum Geleit


Ein Portal wie StudiVZ, wer-kennt-wenn und Konsorten ist grundsätzlich immer unsicher. Das liegt zum einen daran, daß es (sobald eine gewisse Größe erreicht ist) ein lohnendes Ziel für Datensammler darstellt und zum anderen daran, daß der gesammte Code unter den Fittichen derer liegt, die das Portal betreuen und deren Entscheidung es folglich unterliegt, Daten an dritte zu verscheuern. Hier besteht eine immens gefährliche Zusammenlegung von Machtpotenzial.
Daher erscheint für mich das einzig sichere Portal dieser Art eines, welches komplett auf einer OpenSource software aufsetzt und auf einem gemeinnützigen, über Spenden finanzierten Server (ähnlich des Wikipedia-Konzepts) läuft.

So long.

Mittwoch, 28. November 2007

Das digitale Postgeheimniss

Gerade in Anbetracht der jüngsten politischen EskapadenEntwicklungen wird (Gott sei Dank) die technische Unsicherheit diverser Mitteilungsmedien (z.B. e-mail) immer deutlicher.
Obwohl man mit dem technischen Hintergrund sowohl des Problems, als auch der verschiedenen dargebotenen Lösungen, nichts anfangen kann, hinterfragt man heute etwas kritischer die technische Sicherheit der zu übermittelnden Information.
Das ist eine gute Entwicklung.
Eine weitere gute Entwicklung ist, daß der Komfort sowie die Ausgereiftheit von sicheren Übertragungsmöglichkeiten im e-mail Verkehr heute wesentlich weiter entwickelt sind, als noch vor 4 Jahren.

Dennoch lese und höre ich des öfteren Stimmen, die all zu leichtsinnig Brief und e-mail miteinander vergleichen wollen und sich nicht bewusst sind, wie unsicher eine pure Plaintext e-mail eigentlich ist und woran das liegt.

Also worüber reden wir hier eigentlich genau?

Die Situation


Laut NTV versenden und empfange etwa 37 Mio. Deutsche zwischen 16 und 74 Jahren (knapp 2 Drittel der Befragten) Emails.
Die Meisten machen sich über den Verteilungsweg und die Sicherheit des Ganzen wenig bis gar keine Gedanken.
Zum einen versteht man es ohnehin nicht so wirklich und zum anderen vertraut man auch einfach darauf, daß unser Grundgesetz das schon regeln wird. Immerhin sei Email ja doch sowas ähnliches wie der gewöhnliche Brief.

Mit dieser verwegenen Vorstellung würde ich heute gerne aufräumen.

Emails und die analoge Briefpost sind nicht –noch nicht mal annähernd– das Selbe!


Briefpost


Die altbewährete Briefpost sieht ein beschriebenes Stück Papier vor, welches durch einen Umschlag vor neugierigen Blicken geschützt ist. Der Schutz ist zwar nicht unüberwindlich aber doch ausreichend um einem flüchtigen Versuch standzuhalten.

Viel wichtiger als der Umschlag, im Vergleich zur elektronischen Post, ist jedoch die Tatsache, daß der Brief während des gesamten Versendeprozesses ohne Kopie im Orginal weitergegeben wird. Ohne weitere aktive Handlungen existiert also immer nur genau ein Schriftstück (das Orginal) mit der übermittelten Information.
Des weiteren ist der komplete Weg des Briefes eindeutig bestimmbar. Der Brief landet zuerst im Postbriefkasten, geht von dort an meine lokale Postzentrale und wird von dort an eindeutug bestimmbare Zwischenstationen weitergereicht, bis er schließlich vom lokalen Postboten der Empfängerstadt in den Briefkasten des Empfängers eingeworfen wird.
Da man durch diese Gegebenheiten sowohl eindeutig bestimmen kann, wo der Brief zu einem bestimmten Zeitpunkt ist/war, als auch klar nachvollziehen kann, wer an seiner Weiterleitung beteiligt war, kann, in dem Fall ein Brief würde unrechtmäßig gelesen oder kopiert werden, ein eindeutiger Verantwortlicher innerhalb der Post bestimmt werden.

Das ist der Hauptgrund, warum es im Falle analoger Briefpost vollkommen ausreichend ist, einen Artikel im Grundgesetz zu verankern, der das unbefugte Auslesen eines Briefes verbietet.

e-mail


Eine e-mail ist ein rein virtuelles Replik des Briefpost Verfahrens. Ich schreibe meinen Brief, addressiere ihn und schicke ihn ab. Nach der Verteilung, die in der Regel zwischen 3 Sekunden und 5 Tagen braucht, erhält der Empfänger den Brief und kann ihn lesen.

Dann stellen wir doch mal ein paar Fragen:

  • “Ist die Nachricht wirklich von dir?”

  • “Hast du wirklich das geschrieben, was ich hier lese?”

  • “Hat jemand anderes die Nachricht unterwegs gelesen?”

  • “Wurde die Nachricht gar unterwegs manipuliert?”



Im Bestreben, diese Fragen zu beantworten kommen wir zu einem sehr ernüchternden Ergebniss: Das einzige worauf wir uns verlassen können ist die Tatsache, daß die Nachricht irgendwann auf unserem Computer angekommen ist. Denn daß wird dadurch daß wir die Nachricht betrachten können klar.

Die Probleme beim beantworten der obrigen Fragen werden erst deutlich, wenn man sich das Verfahren der Nachrichtenverteilung einmal genauer ansieht.
Jede Email wird nach einem Protokol namens SMTP versandt, welches 1982 als reines Metatext Protokol definiert wurde.
Danach wird die Nachricht zusammen mit verschiedenen Metadaten zur Absender- und Empfängeradresse als menschenlesbarer Text in einem bestimmten Format versandt.

Fakt: Eine e-Mail Übertragung ist ohne weiteres von einem Menschen auslesbar.

Das Versenden selbst erfolgt von Mailserver zu Mailserver, wobei verschiedene Zwischenstationen angesprungen werden können um den optimalen Übertragungsweg zu finden. Welche Server in welcher Reihenfolge angesprungen werden ist dabei nicht nachvollziehbar.

Fakt: Die tatsächliche Herkunft einer e-mail kann nicht nachgewiesen werden.

Wenn im Computerumfeld von übertragen gesprochen wird ist Grundsätzlich von einem Kopiervorgang auszugehen. Anderst als beim analogen Briefverkehr, wird niemals ein Orginal weitergegeben. Statt dessen sendet jede Zwischenstation lediglich eine Kopie der Daten an die nächste. Was eigentlich eine bekannte Tatsache sein sollte, wird im Vertrauen auf die e-mail häufig vergessen oder unterschlagen.
Wenn aber jede Datenweitergabe aus einem Kopiervorgang besteht, so kann nicht garantiert werden, wer auf einer Zwischenstation die Nachricht selbst speichert, ausließt oder gar in manipulierter Form weiterübermittelt.

Fakt: Es ist nicht möglich die Echtheit oder das unverletzte Briefgeheimniss einer Nachricht nachzuweisen.

Schlußfolgerung



Angesichts der technischen Unterschiede kann davon ausgegangen werden, daß e-mail und Briefpost –außer daß es sich in beiden Fällen um Komunikationsmedien handelt– nicht vergleichbar sind.
Daraus folgt, daß auch die Gesetzesgrundlage, wie sie für Briefpost gilt, alleine nicht ausreichend ist, um eine private oder gar rechtlich bindende Kommunikation via e-mail zu garantieren. Daß sich die einzelnen Zwischenstellen bei einer e-mail Übertragung daran halten, die Nachrichten weder mitzulesen noch zu verändern bzw. nachvollziehbar auszuliefern ist mehr der Freundlichkeit der Serverbetreiber als einem rechtlich oder technisch bindenden Umstand zuzuordnen.

Daher muß klar sein, daß weitere Maßnahmen ergriffen werden müßen um e-mail als Kommunikationsmedium zu vervollständigen.
Derzeit existieren zwei ziemlich ausgereifte Konzepte um das zu erreichen: PGP und OpenPGP.

Beide besitzen die selbe technische Grundlage.
Auf der Basis asymetrischer Kryptoverfahren können e-mails verschlüßelt werden. Durch die Verwendung des öffentlichen Schlüßel des Adressaten kann garantiert werden, daß nur dieser die Nachricht wieder entschlüßeln und lesen kann.
Durch einen –mit dem privaten Schlüßel des Absenders verschlüßelten– Hashwert, welcher der Nachricht angefügt wird kann auch bei einer unverschlüßelten Nachricht sowohl deren Integrität geprüft, als auch der Absender eindeutig identifiziert werden.
Beiden Verfahren ist gemein, daß die tatsächliche Sicherheit somit von der Glaubwürdigkeit der öffentlichen Schlüßel abhängt. Oder anderst ausgedrückt: Wenn jeder Kommunikationsteilnehmer darauf vertrauen kann, daß der öffentlicher Schlüßel des jeweils anderen tatsächlich von ihm ist (und nicht von einer dritten Person erstellt und eingemogelt wurde) dann kann die Sicherheit der Kommunikation eindeutig nachgewiesen werden.
Die Art und Weise wie diese Glaubwürdigkeit hergestellt wird ist es auch, die die beiden Verfahren von einander unterscheidet.

Während PGP über eine Hirarchie von vertrauenswürdigen Zertifizierungsstellen die Vertrauenswürdigkeit eines Schlüßels überprüft, legt bei OpenPGP jeder Nutzer für jeden Schlüßel zwei Vertrauensstufen fest: Zum einen wie sicher er ist, daß der Schlüßel eindeutig der entsprechenden Person entspricht und zum anderen wie sehr er der entsprechenden Person dahingehend vertraut andere Schlüßel zu identifizieren.
Vertraut ein Nutzer einem angebotenen Schlüßel, so kann er diesen unterschreiben und sein Vertrauen in den Schlüßel damit bekunden. Ein anderer Nutzer kann daran entscheiden, ob er dem selben Schlüßel nun ebenfalls vertraut oder nicht.
Daraus entsteht ein loses Netz der Glaubwürdigkeit, nach dem Muster, lose gekoppelter privater Zertifizierungsstellen. Je bekannter ein Schlüßel ist, desto wahrscheinlicher ist seine Identität, den das Netz vertraut ihm.

Ich könnte hier noch wesentlich tiefer auf die Technik eingehen, will es aber erst einmal dabei belasen. Wer sich genauer Informieren will findet in den Wiki-Links und den unten angeführten weitergehenden Links genügend Material.
Wenn weiteres Interesse besteht kann ich später auch noch einen Eintrag explitzit zu OpenPGP und dessen Verwendung schreiben.

Bleibt nur noch ein Statement zu machen:

Wer ohne Verschlüßelungen oder Signaturen zu verwenden e-mails verschickt oder solchen empfangenen e-mails in hohem Maße vertraut geht damit ein immenses Risiko ein und kann im Zweifel nicht auf den geschriebenen Text verweisen.

Leute, verschlüßelt eure Mails


Ich bedanke mich für das Interrese.



Weiterführende Links:

[RFC821] SMTP Protocol Definition
[RFC4880] OpenPGP Standard
Die PGP Coorperation
Eine ziemlich gute Anleitung zu OpenPGP

Dienstag, 27. November 2007

Jungfernschrieb

int main(){
    std::cout << "Hello World!" << endl;
    return 0;
}



Hallo und Willkommen,
An dieser Stelle werde ich mich in Zukunft über diverse Themen der Softwareindustrie sowie der freien Softwareentwicklung im Sinne des Open Source Gedanken auslassen.

Ich werde sowohl eigene Projekte veröffentlichen (und über deren Fortschritt berichten), als auch über interessant erscheinende Projekte anderer Autoren berichten.

Des Weiteren werde ich ---wann immer mir der Sinn danach steht--- über gute und schlechte Techniken, Trends und politische Entscheidung rund um das Thema Softwareentwicklung schreiben.

Sämtliche (oder zumindest nahezu sämtliche) Einträge werden sich auf dieses grobe Themengebiet richten, wobei zum einen der professionellen Softwareentwicklung für Serversysteme mit Java und zum anderen die hobbyhafte Entwicklung von Spielen und Multimediaanwendungen unter Linux mit Hilfe von C++ und der libSDL meine Hauptaufmerksamkeit erlangen werden.

Ich wünsche dir, lieber Leser, viel Spass beim Stöbern und freue mich schon auf deine Kommentare