Seite 1 von 3

XOR-Verschlüsselung

Verfasst: Dienstag 18. April 2006, 00:26
von Zilchinger
Ich sag erstmal Hallo und melde mich als neuer User ins Forum 8) ...hehe

Ich bin ziemlich neu in der Sprache Python und lerne jeden Tag unmengen dazu. Ich programmiere zur Zeit an einem größeren Projekt, worin auch eine XOR-Verschlüsselung benötigt wird.

Das ist auch mein Problem:
Prinzipiell habe ich da was gebaut, was auch wunderbar funktioniert. Solange die Streams, die Verschlüsselt werden sollen relativ klein sind.
Will ich jedoch eine Datei verschlüsseln, die > 1 mb ist, dann kann ich nicht nur ne Kanne Kaffetrinken gehen.

Hier mal der Quelltext:

Code: Alles auswählen

import StringIO
import operator

class XORCrypter:
    
    __password = None
    
    def __init__(self, password):
        self.__password = password;
        
    def cryptXOR(self, input):
        sr = StringIO.StringIO(input)
        sw = StringIO.StringIO(input)
        kIdx = 0
        for x in range(len(input)):
            sr.seek(x)
            sw.seek(x)
            sw.write(chr( ord(sr.read(1)) ^ ord(self.__password[kIdx])))
            kIdx = (kIdx + 1) % len(self.__password) 
        sw.seek(0);
        result = sw.read();
        sr.close()
        sw.close()
        return result
Gibt es da nicht irgendwie eine performantere Methode?

Würde mich freuen, wenn mir jemand helfen, oder Anregungen geben könnte!

Bis dann,
Zilchinger

Re: XOR-Verschlüsselung

Verfasst: Dienstag 18. April 2006, 06:54
von gerold
Zilchinger hat geschrieben:Ich sag erstmal Hallo
[...]
Ich programmiere zur Zeit an einem größeren Projekt, worin auch eine XOR-Verschlüsselung benötigt wird.
Hi Zilchinger!

Willkommen hier im Board. :D
Hier ein Link, der dir vielleicht weiter hilft: http://www.amk.ca/python/code/crypto.html

mfg
Gerold
:-)

Verfasst: Dienstag 18. April 2006, 08:22
von modelnine
Ich bin mir momentan alles andere als sicher ob PyCrypto eine XOR-Verschlüsselung definiert (in C), aber auf jeden Fall kann man die relativ einfach selbst bauen (wie immer):

xorc.c

Code: Alles auswählen

/* XOR Crypto for Python, in C.
   Copyright (C) 2006, Heiko Wundram.
   Use freely, but without any warranty from the author... :-) */

#include <stdlib.h>
#include <Python.h>

typedef struct {
  char *pwd;
  int pwdlen;
  int pwdpos;
} xorstate;

void xorfree(xorstate *state)
{
  free(state->pwd);
  free(state);
}

PyObject *xorsetup(PyObject *self, PyObject *args)
{
  char *pwd;
  int pwdlen;
  xorstate *state;
  PyObject *pystate;

  if( !PyArg_ParseTuple(args,"s#",&pwd,&pwdlen) )
    return NULL;

  if( !( state = (xorstate*)malloc(sizeof(xorstate)) ) ) {
    PyErr_SetString(PyExc_MemoryError,"Couldn't allocate XOR buffer.");
    return NULL;
  }
  if( !( state->pwd = (char*)malloc(pwdlen) ) ) {
    free(state);
    PyErr_SetString(PyExc_MemoryError,"Couldn't allocate string buffer.");
    return NULL;
  }
  memcpy(state->pwd,pwd,pwdlen);
  state->pwdlen = pwdlen;
  state->pwdpos = 0;
  if( !( pystate = PyCObject_FromVoidPtr(state,xorfree) ) ) {
    free(state->pwd);
    free(state);
    PyErr_SetString(PyExc_MemoryError,"Couldn't allocate PyCObject.");
    return NULL;
  }

  return pystate;
}

