Encrypt/Decrypt Programm 100% sicher (One-Time-Pad)

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Antworten
Gammahoo
User
Beiträge: 2
Registriert: Sonntag 14. März 2010, 20:49

Huhu,
ich bin noch recht neu mit Python und habe mir gedacht, dass ich auch mal ein kleines Programm in den Showcase stelle, v.a. um Verbesserungen, z.b. zum Programmier-Stil etc., zu kriegen. Das Programm kann Text-Dateien mit Hilfe der One-Time-Pad Methode theoretisch 100% sicher verschlüsseln. Es gibt eine neue Text-Datei und eine Key-Datei aus, die zur Entschlüsselung benötigt wird. Das Programm behält dabei die Formatierung, sowie Leerzeichen und Großbuchstaben bei der Verschlüsselung bei.


http://de.wikipedia.org/wiki/One-Time-Pad

Code: Alles auswählen

'''
Created on 16.03.2010
File encryption (One-Time-Pad-Method)
@author: Orbital
'''

import random

class LoadSave( object ):	#Speichert und Laedt die Datei / Keydatei
		
	def __init__( self ):
		
		self.keystr = ""
		self.count = 0
		self.key = None
	
	def load( self,file,keyfile=None ):	#Laedt die Datei (und die Keydatei, falls angegeben)
		
		file = file.strip('"')	
		if keyfile: keyfile = keyfile.strip('"')	#Strippen wuerde bei None einen Fehler erzeugen
		self.fileobj = open(file,'r')
		self.text = self.fileobj.read()
		self.fileobj.close()
		if keyfile:	#Falls vorhanden: Keydatei wird ausgelesen und gesplittet
			self.fileobj = open(keyfile,'r')
			self.key = self.fileobj.read().split()
			self.fileobj.close()
		
		return (self.text,self.key)	#Rueckgabe der Werte der Datei und Keydatei
	
	def save( self,filename,text,key=None ):	#Speichert die Datei (und die Keydatei, falls angeben)
		
		self.filename = filename + ".txt"	#Fuegt gaengige *.txt-Endung an
		self.keyname = filename + ".key"	#Fuegt *.key-Endung an
		self.cryptfile = open(self.filename,'w')
		self.cryptfile.write(text)
		self.cryptfile.close()
		if key:
			
			while self.count < len(key):	#Konvertiert den Key in einen String mit Leerzeichen getrennt
				
				self.keystr += key[self.count] + " "
				self.count += 1
				
			self.keyfile = open(self.keyname,'w')
			self.keyfile.write(self.keystr)
			self.keyfile.close()

class Encrypt( object ):	#Chiffrieren des Textes
	
	def __init__( self ):
		
		self.text = ""
		self.key = []
		self.count = 0
		self.abcnum = "abcdefghijklmnopqrstuvwxyz0123456789!?.,-_:;+*~/\\<>[]()={}%&' "	#Alle unterstuetzen Zeichen
	
	def cryp( self,crypttext,length ):	#Eigentlicher Chiffrierungsvorgang
		
		while self.count < length:
			
			self.randit = crypttext[self.count]	#Einzelner Buchstabe wird rausgetrennt
			self.cryptletter = self.randit
			self.uplow = self.randit	#Variable fuer spaeteres zuruecksetzen auf urspruengliche Groesse
			if self.randit.lower() in self.abcnum:
				self.randit = self.abcnum.find(self.randit.lower())
				if self.uplow.isupper():	#Die Groesse soll beibehalten werden, deswegen werden nur Buchstaben genutzt
					self.x = random.randrange(0,26 - self.randit)
				else:	#Fuer Kleinbuchstaben
					self.x = random.randrange(0,62 - self.randit)
				self.randit += self.x
				self.cryptletter = self.abcnum[self.randit]
				if self.uplow.isupper(): self.cryptletter = self.cryptletter.upper()
				self.key.append(str(self.x))
			self.text += self.cryptletter
			self.count += 1
		
		return (self.text,self.key)	#Rueckgabe des Textes und des Keys

class Decrypt( object ):	#Dechiffrierungs-Klasse
	
	def __init__( self ):
		
		self.text = ""
		self.count = 0
		self.truecount = 0
		self.abcnum = "abcdefghijklmnopqrstuvwxyz0123456789!?.,-_:;+*~/\\<>[]()={}%&' "
	
	def cryp( self,crypttext,key):	#Eigentliche Dechiffrierung
		
		while self.count < len(crypttext):

			self.encrypt = crypttext[self.count]
			self.cryptletter = self.encrypt
			if self.encrypt.lower() in self.abcnum:
				self.uplow = self.encrypt
				self.encrypt = self.abcnum.find(self.encrypt.lower()) - int(key[self.truecount])	#Berechnung der Buchstabenposition
				self.cryptletter = self.abcnum[self.encrypt]	#Umwandlung Zahl->Buchstabe
				if self.uplow.isupper(): self.cryptletter = self.cryptletter.upper()	#Zuruecksetzung auf Ursprungsgroesse
				self.truecount += 1
			self.count += 1
			self.text += self.cryptletter
			
			
		return self.text

