Westfälische Wilhelms-Universität Münster
Ausarbeitung
Schützbarkeit von Algorithmen
(im Rahmen des Seminars „Informatik und Recht“)
Christian Sonnenberg
Themensteller: Prof. Dr. Herbert Kuchen Betreuer: Prof. Dr. Herber Kuchen Institut für Wirtschaftsinformatik Praktische Informatik in der Wirtschaft
II
Inhaltsverzeichnis
1 Einleitung ...................................................................................................................1
2 Das Konzept „Algorithmus“ ......................................................................................1
2.1 Determinanten des Algorithmenbegriffs...........................................................1
2.2 Vom Problem zum Algorithmus .......................................................................7
2.3 Reverse Engineering - vom Maschinencode zum Quellcode .........................13
3 Aspekte der Schützbarkeit von Algorithmen ...........................................................15
3.1 Urheberrecht und Patentrecht..........................................................................15
3.1.1 Algorithmen und das Patentrecht ................................................................15 3.1.2 Äquivalenz von Programmen und Schriftwerken .......................................16
3.2 Einfluss der Erfindungshöhe auf die Schutzbedürftigkeit ..............................18
3.3 Abhängigkeit der Schutzbedürftigkeit von der Verfeinerungsstufe...............20
3.4 Open – Source .................................................................................................21
4 Fazit..........................................................................................................................22
A Bytecode des Beispiels „Insertion Sort“ ..................................................................23
B Ergebnis der Anwendung eines Java Obfuscators – „Insertion Sort“......................25
C Quicksort – Algorithmus..........................................................................................27
Literaturverzeichnis.........................................................................................................28
Kapitel 1: Einleitung
1
1 Einleitung
In den letzten Jahren wurde dem Gebiet des Softwarerechts eine gestiegene
Aufmerksamkeit zuteil. Vielfach wird bemängelt, die Rechtssprechung würde mit einer
anachronistischen Terminologie vergeblich versuchen, Regelungen für eine noch junge,
dynamische und innovative Informationsgesellschaft treffen zu können.
Einige Vertreter der Softwarebranche merken beispielsweise schon seit längerem
kritisch an, dass ein Schutz für Programme nicht ausreichend sei, vielmehr wäre es von
Interesse, speziell auch Algorithmen schützen lassen zu können.
Das Thema der Schützbarkeit von Algorithmen wird in dieser Arbeit aufgegriffen.
Vor dem juristischen Hintergrund erscheint es zunächst wichtig, zu klären, was unter
einem Algorithmus zu verstehen ist. Überdies erscheint es notwendig, zu erläutern,
wovon die Schutzwürdigkeit eines Algorithmus abhängig ist und welche Implikationen
ein derartiger Schutz mit sich bringt.
Diese Fragestellungen sollen mit dieser Arbeit der Reihe nach aufgegriffen werden.
2 Das Konzept „Algorithmus“
In diesem Kapitel versuche ich, die wesentlichen Eigenschaften eines Algorithmus
herauszustellen und die für das Thema relevanten „algorithmischen“ Aspekte genauer
zu untersuchen, ohne dabei jedoch den Versuch zu unternehmen, eine konkrete
Definition zu entwickeln.
Ziel dieses Kapitels soll es sein, eine genaue Vorstellung darüber zu erlangen, was unter
dem algorithmischen Konzept im Kontext der Informatik zu verstehen ist und welche
Implikationen dies in der praktischen Anwendung mit sich bringt.
2.1 Determinanten des Algorithmenbegriffs
Auch wenn der Begriff des Algorithmus als zentral und fundamental für die Informatik
angesehen wird, so kann er nicht losgelöst vom Begriff des Problems betrachtet werden,
welcher ebenso zentral in der Informatik ist. Ohne die Existenz konkreter Probleme (im
informatorischen Sinne) wäre eine Diskussion über Algorithmen hinfällig.
Kapitel 2: Das Konzept „Algorithmus“
2
Ein Algorithmus gilt als ein Verfahren zur Lösung eines Problems. Ein Problem ist
hierbei eine Fragestellung, die hinreichend genau beschrieben ist. Eine Problemklasse
ist eine Menge von ähnlichen Fragestellungen (mit jeweils unterschiedlichen konkreten
Eingabewerten), die auch Instanzen genannt werden [Wi97, S. 10]. Somit ist zusätzlich
festzuhalten, dass Algorithmen konkrete Probleme einer bestimmten Problemklasse
lösen. Eine Problemklasse stellt z.B. das Suchen eines Elementes in einer Menge dar,
das Sortieren von Elementen, das Lösen linearer Gleichungen oder auch die
Berechnung des kürzesten Weges in einem Navigationssystem. Instanzen der Klasse
Suche eine Element einer Menge wären z.B.: „ist 9 ∈ {7, 9, 14, 21}?“ oder
„ist 1 ∈ {2, 3, 4}?“
Typischerweise wird ein Algorithmus für eine bestimmte Problemklasse entworfen und
löst daher nur Probleme derselben Problemklasse. Allerdings existieren sehr oft für eine
Problemklasse mehrere Algorithmen.
Ein Algorithmus ist folglich spezifisch. In diesem Sinne erfüllt jeder Algorithmus eine
bestimmte funktionale Spezifikation. Diese Eigenschaft resultiert aus einer formaleren
Sichtweise auf Probleme und betont den Verarbeitungsaspekt [Wi97, S. 10]. Die
Problemklasse wird hierbei als Funktion zwischen Eingaben (Input) und Ausgaben
(Output) beschrieben. Aufgabe eines Verfahrens zum Lösen eines Problems ist dann die
Berechnung (Verarbeitung) der Ausgabe auf der Grundlage der Eingabe.
Algorithmen benötigen daher eine Menge von Input – Werten, welche auch leer sein
kann, und transformieren diese in einen Output gemäß einer funktionalen Spezifikation.
Problemklasse K
Problem P1 Problem P2
K-Algorithmus
INPUT
OUTPUT
Lösung P1 Lösung P1
Problemklasse K’
Problem P1 Problem P2
K’-Algorithmus
INPUT
OUTPUT
Lösung P1 Lösung P1
Abbildung 1: Algorithmen vs. Probleme u. Problemklassen
Kapitel 2: Das Konzept „Algorithmus“
3
Algorithmen sind häufig parametrisierbar [He92, S. 20] Das ist vor allem dann wichtig,
wenn der Algorithmus mehrere Probleme einer Problemklasse lösen können muss, was
in den meisten Fällen erwünscht ist. Die Auswahl des Einzelfalls erfolgt hierbei über
Parameter. Diese Eigenschaft wird als Allgemeinheit von Algorithmen bezeichnet.
Unter Berücksichtigung des informatorischen Kontextes wird von einem Algorithmus
gefordert, dass er maschinell ausführbar ist. Kennzeichnend für einen Algorithmus ist
dabei, dass die Verarbeitung des Inputs zum Output durch eine endliche Abfolge von
elementaren Einzelschritten erfolgt.
Im Hinblick auf die Möglichkeit der maschinellen Realisierung eines Verfahrens zur
Lösung eines Problems ist es erforderlich, dass die Lösungsvorschrift nicht in einer
beliebigen, sondern in einer endlichen, präzisen Beschreibung unter Verwendung
effektiver, elementarer Verarbeitungsschritte erfolgt [Wi97, S. 10].
Die Forderung nach einer endlichen Beschreibung ist notwendig, da es sich bei einem
Algorithmus um eine Form von Information handelt, die wie alles andere eine
(maschinelle) Repräsentation, also eine äußere Form besitzen muss. Wenn diese Form
handhabbar sein soll, muss diese Repräsentation natürlich endlich sein, sonst könnte
man sie im Falle einer sprachlichen Formulierung nicht vollständig aufschreiben [Wi97,
S. 10]. Zum Aspekt der Repräsentation bzw. Darstellung von Algorithmen wird an
späterer Stelle noch genauer eingegangen.
Eine präzise Beschreibung soll Missverständnisse bei der Interpretation ausschließen.
Die Bedeutung und die Auswirkung eines jeden Einzelschrittes muss für jeden
auftretenden Fall genau festgelegt sein. Dies wird oft auch als Definitheit bezeichnet.
Um dies zu gewährleisten, bedarf es einer vorgegebenen Sprache mit eindeutig
festgelegter Interpretation, die hinreichend exakt ist [Wi97, S. 10]. Zu diesem Zweck
wurden Maschinensprachen und Programmiersprachen eingeführt. Die in diesen
Sprachen zulässigen Beschreibungsmittel besitzen alle eine klare Bedeutung und
ermöglichen so eine adäquate Spezifizierung von maschinell ausführbaren Algorithmen.
Algorithmenspezifikationen werden, wie später noch erläutert wird, typischerweise auf
unterschiedlichen Abstraktionsniveaus formuliert. Auf einer oberen Abstraktionsebene
geschieht dies oft auf eine semiformalen Art und Weise durch den Gebrauch von
Umgangssprache in Kombination mit einer repräsentativen Kontrollstruktursyntax von
Kapitel 2: Das Konzept „Algorithmus“
4
Programmiersprachen (Pseudocode). Auch auf diesen höheren Abstraktionslevels gilt
die Forderung nach einer (hinreichend) präzisen Beschreibung.
Nicht die konkrete Realisierung auf einer realen Maschine ist entscheidend bei der
Formulierung eines Algorithmus, sondern die Idee der Komposition der elementaren
Operationen, um ausgehend vom Input einen spezifikationskonformen Output zu
erhalten. Dies bedeutet insbesondere, dass diese Idee so genau (präzise) formuliert wird,
als dass das algorithmisch formulierte Konzept von beliebigen Personen, denen diese
Formulierung vorliegt, mental und zusätzlich auch formal jeweils identisch reproduziert
wird. Diese Forderung stellt somit sicher, dass Algorithmen zwischen Personen
kommuniziert werden können, ohne dass die Idee und die Details der Lösungsfindung
aufgrund von Ambiguität verloren gingen.
„… the reader should not expect to read an algorithm as he reads a novel; such an
attempt would make it pretty difficult to understand what is going on; An algorithm
must be seen to be believed…” [Kn73, S. 4]
Charakteristisch für Algorithmen ist, dass deren Ausführung beim Ausführenden
(„Prozessor“) keine Intelligenz, Einsicht, Verstand, Intuition oder schöpferische
Phantasie voraussetzt [Wa89, S. 15]. Daher hat eine algorithmische Beschreibung
insbesondere hinreichend präzise zu erfolgen. Somit sind Algorithmen wie geschaffen
dafür, ein spezifiziertes Lösungsverfahren maschinell (computergestützt im engeren
Sinne) umzusetzen und zur Ausführung zu bringen, denn speziell Maschinen sind als
solche weder intelligent noch in der Lage, intuitiv handeln zu können. Eine Maschine
muss folglich „Schritt für Schritt“ angeleitet werden, um das gewünschte Verhalten
(gemäß der algorithmischen Spezifikation) zu realisieren ohne dass dafür ein
inhaltliches Verständnis für das Vorgehen seitens der Maschine erforderlich ist. Die
Forderung nach der Ausführbarkeit eines Algorithmus auf einer konkreten Maschine
(Computer) hingegen ist nicht charakteristisch für das Konzept von Algorithmen,
wenngleich die prinzipielle Möglichkeit der maschinellen Ausführung aufgrund der
Natur des Konzeptes implizit gegeben ist.
Somit steht die Idee, um die herum ein Algorithmus konstruiert wird, im Mittelpunkt
der Betrachtung. Daher ist es sehr wichtig, die Idee unmissverständlich und präzise
kommunizieren zu können und zwar auf allen Abstraktionsebenen einer
algorithmischen Formulierung. Allerdings ist der Begriff der Präzision auf höheren
Abstraktionsstufen nicht im Sinne von „Beschreibung in allen Einzelheiten“ zu
Kapitel 2: Das Konzept „Algorithmus“
5
verstehen. Vielmehr handelt es sich auf einer sehr hohen Abstraktionsstufe um
konzeptionelle und gedankliche Skizzen eines Algorithmus, welche aber schon die
wesentliche Idee und das Konzept der Lösungsstrategie dokumentieren und damit
insofern präzise sind, als dass aus dieser algorithmischen Skizze unmittelbar jeweils
detailliertere Beschreibungen abgeleitet werden können (-> hinreichende Präzision).
Der Aspekt der Effektivität der Arbeitsschritte ist ebenso von Bedeutung. Effektivität in
diesem Sinne ist dann gegeben, wenn alle Operationen oder Einzelschritte eines
Algorithmus hinreichend einfach und elementar sind, so dass sie prinzipiell auch von
einem Menschen mit Bleistift und Papier exakt und in einer endlichen Zeit ausgeführt
werden könnten [Kn73 S. 6].
Bei der Beschreibung eines Algorithmus ist zwischen den elementaren Operationen
einerseits und den Vorschriften, wie und in welcher Reihenfolge sie angewandt werden
sollen, zu unterscheiden [Wi97 S. 11]. Ein Elementarschritt ist von einer Maschine in
einem Schritt (als unteilbare Aktion) auszuführen. Bezüglich der Beschreibung der
Abfolge der Elementarschritte sind folgende Strukturelemente eines Algorithmus
anwendbar: Sequenz; Auswahl von Fällen mit anschließender Entscheidung, was als
nächstes ausgeführt wird; feste Wiederholungen von Schrittfolgen sowie bedingte
Wiederholungen.
Nachdem nun die prinzipielle Art der Beschreibung von Algorithmen diskutiert wurde,
sollen jetzt noch einige Eigenschaften von Algorithmen besprochen werden.
Ein Algorithmus heißt terminierend genau dann, wenn der Algorithmus für alle
erlaubten Eingaben nach endlich vielen Schritten beendet wird. Für die praktische
Anwendung sind in den meisten Fällen primär terminierende Algorithmen interessant.
Einige (nicht unbedeutende) Ausnahmen bilden hier Betriebssystemfunktionen oder
Prozess-Steuerungsalgorithmen [He92, S. 21]. Tatsächlich ist eine Forderung nach der
Terminierung nicht präzise genug für die praktische Verwendung [Kn73, S. 6]. Ein
Algorithmus, welcher beispielsweise ermitteln soll, ob bei einer Partie Schach der
Spieler „weiß“ zwingend gewinnt, ist zwar endlich und terminiert, aber wir werden das
Ergebnis in unserem Leben vielleicht niemals erfahren, da ein solcher Algorithmus sehr
viel Berechnungszeit beanspruchen wird. Ein brauchbarer Algorithmus sollte daher
nicht irgendwie oder irgendwann, sondern möglichst in einer akzeptablen Anzahl von
Schritten terminieren.
Kapitel 2: Das Konzept „Algorithmus“
6
Determinismus ist eine weitere typische Eigenschaft von Algorithmen. Diese ist immer
dann gegeben, wenn die Reihenfolge der Verarbeitungsschritte des betrachteten
Algorithmus stets eindeutig festgelegt ist, in der Auswahl der Verarbeitungsschritte also
keine Wahlmöglichkeit besteht. Dies heißt dann auch, dass verschiedene Abarbeitungen
eines Algorithmus für die gleiche Eingabe immer die gleiche Folge von Schritten
ausführen [Wi97, S.12]. Determinismus ist nicht immer unbedingt notwendig oder
erwünscht. Einige Problemklassen beispielsweise im Bereich der künstlichen Intelligenz
verbieten gar die Anwendung deterministischer Algorithmen, da hier insbesondere mit
stochastischen Modellen gearbeitet wird und somit auch die Reihefolge der
Verarbeitungsschritte zwingend stochastisch getrieben ist. Jede neue Abarbeitung eines
solchen nicht deterministischen Algorithmus bei unverändertem Input würde jeweils
eine andere Reihenfolge bei der Ausführung von Einzelschritten bewirken und
gegebenenfalls auch ein anderes Ergebnis.
Eine ganz wesentliche Eigenschaft ist zudem die Determiniertheit von Algorithmen. Ist
das Ergebnis der Abarbeitung für alle Eingaben eindeutig festgelegt, so ist ein
Algorithmus determiniert. Sinnvolle Beispiele für nicht determinierte Algorithmen sind
nur schwer zu finden, da Nicht-Determiniertheit der Auffassung, dass ein Algorithmus
eine funktionale Spezifiktion erfüllen soll (zumindest auf den ersten Blick),
widerspricht [Wi97, S. 13]. Nach obigen Erläuterungen ist aber auch klar, dass
Algorithmen denkbar sind, bei denen der Output nicht unbedingt von vornherein für alle
Eingaben eindeutig festgelegt ist, für ein und dieselbe Eingabe (-menge) also jeweils
unterschiedliche aber gültige Ergebnisse erzielt werden können. Vornehmlich trifft dies
auf Algorithmen zu, die entweder auf stochastischen Modellen arbeiten (siehe
künstliche Intelligenz) oder Algorithmen, deren Abarbeitung mit realen Zufällen
verknüpft ist (z.B. Algorithmen basierend auf Warteschlangen, Transaktionen;
Betriebssystemalgorithmen).
Ein Algorithmus heißt sequentiell, wenn zu jedem Zeitpunkt nur ein elementarer
Arbeitsschritt ausgeführt werden kann. Parallel ist er hingegen, wenn gewisse
Arbeitsschritte nebeneinander (zur gleichen Zeit) ausgeführt werden. Es sei angemerkt,
dass die Eigenschaft sowohl einem Algorithmus zukommen kann, als auch der
Ausführung eines Algorithmus [Wi97, S. 13].
Wie aus den obigen Erläuterungen deutlich wird, muss ein Algorithmus nicht alle
Eigenschaften auf einmal erfüllen. Ein idealtypischer Algorithmus sollte zwar
Kapitel 2: Das Konzept „Algorithmus“
7
terminieren, deterministisch und zugleich determiniert sein. So wäre gesichert, das ein
Output nach endlicher Zeit zu erwarten ist, dessen Herleitung nachvollziehbar (weil in
eindeutiger Weise geschehen) und dessen Validität (siehe funktionale Spezifikation)
gesichert. Allerdings muss ein deterministischer Algorithmus nicht unbedingt
determiniert sein. Vielfach ist eine Forderung nach Determiniertheit noch nicht einmal
zweckmäßig (siehe künstliche Intelligenz). Selbst das Kriterium der Terminiertheit ist in
einigen wenigen aber umso bedeutenderen Anwendungsgebieten nicht erfüllbar (siehe
Betriebssystem). Dieser Umstand, dass keine allgemeinen Aussagen über die
Anforderungen bezüglich der Eigenschaften eines Algorithmus getroffen werden
können, schlägt sich in der Literatur insofern nieder, als das die Definitionen bezüglich
konstituierender Merkmale und suffizienter Anforderungen an einen Algorithmus
vielfach einen „defensiven“ Charakter aufweisen.
In diesem Sinne kann ein Algorithmus zusammenfassend also als ein
Problemlösungsverfahren für Probleme einer bestimmten Problemlösungsklasse
betrachtet werden. Hierbei muss er einer funktionalen Spezifikation genügen. Die
Lösungsfindung geschieht in einer Abfolge von elementaren Einzelschritten. Die
algorithmische Darstellung und Beschreibung der Komposition dieser Einzelschritte hat
prinzipiell in einer endlichen, präzisen Beschreibung des Verfahrens unter Verwendung
elementarer Verarbeitungsschritte zu erfolgen.
Neben dieser umgangssprachlichen Annäherung an den Algorithmusbegriff gibt es
weitaus formalere (mathematische) Ansätze zur Beschreibung des algorithmischen
Konzeptes. Beispielsweise ist es auch möglich, für jeden Algorithmus zu fordern, auf
einer so genannten Turing-Maschine ausführbar (turing - berechenbar) zu sein. Eine
Turing-Maschine ist dabei ein abstraktes theoretisches Modell eines Rechners zur
Abarbeitung eines Algorithmus. Ein Algorithmus ist in diesem Sinne also alles, was
eine Turingmaschine ausführen kann.
2.2 Vom Problem zum Algorithmus
Ausgangspunkt eines jeden Algorithmus ist die Formulierung einer Problemstellung (in
Form eines konkreten Problems oder einer Problemklasse). In den meisten Fällen ist die
Problemstellung jedoch sehr allgemein und wenig handhabbar bezüglich einer
strukturierten Lösungsfindung. Sollen beispielsweise zwei Zahlen miteinander addiert
werden, so ist zwar die Problemstellung benannt, jedoch ist noch nicht ersichtlich, wie
Kapitel 2: Das Konzept „Algorithmus“
8
diese Addition erfolgen soll und was in diesem Zusammenhang überhaupt unter einer
Zahl zu verstehen ist.
Es bedarf folglich einer Strukturierung und Formalisierung der Problemsstellung. Dies
geschieht durch eine geeignete Modellierung des Problembereiches [Ah87, S. 1-2].
Solch ein Modell ist meistens sehr präzise formuliert (formales Modell). Auf Grundlage
der Eigenschaften des formalen Modells kann identifiziert werden, was unter einer
„guten“ oder optimalen Lösung zu verstehen ist. Darauf aufbauend ist es jetzt möglich,
eine geeignete Lösungsstrategie zum Auffinden einer guten bzw. optimalen Lösung zu
entwickeln. Eine derartige Strategie (z.B. Durchsuchen des Lösungsraums) ist ebenfalls
abhängig von den Eigenschaften und Annahmen des Modells.
Hier wird deutlich, dass schon die Modellierung des Problembereiches weitreichende
Auswirkungen auf den darauf aufbauenden Algorithmus hat, ist er doch nichts anderes
als die Formalisierung der Lösungsstrategie, eine Lösungsvorschrift also. Im Beispiel
der Addition zweier Zahlen ist die Art der Modellierung einer „Zahl“ durchaus
entscheidend für die Handhabbarkeit und potentielle Effizienz einer Addition: Stelle ich
Zahlen einfach als Striche dar (Unärsystem) oder lege ich die römische
Zahlendarstellung zugrunde? Rechne ich gar mit arabischen Ziffern? Wenn ja, im
Dual-, Oktal- oder Dezimalsystem? (Frage der Modellierung). Wie sieht die erhaltene
Zahl nach der Addition aus und nach welchen Regeln gelange ich zu dieser
Zahlendarstellung? (Frage nach der Lösung des Problems und den Eigenschaften des
Modells). Je nachdem, welches Zahlensystem zugrunde gelegt wird, ist die
Lösungsstrategie eher simpel oder aber sehr aufwendig (z.B. ist die Addition von
Zahlen im Unärsystem sehr leicht im Vergleich zur Addition römischer Zahlen!).
Ist der Problembereich nun hinreichend formalisiert/ modelliert, kann ausgehend von
der Lösungsstrategie ein Algorithmus unter Berücksichtigung der modellspezifischen
Eigenschaften entwickelt werden.
Dieser Prozess wird in Form der so genannten schrittweisen Verfeinerung vollzogen.
Infolge der Verfeinerung durchläuft der Algorithmus verschiedene Abstraktionsstufen.
Dies führt zu einer „Ableitungskette“, in der ausgehend von einer recht abstrakten
Algorithmusskizze nach und nach detailliertere (und damit weniger abstrakte)
algorithmische Beschreibungen abgeleitetet werden. Die Präzision der Beschreibung
nimmt so mit sinkendem Abstraktionsgrad zu. Der Begriff der Abstraktion bezieht sich
hier also auf die Art der Darstellung und der dadurch implizierten „Entfernung“ zur
Kapitel 2: Das Konzept „Algorithmus“
9
konkreten Ausführung auf einer Maschine (dem ausführbaren Programm in Form von
Maschinencode).
Auf der obersten Abstraktionsstufe ist der Algorithmus umgangssprachlich oder
graphisch (Struktogramme, Sequenzdiagramme) formuliert. Schon in diesem Stadium
muss die Formulierung den Anforderungen an algorithmische Beschreibungen genügen,
insbesondere des präzisen Ausdruckes (siehe 2.1). Allerdings wird dies in der Praxis
häufig nicht in dieser strikten Form gehandhabt. Vielmehr wird der Prozess der
schrittweisen Verfeinerung dahingehend interpretiert, als dass die Präzision (und damit
auch der Grad der Eindeutigkeit) der Beschreibung mit abnehmendem
Abstraktionsniveau zu verstärken ist. Die Präzision erfolgt dann häufig erst im
Implementierungsprozess, wenn der Algorithmus in einer konkreten
Programmiersprache formuliert wird.
Im Folgenden soll die schrittweise Verfeinerung mit vorausgehender
„Strategieformulierung und Modellierung“ an einem Beispiel erläutert werden. Die
Problemstellung lautet: „Sortiere eine Menge (unsortierter) ganzer Zahlen aufsteigend“.
Modellierung: Die Menge der ganzen Zahlen wird durch ein Feld (Array)
repräsentiert. Dabei repräsentiert jedes Feldelement eine ganze Zahl und ist über
einen Index zugreifbar.
Eine mögliche Strategie (einfach aber nicht die „effizienteste“): Teile das Feld in
einen sortierten Teil und einen Unsortierten Teil wobei der unsortierte Teil
verkleinert werden soll. Anfangs bestehe der sortierte Teil nur aus dem ersten
Feldelement, der unsortierte aus den übrigen Feldelementen. Für alle Feldelemente
im Array mache folgendes: entferne das erste Element aus dem unsortierten Teil
und durchsuche den sortierten, um es an der korrekten Position einzufügen.
Die erste algorithmische Abstraktion im Zuge der schrittweisen Verfeinerung hierzu
ließe sich wie folgt darstellen:
füge ein
sortiert< … < … < …
unsortiert 1 2 3 5 7 9 4 8 6
Abbildung 2: visualisierte Idee Insertion Sort
Kapitel 2: Das Konzept „Algorithmus“
10
/*Sortieren eines Arrays durch Einfügen */// bis Restarray (unsortierter Teil) einelementigfor (int i = 1; i < array.length; i++)
// erstes Element aus unsortiertem Teil auswählen// Element als „tmp“ zwischenspeichern// durchlaufe den sortierten Teil in einer// Schleife von hinten nach vornewhile (sortierter Teil noch nicht durchlaufen und
Feldelement > „tmp“)// dabei vertausche in jedem Schritt die Inhalte des// aktuellen Feldelementes mit rechtem benachbarten// Feldelement
// füge „tmp“ an in das Feldelement ein, das zuletzt// untersucht wurde
Hier ist schon erkennbar, dass sich die Beschreibung des Algorithmus neben
umgangssprachlichen Formulierungen auch einer formaleren Kontrollstruktursyntax
aus Programmiersprachen bedient. So wird diese Art der Verfeinerung oder
Abstraktion auch als Pseudocode bezeichnet.
In der nächsten Verfeinerung wird dieser Pseudocode nun in die Syntax einer
beliebigen Programmiersprache übersetzt. Der große Vorteil von Pseudocode ist,
dass er von einer konkreten Programmiersprache abstrahiert, dieser aber in der
Regel ohne großen Aufwand in eine beliebige Programmiersprache übersetzt
(„abgeleitet“) werden kann. In diesem Beispiel wird der Pseudocode in die
Programmiersprache Java übersetzt:
/*Sortieren eines Arrays durch Einfügen */public static void insertionSort(int[] array) {// bis Restarray (unsortierter Teil) einelementigfor (int i = 1; i < array.length; i++) {
// erstes Element aus unsortiertem Teil auswählen// Element als „tmp“ zwischenspeichern
int tmp = array[i];// durchlaufe den sortierten Teil in einer// Schleife von hinten nach vorne
// Index fuer Durchlauf initialisierenint j = i - 1;
while ((j >= 0) && (tmp < array[j])) {// dabei vertausche in jedem Schritt die Inhalte des// aktuellen Feldelementes mit rechtem benachbarten// Feldelement
array[j+1] = array[j];//dekrementiere den Index jj = j – 1;
}// füge „tmp“ an in das Feldelement ein, das zuletzt// untersucht wurde
array[j+1] = tmp;} }
Kapitel 2: Das Konzept „Algorithmus“
11
Um den Algorithmus maschinell (auf einem Computer) ausführen zu lassen,
überführen wir den in der Programmiersprachensyntax beschriebenen Algorithmus
in ein Programm. Hierzu muss die algorithmische Beschreibung um
programmiersprachenspezifische Beschreibungsmittel und abstrakte Befehle
(Befehle, die unabhängig von einer konkreten Maschine sind), ergänzt werden. Ist
dies geschehen, ergibt sich der so genannte Quellcode. Hier wird auch deutlich, dass
ein Programm nicht mit einem Algorithmus gleichgesetzt werden kann. Vielmehr
stellt es eine notwendige Hülle dar, in welcher durchaus auch mehrere Algorithmen
verpackt sein können. Denkbar sind auch Programme ohne eine konkrete
Algorithmenbeschreibungen oder mit ausschließlich trivialer algorithmischer
Formulierung.
Für das Beispiel wird im Folgenden ein repräsentativer Quellcode aus (jetzt ohne
Kommentare und in Java-Syntax) dargestellt.
public class InsertionSort {
private static int[] array = {13,4,5,2,6,1};
public static void main(String args[]) {insertionSort(array);System.out.println(“Ergebnis: ”);for (int i = 0; i < array.length; i++) {System.out.println(array + “ ”);
}}
public static void insertionSort(int[] array) {for (int i = 1; i < array.length; i++) {
int tmp = array[i];int j = i - 1;
while ((j >= 0) && (tmp < array[j])) {array[j+1] = array[j];j = j – 1;
}array[j+1] = tmp;
}}
}
Kurze Erläuterung: das Programm sortiert die vorgegebene Menge {13, 4, 5, 2, 6, 1}
ganzer Zahlen und gibt diese anschließend auf dem Bildschirm aus. Auf die
Möglichkeit der manuellen Eingabe wurde verzichtet, um unnötige Komplexität am
Quellcode zu vermeiden. Schließlich geht es in diesem Beispiel um Anschaulichkeit
Kapitel 2: Das Konzept „Algorithmus“
12
und um das Verständnis für die Abstraktionsstufe „Quellcode“ im Prozess der
schrittweisen Verfeinerung.
Der Quellcode kann für sich genommen noch nicht auf einer konkreten Maschine
ausgeführt werden. Vielmehr muss er in eine Repräsentationsform umgesetzt
werden, die einer Maschine (dem Computer) zugänglich ist. Dazu wird der
Quellcode von einem Compiler der benutzten Programmiersprache in einen
Maschinencode bzw. in Maschinensprache übersetzt. Erst jetzt kann das Programm,
und mit ihm der Algorithmus zum laufen gebracht werden!
Der Maschinencode stellt die niedrigste Abstraktionsstufe dar. Eine algorithmische
Beschreibung in Maschinencode ist jetzt maschinenabhängig, wohingegen eine
Beschreibung in Form von Quellcode nach wie vor von der konkreten Maschine
abstrahiert. In Java kann z.B. ein und derselbe Quellcode in verschiedene
Maschinencodes übersetzt werden. Das compilierte Programm liegt in diesem
Beispiel als „Quasi-Maschinencode“ für die Java-Virtual-Machine vor, dem so
genannten Bytecode. Dieser sei aus Platzgründen nicht an dieser Stelle, sondern im
Anhang A vollständig aufgeführt.
Allerdings ist der Quellcode insoweit spezifischer als ein Pseudocode mit gleicher
Bedeutung, als dass der Quellcode ausschließlich für die Programmiersprache gilt,
in der er formuliert wurde. Soll beispielsweise ein in der Programmiersprache Java
geschriebener Quellcode von einem Compiler für die Programmiersprache C++ in
Maschinencode übersetzt werden, wird dies nicht ohne weiteres gelingen.
Anhand dieses eher simplen Beispiels kann leicht der Eindruck entstehen, das sich
der Prozess der schrittweisen Verfeinerung nur über wenige Verfeinerungsstufen
(in diesem Beispiel zwei Stufen) erstreckt. Typischerweise führt eine schrittweise
Verfeinerung zu deutlich mehr als zwei Ableitungsschritten.
Die Folgende Abbildung soll noch einmal den Entstehungsprozess von Algorithmen
veranschaulichen.
Kapitel 2: Das Konzept „Algorithmus“
13
Wie aus der graphischen Darstellung zu erkennen ist, gibt es für eine Problemstellung
oftmals mehrere Algorithmen. Dieser Fakt wird an späterer Stelle ausführlich
aufgegriffen. In der juristischen Frage nach der Schützbarkeit von Algorithmen ist es
mithin von großer Bedeutung, beurteilen zu können, welche Algorithmen überhaupt
eines Schutzes bedürfen. Zumeist sind solche Algorithmen von Interesse, welche
Probleme besonders effizient oder im Vergleich zu anderen Algorithmen, welche
dieselbe Spezifikation besitzen, signifikant besser lösen können.
2.3 Reverse Engineering - vom Maschinencode zum Quellcode
Unter dem Reverse Engineering versteht man das Zurückübersetzen vom schwer
lesbaren Maschinencode in den Quellcode. Es wird realisiert durch die Technik des
Dekompilierens. Dieses Rückübersetzen ist nicht ohne einen gewissen Verlust möglich.
Überdies ist Dekompilieren nur für sehr wenige Programmiersprachen (wie z.B. Java)
auf eine sinnvolle Art und Weise möglich. In Java wird z.B. der Quellcode in den
Bytecode für eine virtuelle Maschine übersetzt. Dieser enthält noch alle relevanten
schrittweise Verfeinerung
Problem- stellung
Modell
Problem- formalisierung
informeller Algorithmus
Pseudocode/ abstrakte Datentypen
Programm/ Datenstrukturen
informeller Algorithmus
ausführbarer Maschinencode
Idee/ Anwendungs-
wissen
trickreiches, elegantes
Design der „Programm-
beschreibung“/Problem- Lösungs- Wissen
Testen
Optimierung/
Schutz des Bytecodes
Abbildung 3: Entstehungsprozess von Algorithmen
Kapitel 2: Das Konzept „Algorithmus“
14
Informationen, so dass ein Zurückübersetzen auf eine eindeutige Weise geschehen
kann. Maschinencode dagegen ist nicht eindeutig dekompilierbar, was insbesondere ein
automatisierbares Dekompilieren sehr schwierig, wenn nicht sogar unmöglich macht.
Die Notwendigkeit zum Dekompilieren von Software kann sich aus verschiedenen
Gründen ergeben, z.B. wenn der Quellcode versehentlich gelöscht worden oder verloren
gegangen ist, der Softwarehersteller sein Geschäft nicht mehr fortsetzen und somit das
Produkt nicht weiter unterstützen kann oder aber eine geänderte Anwendungssystem -
Landschaft innerhalb einer Unternehmung Analysen und Anpassungen am Quellcode
erfordern (Interoperabelitätssicherung).
Andererseits kann das Dekompilieren auch zu Spionage nach verwendeten Algorithmen
sowie in der Software abgebildeten Geschäftsgeheimnissen missbraucht werden.
Um Verstößen gegen das Gesetzt gegen unlautern Wettbewerbs (UWG) auch auf
technischer Ebene vorzubeugen und das Ausspionieren von Algorithmen und
Geschäftsgeheimnissen in Software durch Dekompilieren zu erschweren, wurden
Obfuscatoren entwickelt. Diese verfremden („verwaschen“) den Maschinencode, so
dass ein Dekompilieren nur eingeschränkt oder überhaupt nicht mehr möglich ist.
Gerade für die Programmiersprache Java wurde eine Reihe von Obfuscatoren
entwickelt, da der Java-Bytecode relativ unproblematisch dekompiliert werden kann
und ein Ausspionieren von verwendeten Algorithmen sehr leicht ist. Java-Obfuscatoren
zielen auf die Verfremdung des Bytecodes ab.
Gelingt es, einen von einem Obfuscator „verwürfelten“ Bytecode zu dekompilieren, so
ist der Quellcode in der Regel nicht mehr lesbar und weniger aufschlussreich.
Methodennamen und Variablenbezeichnungen sind verfremdet (layout obfuscation)
ebenso wie verwendete Datenstrukturen (data obfuscation). Manchmal wird sogar auch
der Kontrollfluss eines Programms geändert (control obfuscation). In diesem Falle ist
ein direktes Dekompilieren nicht möglich.
In dieser Arbeit wird beispielhaft gezeigt, wie eine Anwendung des Java-Obfuscator
JShrink auf den im Anhang A dargestellten Bytecode wirkt. JShrink arbeitet dabei auf
Bytecodeniveau. Hierbei wurde der mit JShrink verfremdete Bytecode dekompiliert.
Der resultierende Quelltext ist im Anhang B aufgeführt.
Kapitel 3: Aspekte der Schützbarkeit von Algorithmen
15
3 Aspekte der Schützbarkeit von Algorithmen
Um die Schutzbedürftigkeit von Algorithmen rechtfertigen zu können, bedarf es der
Untersuchung einiger relevanter Aspekte.
Dazu wird im Folgenden ein erster Brückenschlag zur Jurisdiktion vollzogen sowie eine
kurze Untersuchung angestellt, inwieweit eine juristische Rechtfertigung eines
Algorithmenschutzes wirtschaftsinformatorisch beurteilt werden muss. Anschließend
werden eher technische Argumente angeführt, welche eine Rechtfertigung der
Schützbarkeit von Algorithmen auf der Grundlage einer entsprechenden
Erfindungshöhe sowie Verfeinerungsstufe begründet sehen.
3.1 Urheberrecht und Patentrecht
In der Frage nach der Schützbarkeit von Algorithmen erscheinen zwei Rechtskonzepte
relevant, das Urheberrecht und das Patentrecht, welche unabhängig voneinander laufen
und jeweils unterschiedliche Personengruppen bevorteilen.
3.1.1 Algorithmen und das Patentrecht
Bislang lässt sich zumindest nach dem deutschen und dem europäische Patentrecht
keine Software oder gar Quellcodebeschreibung schützen. Schützbar sei ein Programm
immer nur im Zusammenhang mit einer bestimmt Technik.
Programme gelten nach dieser Auffassung nicht als Technik. Diese Sichtweise ist
jedoch recht veraltet. Etymologisch gesehen ergibt sich die Legitimation, Programme
und im Speziellen von Algorithmen als Technik aufzufassen, sofort. Technik bedeutet
demnach nichts anderes als Kunst, Handwerk, Kunstfertigkeit oder Verfahren zur
Lösung einer Aufgabe [Te99]. Umgangssprachlich wurde der Begriff „Technik“ bisher
immer mit Einrichtungen, welche naturwissenschaftliche Erkenntnisse praktisch nutzbar
machen, assoziiert (insbesondere mit Maschinen). Die Notwendigkeit, Technik auch als
Verfahren zu verstehen, hat sich erst in den letzten Jahrzehnten mit der wachsenden
Bedeutung der Informationsverarbeitung verstärkt herausgebildet.
Würden dennoch Softwarepatente nach dem Vorbild der USA erteilt werden können ist
einzuwenden, dass derartige nur etwas Patente nützen, wenn man sie angreifen und
verteidigen kann. Gerade kleine und mittelgroße Unternehmen können ein steigendes
Kapitel 3: Aspekte der Schützbarkeit von Algorithmen
16
Budget für ihre Rechtsabteilungen nicht finanzieren. Patente, einhergehend mit der
Beobachtung der Konkurrenz und dem Ergreifen repressiver als auch präventiver
juristischer Reaktionen sind sehr teuer. Daher sind große Firmen mit ausreichend
finanziellen Mitteln unverhältnismäßig bevorteilt. Sie können ihren
Wettbewerbsvorsprung bis hin zum Monopol ausbauen, Lizenzbedingungen unterliegen
dann mittelfristig keiner Marktregulierung mehr. Hinzu kommt, dass die Chance
jemanden zu verklagen in den USA schon jetzt wesentlich kleiner ist, als selbst
verklagt zu werden. Einige sprechen vom so genannten „Minenfeld der (Software-)
Patente“.
Dieses Phänomen trägt kuriose Früchte. In einem Wettbewerb der Open-Source–
Gemeinde sollte das Programm gewinnen, welches die meisten Patente verletzt. Sieger
war der Entwickler eines Fortschrittbalkens. Zehn Zeilen Code verstießen gegen 18
Patente.
3.1.2 Äquivalenz von Programmen und Schriftwerken
Das Urheberrecht schützt im Gegensatz zum Patentrecht nur das Programm oder die
Software als ganzes. Weder die Idee, noch wesentliche Programmfragmente zu deren
Umsetzung sind über das Urheberrecht als Einzelaspekte schützbar. Die Schützbarkeit
eines Programms über das Urheberrecht stützt sich auf die Prämisse, dass Programme
mit Schriftwerken vergleichbar sind.
Einige Juristen merken in der Frage nach der Äquivalenz von Computerprogrammen zu
Schriftwerken kritisch an, dass Programme im Gegensatz zu literarischen Werken für
Maschinen geschrieben seien und daher von vornherein nicht mit Schriftwerken
vergleichbar sind und somit insbesondere das Urheberrecht in der Sache der
Schützbarkeit von Programmen nicht einschlägig sei. Diese Sichtweise ist aber nur dann
nachvollziehbar, wenn ein Programm bereits auf dem untersten Abstraktionsniveau
spezifiziert wurde (Maschienencode).
Tatsächlich ist die Auffassung, Programme seien für Maschinen geschrieben, nicht
korrekt. Programme sind sehr wohl für Menschen geschrieben. Sie dienen im
Entwicklungsprozess als Diskussionsgrundlage zur Klärung von Implementierungs-
fragen und sie kommunizieren die dem Programm zugrunde liegende Idee zu anderen
Projektmitarbeitern, die räumlich getrennt voneinander arbeiten. Programme nehmen so
auch Koordinationsaufgaben war. Programme enthalten wie literarische Werke auch
Kapitel 3: Aspekte der Schützbarkeit von Algorithmen
17
Wissen. Überdies stellen sie Information dar, sobald sie das Wissen von anderen
(Projektmitarbeitern) erweitern.
Wissen und Information sind menschliche Phänomene, die einer Maschine nicht
zugänglich sind! Maschinen arbeiten mit Daten. Erst wenn einer konkreten
Datenverarbeitung der Mensch mit seiner Fähigkeit zur Interpretation und ein
Bezugsrahmen (Anwendungskontext) hinzugefügt wird, stellen die Ergebnisse der
Datenverarbeitung Informationen dar, aus denen dann Wissen generiert wird.
Programme und mit ihnen Algorithmen werden für einen konkreten
Anwendungskontext entworfen. Vorraussetzung hierbei ist die menschliche Intention,
ein Problem sinnvoll lösen zu wollen (sinnvoll setzt Interpretation voraus -> nicht
irgendwie) sowie die Sicherstellung der Verwertbarkeit der Ergebnisse (Interpretation
erneut Vorraussetzung für Beurteilung der Verwertbarkeit).
Insofern sind Programme, ebenso wie Schriftwerke, für Menschen geschrieben und
nicht nur für Maschinen! Ebenso ist die Einordnung als Sprachwerk gemäß den weiter
oben aufgeführten Erläuterungen auf allen Abstraktionsstufen einer algorithmischen
Beschreibung insbesondere auf den unteren Ebenen offensichtlich gerechtfertigt (siehe
Umgangs-, Programmier-, Maschinensprache).
Dieser Auffassung folgend, propagieren nun einige Juristen: „Der Unterschied von
Computerprogrammen und Schriftwerken ist nicht allzu groß!“. Allerdings wird hierbei
nicht differenziert genug argumentiert. Das Medium Buch als Informationsträger besitzt
andere Eigenschaften und Einschränkungen als das Medium Hardware, für das
Programme entworfen werden. So besitzt ein Computer im Gegensatz zu einem Buch
„mehrdimensionalen Ressourcenbeschränkungen“, welche die Möglichkeiten der
Informationsrepräsentation einschränken (beim Buch wirkt evtl. nur die maximale
Anzahl an Seiten einschränkend). Bei einem Buch verläuft eine Formulierung
problemlos, sie läuft „auf Anhieb“. Dies ist unter anderem dadurch begründet, dass ein
Buch durchgängig nur eine Abstraktion zur Informationsdarstellung besitzt, nämlich die
der natürlichen Sprache.
Computerhardware erfordert ungleich mehr Aufwand zum „Verfassen“ eines
Quelltextes. Speicherbeschränkungen, maschinenabhängige Beschränkungen von
Repräsentationsmöglichkeiten (z.B. nur ganze Zahlen darstellbar, keine Fliesskomma-
Arithmetik), effiziente Formulierung des Programms (abhängig von unterliegender
Hardware) seien nur beispielhaft erwähnt. All diese Beschränkungen treten
Kapitel 3: Aspekte der Schützbarkeit von Algorithmen
18
typischerweise gleichzeitig auf und müssen somit simultan bei der Programmschöpfung
berücksichtigt werden. Dieser Aspekt wird in der Diskussion über die Auswirkung der
Verfeinerungsstufe eines Algorithmus auf deren Schutzbedürftigkeit aufgegriffen.
Demgegenüber ist allen Sprachwerken insbesondere auch den Computerprogrammen
eines gemein: Die eigenschöpferische Leistung ist Voraussetzung für den Anspruch auf
Schutz und die Schätzung des Werkes. Der ideelle Wert von Informationsgehalt und
induziertem Wissen ist besonders betonenswert.
3.2 Einfluss der Erfindungshöhe auf die Schutzbedürftigkeit
In den USA herrscht ein Trend zum Schutz schon ab einer geringen Erfindungshöhe,
begründet durch die generelle Möglichkeit der Patentierbarkeit von
Computerprogrammen, Software oder Geschäftsideen. Diese Praxis impliziert ein
schwerwiegendes Problem: Die Ressource „Basistechnologie/ grundlegende
Algorithmen“ wird knapp. Das Handwerkzeug eines jeden Programmierers würde der
Allgemeinheit über kurz oder lang entrissen. Der prinzipielle Sinn von Programmierung
an sich, nämlich der Realisierung einer maschinellen Ausführung von Algorithmen,
wäre in Frage gestellt. Dies wäre ungefähr so, als patentierte jemand nach und nach die
arithmetische Operatoren +, -, *, /. Jedwedes Rechnen würde dadurch unmittelbar eine
etwaige Rechtsverletzung nach sich ziehen, Rechnen wäre quasi nicht mehr ohne
weiteres möglich, schon gar nicht für jedermann.
In diesem Sinne könnte man jedes Programmstück als Algorithmus ansehen. Diese
Betrachtung impliziert eine geringe Erfindungshöhe.
Daher erscheint es sinnvoll, lediglich überdurchschnittliche Algorithmen schützen zu
lassen. Dies bezieht sich auf den Algorithmen im engeren Sinne, welche sich durch
komplexe Kombinationen von Kontroll- und Datenstrukturen auszeichnen. An dieser
Stelle sei kurz angemerkt, dass Programme demnach auch ohne Algorithmen im
engeren Sinne existieren. Die Überdurchschnittlichkeit von Algorithmen im engeren
Sinne schlägt sich in deren Erfindungshöhe nieder. Die Erfindungshöhe ließe sich
beispielsweise durch die investierte Forschungszeit, den Innovationsbeitrag, die
konzeptionelle Eleganz und vor allem durch die daraus resultierende Effizienz eines
Verfahrens explizieren. Die Güte und die Qualität eines Algorithmus korreliert positiv
mit der Erfindungshöhe eines Algorithmus. Effiziente Algorithmen fallen nicht vom
Himmel, insbesondere ist die Menge der fähigen Algorithmen – Ingenieure
Kapitel 3: Aspekte der Schützbarkeit von Algorithmen
19
vergleichsweise gering. So würde ein durch eine überdurchschnittliche Erfindungshöhe
gerechtfertigter Schutz auch die materiellen Aufwendungen sowie die Personellen
Leistungen der Algorithmenerstellung würdigen.
“Algorithms are a sharp knife - it does exactly what it is supposed to do with a
minimum amount of applied effort. Using the wrong algorithm to solve a problem is like
trying to cut a steak with a screwdriver: you may eventually get a digestible result, but
you will expend considerably more effort than necessary, and the result is unlikely to be
aesthetically pleasing” [Co90, S. 16]
So ließe sich das Sortierproblem mit dem so genannten Quicksort-Algorithmus deutlich
schneller (effizienter) Lösen. Die Idee hinter dem Quicksort ist nicht trivial aber
hochgradig elegant und beruht auf einem Prinzip, das schon den Römern geläufig war:
„Divide and Conquer“. Dieser Algorithmus ist im Anhang C dargestellt.
Beispielhaft seien an dieser Stelle auch die Algorithmen für das MP3- und das GIF-
Format erwähnt. Insbesondere dem MP3-Format liegt eine lange Entwicklungszeit
zugrunde. Das Ziel, multimediale Daten (audio, visuell) hochgradig kompakt
abzuspeichern, also Platz zu sparen in diesem Sinne, hat im Ergebnis die multimediale
Welt revolutioniert. Auf einmal war es möglich, mobile Datenträger mit äußerst
beschränktem Speichervorrat (MP3-Player) wirtschaftlich zu vermarkten oder gar MP3-
Dateien relativ effizient via Internet auszutauschen. Daher ist das MP3-Format
konzeptionell hochgradig nicht trivial und sehr kompliziert. Allein schon die
Schwierigkeit, Daten stark zu komprimieren und dabei die Qualität des Originals
beizubehalten und Audio- sowie Videodaten gleichzeitig zu berücksichtigen, bringt
dieses Format an die Grenze des machbaren. Ähnlich verhält es sich mit dem GIF-
Format, welches allerdings nur die Komprimierung von Bilddaten einschließt und im
Bereich des Webdesigns noch weit verbreitet ist.
Das Problem, was sich hier ergibt, ist das Spannungsfeld, welches durch die
Erfindungshöhe und den damit verbundenen persönlichen und wirtschaftlichen
Interessen induziert wird. Algorithmen mit einer niedrigen Erfindungsleistung sollten
allgemeines Gedankengut bleiben, demgegenüber ist großer Erfindergeist schon aus
moralischen und ethischen Gesichtspunkten in gebührendem Maße zu schätzen und
anzuerkennen, ohne dabei jedoch die Gefahr entstehen zu lassen, durch einen Schutz die
Interessen der Allgemeinheit zu vernachlässigen.
Kapitel 3: Aspekte der Schützbarkeit von Algorithmen
20
Eine weitere große Schwierigkeit ergibt sich in der Quantifizierung einer
Erfindungshöhe. Ab wann liegt eine triviale Erfindungshöhe vor, ab wann eine
überdurchschnittliche? Was gehört zum Rüstzeug eines jeden Programmierers?
3.3 Abhängigkeit der Schutzbedürftigkeit von der
Verfeinerungsstufe
Aus Abbildung 3 ist erkennbar, dass Ideenreichtum nicht nur bei der Konzeption eines
Algorithmus erforderlich ist, sondern zusätzliche auch bei der Implementierung
(Erstellen des Programms). Hierbei spielen insbesondere auf der Quellcode-Ebene die
Konzeption von abstrakten Datentypen (ADT’s) und eine geeignete Wahl und Nutzung
von Datenstrukturen sowie abstrakten Befehlen eine große Rolle. Besonders wichtig ist
dann die Überprüfung der Gesamtkonzeption mit anschließender Fehlerbeseitigung
auch konzeptioneller Fehler. Dies wird als Testen bezeichnet. Je näher die Abstraktion
an einer konkreten Maschine ist und je umfangreicher die algorithmische Beschreibung,
desto langwieriger und aufwendiger gestaltet sich das Testen und desto wichtiger wird
es.
Somit nimmt der „Wert“ des zusätzlichen Ideenreichtums mit abnehmendem
Abstraktionsniveau der algorithmischen Beschreibung zu, ebenso sind gerade auf den
unteren Abstraktionslevels die spezifischen Fähigkeiten eines Programmierers sehr
stark gefragt (-> Eleganz der Implementierung, „Spagetti-Code“ versus
Wiederverwendbarkeit). Ein guter Algorithmus kann durchaus schlecht implementiert
sein, sogar soweit, dass er die vorgegebene Spezifikation nicht mehr erfüllt (überprüfen
durch Testen!). Dieser Implementierungsaufwand muss honoriert werden in Form von
Schutz oder materieller Entlohnung. Bloße Anerkennung ist hierbei nicht ausreichend,
wird doch sehr viel Arbeitszeit und –kraft in den Implementierungsprozess investiert.
Hier bezieht sich die Schutzbedürftigkeit also auf die Implementierung oder Umsetzung
eines Algorithmus. Eine besondere Schützbedürftigkeit in diesem Sinne bestünde
demnach, wenn die Implementierung außerordentlich elegant und unter effizienter
Ausnutzung der zu Verfügung stehenden Systemressourcen erfolgt ist.
Vielfach ist es auch sinnvoll, eine algorithmische Idee als solche zu schützen, ohne dass
diese schon in einer Programmiersprache implementiert ist. Die Existenz eines
Algorithmus ist unabhängig von dessen Darstellungsform. Sie kann sich in
Kapitel 3: Aspekte der Schützbarkeit von Algorithmen
21
mechanischen Vorrichtungen, Schaltkreisen, Quellcodes oder auch in Pseudocodes
manifestieren.
3.4 Open – Source
Die „Open-Source-Gemeinde“, welche gemeinsam Programme (und damit auch
Algorithmen) entwickelt und diese offen jedermann zur Verfügung stellt, sieht sich
durch Softwarepatente existenziell bedroht. Die Gemeinde befürchtet, speziell durch
Patente in ihrem gestalterischem Potenzial beschnitten zu werden, da ein Schutz gerade
auch bestimmter Algorithmen (siehe Rüstzeug für Programmierer) die Entwicklung von
Programmen für spezifische Anwendungsgebiete (siehe z.B. Text-, Grafikverarbeitung,
Programme mit MP3-Unterstützung) verhindern würde. Die Aufnahme von durch ein
Patent geschützten Programmteile in den eigenen Quellcode verbietet sich schon durch
die Open-Source-Lizenzen, nach denen es jedem Anwender offen steht, den Quellcode
zu kopieren und zu modifizieren, ohne dass dabei Gebühren anfallen.
Auch die Möglichkeit, selbst Softwarepatente anzumelden, entfällt, da die Open-
Source-Gemeinschaft keine gewerbliche Organisation darstellt und somit ein
wesentliches Kriterium für die Patentrechtserteilung nicht erfüllt wird.
Unternehmen mit eigenen Patenten haben zudem mit Open-Source ein besonders
leichtes Spiel, lässt sich doch der quelloffene Code problemlos auf etwaige
Patentrechtsverletzungen überprüfen. Somit wird zugleich das Dekompilierungsverbot
des Urheberrechts umgangen, weil gar nicht erst dekompiliert werden muss.
Open-Source-Software scheint zu Softwarepatenten schlicht inkompatibel zu sein. Das
ist vor allem aber mit der generellen Gegensätzlichkeit von Offenheit zu
Schutzansprüchen zu begründen.
Allerdings zeigt Open-Source (Offener Quellcode) auch eine Möglichkeit auf, wie sich
Softwarepatente aushebeln lassen. Freier Code ist schädlich für ein späteres Patent. Was
es schon gibt, kann nicht patentiert werden, da jeder Anmeldung eine erfinderische
Höhe (Innovation) zugrunde liegen muss. Allerdings impliziert dies jedoch nicht, dass
die Open-Source-Gemeinschaft Algorithmen als solche schützen lassen kann. Streitbar
ist zudem erneut, wie eine erfinderische Höhe bei Software quantifiziert werden kann.
Kapitel 4: Fazit
22
4 Fazit
Möchte man die Frage nach der Schützbarkeit von Algorithmen aus dem juristischen
Blickwinkel heraus untersuchen, lassen sich vorweg schon ein paar Mängel
grundsätzlicher Natur aufzeigen.
So geht z.B. das Patentrecht von einem veralteten Technik-Begriff aus, was bezüglich
der Schützbarkeit von Programmen und Algorithmen im Speziellen von Nachteil ist.
Bezüglich des Urheberrechts lässt sich feststellen, dass eine gewisse Äquivalenz von
Programmen und Schriftwerken gegeben ist. Programme sind wie Schriftwerke auch für
Menschen geschrieben, jedoch existieren auch deutliche Unterschiede hinsichtlich
zusätzlicher Beschränkungen bei der Formulierung von Programmen, welche momentan
in der Rechtssprechung unberücksichtigt bleiben. Darüber hinaus sind Algorithmen
nach deutschem und europäischem Recht weder durch das Urheberrecht schützbar, noch
patentierbar.
Ob ein Algorithmus überhaupt zu schützen ist, sollte eng mit dessen Erfindungshöhe
zusammenhängen. Hierbei ist eine zeit- und kostenintensive Erfindungsleistung, zu der
auch die knappe Ressource Humankapital beigetragen hat, gegenüber trivialen und eher
einfachen Erfindungen zu würdigen. Nicht nur ehrgeiziger Erfindergeist sondern auch
wirtschaftliche Interessen beeinflussen die Erfindungshöhe positiv. Somit wäre ein
Schutz auch aus diesem Blickwinkel heraus für hoch entwickelte Algorithmen
angebracht, um so auch wirtschaftlichen Interessen gerecht zu werden. Zu klären ist bei
dieser Argumentation jedoch, ab welcher Erfindungshöhe eine Schutzbedürftigkeit
gerechtfertigt wäre.
Überdies stellt auch die Verfeinerungsstufe eines Algorithmus ein zentrales Kriterium
zur Bewertung der Schutzbedürftigkeit dar. Die Implementierung eines komplexen
Algorithmus in Form eines Programms ist nicht trivial. Das Problemlösungswissen
eines Programmierers bezüglich einer geschickten und eleganten Implementierung eines
Algorithmus steckt in der Programmformulierung. Je niedriger die Abstraktionsstufe
der algorithmischen Beschreibung, desto „wertvoller“ wird jede Codezeile eines
Programms (Programmformulierung ist zeit- und testintensiv). Vielfach sind schon
Beschreibungen auf relativ hohem Abstraktionsniveau wertvoll (als Ergebnis intensiver
Forschung), so dass es wünschenswert erscheint, einen Algorithmus schon ab einem
hohen Abstraktionsgrad (Algorithmusskizze, Pseudocode) schützen zu können.
Anhang A: Bytecode des Beispiels „Insertion Sort“
23
A Bytecode des Beispiels „Insertion Sort“
Compiled from InsertionSort.javapublic class InsertionSort extends java.lang.Object {
public InsertionSort();public static void main(java.lang.String[]);public static void insertionSort(int[]);static {};
}
Method InsertionSort()0 aload_01 invokespecial #1 <Method java.lang.Object()>4 return
Method void main(java.lang.String[])0 getstatic #2 <Field int array[]>3 invokestatic #3 <Method void insertionSort(int[])>6 getstatic #4 <Field java.io.PrintStream out>9 ldc #5 <String "Ergebnis: ">11 invokevirtual #6 <Method void print(java.lang.String)>14 iconst_015 istore_116 goto 5119 getstatic #4 <Field java.io.PrintStream out>22 new #7 <Class java.lang.StringBuffer>25 dup26 invokespecial #8 <Method java.lang.StringBuffer()>29 getstatic #2 <Field int array[]>32 iload_133 iaload34 invokevirtual #9 <Method java.lang.StringBuffer
append(int)>37 ldc #10 <String " ">39 invokevirtual #11 <Method java.lang.StringBuffer
append(java.lang.String)>42 invokevirtual #12 <Method java.lang.String toString()>45 invokevirtual #6 <Method void print(java.lang.String)>48 iinc 1 151 iload_152 getstatic #2 <Field int array[]>55 arraylength56 if_icmplt 1959 return
Method void insertionSort(int[])0 iconst_11 istore_12 goto 485 aload_06 iload_17 iaload8 istore_29 iload_110 iconst_1
Anhang A: Bytecode des Beispiels „Insertion Sort“
24
11 isub12 istore_313 goto 2816 aload_017 iload_318 iconst_119 iadd20 aload_021 iload_322 iaload23 iastore24 iload_325 iconst_126 isub27 istore_328 iload_329 iflt 3932 iload_233 aload_034 iload_335 iaload36 if_icmplt 1639 aload_040 iload_341 iconst_142 iadd43 iload_244 iastore45 iinc 1 148 iload_149 aload_050 arraylength51 if_icmplt 554 return
Method static {}0 bipush 62 newarray int4 dup5 iconst_06 bipush 138 iastore9 dup10 iconst_111 iconst_412 iastore13 dup14 iconst_215 iconst_516 iastore17 dup18 iconst_319 iconst_220 iastore21 dup22 iconst_423 bipush 625 iastore26 dup27 iconst_528 iconst_129 iastore30 putstatic #2 <Field int array[]>33 return
Anhang B: Ergebnis der Anwendung eines Java Obfuscators
25
B Ergebnis der Anwendung eines Java Obfuscators –
„Insertion Sort“
import I.I;import java.io.PrintStream;
public class InsertionSort {
private static int append[] = {13, 4, 5, 2, 6, 1};
public InsertionSort() {}
public static final void main(String args[]) {append(append);System.out.print(I.I(1));for(int i = 0; i < append.length; i++)
System.out.print(append[i] + I.I(12));}
public static final void append(int ai[]) {for(int i = 1; i < ai.length; i++) {
int j = ai[i];int k;for(k = i - 1; k >= 0 && j < ai[k]; k--)
ai[k + 1] = ai[k];
ai[k + 1] = j;}
}}
package I;
import java.io.InputStream;
public class I {
static byte getClass[] = null;static String getResourceAsStream[] = new String[256];static int intern[] = new int[256];
public I() {}
public static final synchronized String I(int i) {int j = i & 0xff;if(intern[j] != i) {
intern[j] = i;if(i < 0)
i &= 0xffff;getResourceAsStream[j] = (new String(getClass, 0, i,
getClass[i - 1] & 0xff)).intern();}return getResourceAsStream[j];
Anhang B: Ergebnis der Anwendung eines Java Obfuscators
26
}
static {try {
InputStream inputstream = (newI()).getClass().getResourceAsStream("" + 'I' + '.' + 'g' + 'i' +'f');
if(inputstream != null) {int i = inputstream.read() << 16 |
inputstream.read() << 8 | inputstream.read();getClass = new byte[i];int j = 0;byte byte0 = (byte)i;byte abyte0[] = getClass;while(i != 0) {
int k = inputstream.read(abyte0, j, i);if(k == -1)
break;i -= k;for(k += j; j < k; j++)
abyte0[j] ^= byte0;
}
inputstream.close();}
}catch(Exception exception) { }
}}
Vergleicht man die Quelltextdarstellungen des „Insertion Sort“ aus Kapitel 2.2 mit
denen aus Anhang B, so fällt auf, dass Methoden- und Variablennamen verändert,
Strings (textuelle Beschreibungen -> siehe System.out.println()) zusätzlich codiert und
sogar Schleifentypen ausgetauscht wurden (while-Schleife versus for-Schleife). Es wird
deutlich, dass der Quelltext aus Anhang B deutlich schwerer lesbar und somit weniger
verständlich als der originale Quellcode ist.
Hierbei sei noch angemerkt, dass sich der Nutzen eines Obfuscators in diesem Beispiel
in Grenzen hält, da der Quelltext für den „Insertion Sort“ eher klein ist und der
verwendete Algorithmus nach wie vor gut erkennbar ist. Für große
Quelltextbeschreibungen ist jedoch ein Obfuscator durchaus angebracht.
Algorithmische Beschreibungen in einem Programm erstrecken sich vielfach über
mehrere 100 Zeilen Quelltext. Wird ein solcher Quellcode verfremdet, sind darin
beschrieben Algorithmen im Anschluss nur sehr schwer nachvollziehbar.
Literaturverzeichnis
27
C Quicksort – Algorithmus
void quicksort(int[] a, int L, int R) {
int m = a[(L+R) / 2];
int i = L;int j = R;
while(i <= j) {
while(a[i] < m) {i = i + 1;
}
while(m < a[j]) {j = j - 1;
}
if (i <= j) {swap(a, i, j);i = i + 1;j = j - 1;
}}if (L < j) quicksort(a, L, j);if (i < R) quicksort(a, i, R);
}
void swap(int[] a, int i, int j) {int tmp = a[i];a[i] = a[j];a[j] = tmp;
}
Literaturverzeichnis
28
Literaturverzeichnis
[Ah87] Alfred V. Aho, John E. Hopcroft, Jefrey D. Ullman: Data structures and algorithms, Addison-Wesley, 1987.
[Co90] Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest: Introduction to Algorithms, The MIT Press, 1990.
[He92] Dietmar Hermann: Algorithmen Arbeitsbuch, Addison-Wesley, 1992.
[Kn73] Donald E. Knuth: The Art of Computer Programming, 2nd. ed., Addison-Wesley, 1973.
[Te99] Rolf A. Teubner: Vorlesungsskript Wirtschaftsinformatik I, Wintersemester 1999/2000
[Wa89] Martin Warnke: Informatik, R. Oldenbourg Verlag, 1989.
[Wi97] Guido Wirtz: Vorlesungsskript Informatik I, Wintersemester 1997/98