PyObject *xor(PyObject *self, PyObject *args)
{
  char *data, *xordata;
  int datalen, curpos;
  PyObject *pystate, *pydata;
  xorstate *state;

  if( !( PyArg_ParseTuple(args,"Os#",&pystate,&data,&datalen) ) )
    return NULL;

  if( !PyCObject_Check(pystate) ) {
    PyErr_SetString(PyExc_ValueError,"First parameter must be a state.");
    return NULL;
  }
  state = PyCObject_AsVoidPtr(pystate);
  if( !( xordata = (char*)malloc(datalen) ) ) {
    PyErr_SetString(PyExc_MemoryError,"Couldn't allocate xor array.");
    return NULL;
  }
  memcpy(xordata,data,datalen);
  for( curpos = 0; curpos < datalen; curpos++ )
    xordata[curpos] = data[curpos] ^ state->pwd[(curpos+state->pwdpos)%
						state->pwdlen];
  state->pwdpos = (curpos+state->pwdpos) % state->pwdlen;
  pydata = PyString_FromStringAndSize(xordata,datalen);
  free(xordata);

  return pydata;
}

static PyMethodDef XorCMethods[] = {
  {"setup",xorsetup,METH_VARARGS,
   "Sets up a structure which keeps track of the encryptions state."},
  {"xor",xor,METH_VARARGS,
   "XORs the passed buffer with a specified "},
  {NULL, NULL, 0, NULL}
};

PyMODINIT_FUNC initxorc()
{
  Py_InitModule("xorc",XorCMethods);
}
Und der entsprechende setup.py-File:

setup.py

Code: Alles auswählen

# -*- coding: iso-8859-15 -*-

from distutils.core import setup, Extension

xorc = Extension('xorc',sources=['xorc.c'])

setup(name='xorc',version='0.1',
      description='Encrypts a string using a simple XOR crypt.',
      ext_modules=[xorc])
Das ganze ist folgendermaßen zu benutzen:

Code: Alles auswählen