info = ""
while "encrypt" not in info:
	info = raw_input("What would you like to do (decrypt,encrypt)? ")
	if info == "decrypt":
		break
if info == "encrypt":
	crypfile = raw_input("Which textfile do you want to encrypt? ")
	filename = raw_input("Please enter a name for your encrypted file: ")
	cryptext = LoadSave().load(crypfile)	#Aufrufung der Ladeklasse
	crypd = Encrypt().cryp(cryptext[0],len(cryptext[0]))	#Aufrufung der Chiffrierungsklasse
	LoadSave().save(filename,crypd[0],crypd[1])	#Aufrufung der Speicherklasse
elif info == "decrypt":
	crypfile = raw_input("Which textfile do you want to decrypt? ")
	keyfile = raw_input("Where is your keyfile located? ")
	filename = raw_input("Please enter a name for your decrypted file: ")
	cryp = LoadSave().load(crypfile,keyfile)	#Aufrufung der Ladeklasse
	crypdtext = Decrypt().cryp(cryp[0],cryp[1])	#Aufrufung der Dechiffrierungsklasse
	LoadSave().save(filename,crypdtext)	#Aufrufung der Speicherklasse
BlackJack

@Gammahoo: Was hast Du Dir bei den Klassen gedacht? Die sind total unnütz und machen das Programm einfach nur viel komplexer als es sein müsste. Wenn man ein Exemplar nur erstellt um danach eine Methode aufzurufen und das Exemplar danach sofort wieder weggeworfen wird, dann wollte man in der Regel eigentlich einfach nur eine Funktion schreiben. Klassen sollten "Dinge" beschreiben und keine "Tätigkeiten".

One-Time-Pad mit Beschränkung auf bestimmte Zeichen ist ungewöhnlich. Das lässt sich mit XOR-Verknüpfung von Bytewerten ganz einfach für beliebige Daten implementieren. Und dann braucht man auch nur *eine* Funktion zum Ver- und Entschlüsseln.
Gammahoo
User
Beiträge: 2
Registriert: Sonntag 14. März 2010, 20:49

Ich wollte später noch weitere Verschlüsselungsmethoden anfügen. Deswegen habe ich gleich eine Klasse erstellt, in die dann später weitere Methoden rein kommen.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Gammahoo hat geschrieben:Ich wollte später noch weitere Verschlüsselungsmethoden anfügen. Deswegen habe ich gleich eine Klasse erstellt, in die dann später weitere Methoden rein kommen.
Das kann man aber auch prima auf Modulebene mit Funktionen und ohne Klassen machen...
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo.
Gammahoo hat geschrieben:Ich wollte später noch weitere Verschlüsselungsmethoden anfügen. Deswegen habe ich gleich eine Klasse erstellt, in die dann später weitere Methoden rein kommen.
Das macht es auch nicht besser ;-) Dann verwendest du Klassen nur als Namesraum und dafür sind sie ebenfalls nicht gedacht. Du möchtest also immer noch Funktionen haben und diese ggf. in ein Dictionary packen.

Sebastian
Das Leben ist wie ein Tennisball.
lunar

@Gammahoo: Die Verschlüsselung ist ganz allgemein zu kompliziert. Die XOR-Verknüpfung beliebiger Datenblöcke (nichts anderes ist ein One-Time-Pad) ist ein Einzeiler:

Code: Alles auswählen

''.join(chr(ord(d) ^ ord(k)) for d, k in izip(data, key))
Mit Python 3 ist das sogar noch kürzer (vollständiges Beispiel):

Code: Alles auswählen

bytes(map(operator.xor, data, key))
Edit: Nebenbei bemerkt, lese einmal die Dokumentation des random-Moduls:
However, being completely deterministic, it is not suitable for all purposes, and is completely unsuitable for cryptographic purposes.
Man verwendet keine deterministischen Pseudozufallsgeneratoren für kryptographische Zwecke. „100% sicher“ im kryptographischen Sinne ist Deine Implementierung also beileibe nicht. Dafür musst Du einen echten Zufallsgenerator heranziehen (os.urandom oder random.SystemRandom()).
Antworten