modelnine@phoenix ~/xorc/build/lib.linux-x86_64-2.4 $ python
Python 2.4.2 (#1, Apr  3 2006, 12:10:45)
[GCC 3.4.6 (Gentoo 3.4.6, ssp-3.4.5-1.0, pie-8.7.9)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import xorc
>>> state = xorc.setup("mein geheimes kennwort")
>>> xorc.xor(state,"Ich will diesen Text verschlüsseln; wer kann mir sagen was rauskommt?")
'$\x06\x01NW\x0e\t\x04E\r\x04\x00\x00E\x05E:\x0b\x0f\x1bR\x02\x08\x17\x1a\rH\x0b\x99\x1b\x16\x0c\x01\x0bH\x00\x1c\x00\x1cN\x1c\x0e\x1c\x1aM\x08\x00\x1c\x00\x14\x04\x0f\x00\x07M\x12\x12SK\x17\x0f\x1b\x04\x04\x1d\x19\x00\x11V'
>>> decstate = xorc.setup("mein geheimes kennwort")
>>> xorc.xor(decstate,'$\x06\x01NW\x0e\t\x04E\r\x04\x00\x00E\x05E:\x0b\x0f\x1bR\x02\x08\x17\x1a\rH\x0b\x99\x1b\x16\x0c\x01\x0bH\x00\x1c\x00\x1cN\x1c\x0e\x1c\x1aM\x08\x00\x1c\x00\x14\x04\x0f\x00\x07M\x12\x12SK\x17\x0f\x1b\x04\x04\x1d\x19\x00\x11V')
'Ich will diesen Text verschl\xfcsseln; wer kann mir sagen was rauskommt?'
>>>
modelnine@phoenix ~/xorc/build/lib.linux-x86_64-2.4 $
Ich hab einen kurzen Test gemacht der den Durchsatz auf meinem Rechner auf knapp 29MB/s misst (natürlich mit der Quelldatei im Plattencache...).

Viel Spaß damit!

EDIT by mawe: hab den C-Code eingefärbt

Verfasst: Dienstag 18. April 2006, 08:37
von gerold
modelnine hat geschrieben:Ich bin mir momentan alles andere als sicher ob PyCrypto eine XOR-Verschlüsselung definiert (in C)
Hi modelnine!

Ich habe PyCrypto noch nicht ausprobiert. Ich kenne nur die Beispiele aus dem Internet. Die Beschreibung auf der Homepage "Stream encryption algorithms: ARC4, simple XOR" hat mich dazu verleitet, den Link hier zu erwähnen.

lg
Gerold
:-)

Verfasst: Dienstag 18. April 2006, 18:58
von modelnine
Humm... Ich hab gerade auch noch mal geguckt, und tatsächlich, es scheint dass PyCrypto mittlerweilen eine XOR-Verschlüsselung bekommen hat. Als ich vor ewigen Zeiten mal einen Wrapper für PyCrypto geschrieben hab (um es einfacher benutzbar zu machen, yawPyCrypto um genau zu sein) hatte es noch kein C-Modul dafür, und als ich heute morgen auf die Seite geguckt hab, hab ich beim skimmen auch keine Referenz auf XOR gefunden. Okay. Vielleicht kann's ja jemand trotzdem gebrauchen. ;-)

Verfasst: Mittwoch 19. April 2006, 11:25
von Zilchinger
Danke für den großen Aufwand.
Ich werde mich da mal reinfuchsen.

Bis die Tage,
Zilchinger

Verfasst: Mittwoch 19. April 2006, 20:41
von murph
Ich habe ein paar Fragen:
Macht es Sinn, das XORC-Ergebnis noch eimal zu verschlüsseln (noch einmal XORC oder 128bit?)
Wo muss der Skript liegen, um ausgeführt werden zu können?
Noch ein Fehler:
/var/mail/distutils.core
ist bei mir nicht vorhanden...der ganze Order /var/mail ist leer, deshalb eine korrekte fehlermeldung^^ Wie kann ich das nachbessern?

Verfasst: Mittwoch 19. April 2006, 21:27
von Leonidas
murph hat geschrieben:Wo muss der Skript liegen, um ausgeführt werden zu können?
Egal wo. Wenn du es mit python <pafd_zum_stript> aufrufst, ist das vollkommen egal. Wenn du unter Linux arbeitest, ist es praktisch noch das Skript mit chmod a+x skript.py ausführbar zu machen, man kann es dann auch mit ./skript.py ausführen.

Verfasst: Donnerstag 20. April 2006, 04:59
von murph
Wenn er sich nun selbst

Code: Alles auswählen

#include <stdlib.h>
#include <Python.h>
holt, dann nur noch der Fehler mit dem leeren Ordner (ich kann bei der Installation nichts falsch geamcht ahben, das war von Ubuntu(Linux) vorinstalliert. Aber da werde ich mcih dann an das entsprechende Forum bei Ubuntu wenden.

Verfasst: Donnerstag 20. April 2006, 07:09
von modelnine
Noch mal kurz was zur Verschlüsselungs_sicherheit_ dieses Algorithmus: nicht existent.

1) Es macht keinen Sinn das Ergebnis einer XOR-Verschlüsselung noch mal mittels des selben Algorithmus zu Verschlüsseln, die Brechbarkeit des Algorithmus erschwert sich dadurch kein bisschen (es ist einfach so als ob man anstelle des ursprünglichen Schlüssels einen anderen, lcm(len(schlüssel1),len(schlüssel2))-langen Schlüssel der sich aus den beiden Schlüsseln mittels XOR-Verschlüsselung ergibt, benutzt hätte), wobei sogar wenn man zwei Schlüssel benutzt die Entschlüsselungsreihenfolge egal ist, also:

d(schlüssel2,d(schlüssel1,c)) = d(schlüssel1,d(schlüssel2,c))

wobei d die Entschlüsselungsfunktion (die bei XOR == e ist) und c der Cyphertext (also das Chiffrat).

Kleiner Zusatz: die "Verschlüsselungssicherheit" erhöht sich natürlich, wenn len(schlüssel1) und len(schlüssel2) ungleiche Primzahlen sind (bzw. nur ggT der beiden == 1 ist, bei Primzahlen ist er das aber immer), da dann die effektive Schlüssellänge len(schlüssel1)*len(schlüssel2) ist. Sobald man aber zwei gleichlange Schlüssel benutzt (was ja der Normalfall ist) hat man gar keinen Gewinn, darauf wollte ich hinaus. Was aber nicht bedeutet, dass es noch einen anderen Angriff gibt, der die effektive Schlüssellänge bei solcherart synthetisierten Schlüsseln reduziert, schließlich IANAC (I am not a cryptographer).

2) Die Sicherheit der XOR-Verschlüsselung ist trivial. Durch ein bisschen Zeichenhäufigkeitssuche kann man bei einem mittellangen Text die Verschlüsselung maschinell einfachst brechen, und zwar indem man den Text suksessive in Zeilen aufteilt (einer fixen Länge, genau wie der Schlüssel), und dann einfach in einer Spalte die Zeichenhäufigkeit vergleicht mit Werten die man für eine entsprechende natürliche Sprache kennt. Auch wenn das ganze ein bisschen Zeit braucht, so ist diese Zeit auf einem modernen Rechner < 5s für einen längeren Text (der in einer natürlichen Sprache geschrieben ist).

3) Genauso, wenn ich bei der XOR-Verschlüsselung die Struktur des verschlüsselten Textes kenne (zum Beispiel das er mit "halligalli123" anfängt), dann kann ich unmittelbar auf diese Anzahl von Zeichen des Schlüssels zurückschließen, und habe dann meißtens schon den ganzen Schlüssel.

Insgesamt: XOR ist für eine sinnvolle Verschlüsselung nie im Leben geeignet. Es ist mehr ein Beispiel für eine symmetrische Funktion.

Verfasst: Donnerstag 20. April 2006, 13:24
von Joghurt
modelnine hat geschrieben:Insgesamt: XOR ist für eine sinnvolle Verschlüsselung nie im Leben geeignet. Es ist mehr ein Beispiel für eine symmetrische Funktion.
XOR ist absolut sicher, allerdings NUR, wenn
a) der Schlüssel mindestens genauso lang ist wie der Text, und
b) der Schlüssel komplett zufällig ist, und
c) kein Schlüssel mehrmal verwendet wird.

Ansonsten gilt natürlich das von modelnine gesagte. Wenn ihr Sicherheit wollt, nehmt einfach einen erprobten Verschlüsselungsalgo, z.B. AES oder Blowfish (beides ist mit PyCrypto kein Problem)

Verfasst: Donnerstag 20. April 2006, 13:53
von Python 47
Ein absolut sichere Verschlüsselung ist das One Time Pad. Es ist in der praxis sehr schwer anwendbar, dafür aber auch unmöglich knackbar(wenn einige Bedingungen erfüllt sind).

Aber leider kann man das mit PyCrypto nicht machen! :?

Verfasst: Donnerstag 20. April 2006, 14:09
von modelnine
Ein absolut sichere Verschlüsselung ist das One Time Pad.
XOR mit längerem Schlüssel als Plaintext ist eine Art von One-Time-Pad-Verschlüsselung.

Verfasst: Donnerstag 20. April 2006, 14:10
von Python 47
modelnine hat geschrieben:
Ein absolut sichere Verschlüsselung ist das One Time Pad.
XOR mit längerem Schlüssel als Plaintext ist eine Art von One-Time-Pad-Verschlüsselung.
Achso gut, das wusste ich nicht!Man lernt eben nie aus! :wink:

Verfasst: Donnerstag 20. April 2006, 14:24
von modelnine
Normalerweise bedeutet "One-Time-Pad" keinen spezifischen Algorithmus (der Name kommt zwar von einer bestimmten Anwendung, aber...), sondern spezifiziert eine Klasse von Algorithmen mit bestimmten Eigenschaften, wie die "Unbrechbarkeit." (die auch hier sehr relativ zu verstehen ist bei einer real-world-Anwendung, aber dazu lass ich mich jetzt nicht aus ;-))

Verfasst: Donnerstag 20. April 2006, 16:47
von murph
Ich habe nur die Idee gehabt, einen sicheren Datentransfer zu machen,
der, wie man es nun mal gerne mag, zu (fast)100 % sicher ist...da ist nur die Frage: welches Schlüsselsystem nimmt man da? Deshalb das Interesse...
Gibt es noch mehr Verschlüsselungen (von denen ihr den Skript habt), die man nutzen kann?

Verfasst: Donnerstag 20. April 2006, 17:11
von Leonidas
murph hat geschrieben:Ich habe nur die Idee gehabt, einen sicheren Datentransfer zu machen, der, wie man es nun mal gerne mag, zu (fast)100 % sicher ist...
Es gibt keine 100% sicheren Verschlüsselungen. Einige sind sicherer andere weniger. Und XOR ist weit davon entfernt sicher zu sein.
murph hat geschrieben:da ist nur die Frage: welches Schlüsselsystem nimmt man da? Deshalb das Interesse...
Ich würde es mit SSL Tunneln, ggf auch extern über Stunnel. Aber eigentlich nutze ich immer SSH's SCP/SFTP. Das ist sicher, schnell, gut getestet, weithin unterstützt und schon fertig benutzbar.
murph hat geschrieben:Gibt es noch mehr Verschlüsselungen (von denen ihr den Skript habt), die man nutzen kann?
Brauchst du eine Stream-Verschlüsselung oder eine Blockverschlüsselung? Wenn letzteres möglich ist, solltest du dir auf jeden Fall PyCrypto ansehen. Blowfish oder AES zu knacken sollte ein schwierigereres Unterfangen sein, als XOR.

Oder du kannst gleich die grpße Public-Key Maschinierie anwerfen: RSA, DSA, ElGamal.

Hängt einfach ab, was du brauchst. Von dem was du so gemeint hast, würde ich dir zu SSL raten.

Verfasst: Donnerstag 20. April 2006, 17:35
von modelnine
Du kannst Dir auch mal yawPyCrypto angucken, was ich während meiner Zeit an der UdS als Wrapper für PyCrypto geschrieben hab, um gewisse Dinge wie Block-Ciphers "einfacher" nutzbar zu machen, oder auch für Public-/Private-Key Cryptographie. Ich hab yawPyCrypto lange nicht mehr angefasst; wenn's Probleme gibt, msg me. ;-)

Verfasst: Donnerstag 20. April 2006, 18:04
von Joghurt
murph hat geschrieben:Ich habe nur die Idee gehabt, einen sicheren Datentransfer zu machen
Was meinst du mit sicher?
Willst du verhindern, dass jemand mitliest, oder willst du sicherstellen, dass die Nachricht nicht manipuliert wurde, oder beides?

Im ersten Fall bietet sich AES an, im zweiten Fall Assymetrische Verschlüsselung.

Für die, die sich fragen, warum XOR mit einmaligen zufälligen Schlüsseln perfekt sicher ist: z.B. kann die Nachricht "fl091jvcajgi3fhfal" sowohl "Stirb, Ungläubiger" als auch "Heute abend Party!" heißen; beides ist gleich wahrscheinlich.

Verfasst: Donnerstag 20. April 2006, 18:26
von murph
Die Aufgabe ist, dass die Datei nicht manipuliert werden kann, ohne sie unnütz zu machen. Ebenso stehen in ihr empfindliche Daten, wie (nur über include) die Datenbankverbindung zur MySQL.
Ich habe grade die Idee, den md5hash aus dem Text zu ziehen und zu vergleichen mit dem auf dem Server gelegenden Wert (über threading zuerst das ausrechnen lassen und danach den md5-hash vom skript zu ziehen und dem Server senden).