Base64 - Encode - Decode

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
fstrauss
User
Beiträge: 10
Registriert: Montag 12. September 2011, 11:29

Hallo Community!

ich habe eine Frage zur Verschlüsselung bzw. Entschlüsselung von einem String in Base64/32/16.

Gibt es jemand, der so etwas schon gemacht hat?
Wäre super, wenn ich mir mal den Quelltext anschauen könnte. (Vorlesung Kryptographie)

Die eingebaute Funktion "base64" von Python soll dabei nicht benutzt werden!
Es soll quasi "von Hand" gemacht sein.


Danke im Voraus
BlackJack

@fstrauss: Du möchtest gerne Quelltext für Base64-(de)kodierung sehen, dabei darf die entsprechende eingebaute von Funktion von Python aber nicht benutzt werden? Fragst Du da gerade ob jemand Deine Hausaufgaben für Dich macht!? :-)

Ich denke dazu sollte es mehr als genug Informationen und auch Implementierungen im Netz geben. Mach doch wenigstens Deine Recherche-Arbeit selbst. :-P

Falls Du dann konkrete Probleme bei *Deiner* Implementierung hast, kannst Du die ja (mit Quelltext) hier zur Diskussion stellen.

Hinweise: Zwischen "Zeichen" und ihrem Bytewert als Zahl kann man in Python mit `ord()` und `chr()` hin und her konvertieren. Bits verschieben und logische Verknüpfungen funktionieren mit den gleichen Operatoren wie bei den meisten Sprachen, die C irgend wo bei ihren Vorbildern für so etwas haben, also hauptsächlich ``<<``, ``>>``, ``&``, und ``|``.
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Warum nimmst du nicht einfach den Quelltext der `base64`-Funktion als Vorlage?!

http://hg.python.org/cpython/file/2.7/Lib/base64.py
„Lieber von den Richtigen kritisiert als von den Falschen gelobt werden.“
Gerhard Kocher

http://ms4py.org/
BlackJack

@ms4py: Wahrscheinlich weil das da nicht drin steht. ;-) Das Modul verwendet seinerseits Funktionen aus dem `binascii`-Modul, und das ist in C geschrieben. Und ob das jetzt so hilfreich ist…: http://hg.python.org/cpython/file/d2f30 ... cii.c#l468
fstrauss
User
Beiträge: 10
Registriert: Montag 12. September 2011, 11:29

Also die Verschluesselung habe ich jetzt selber hinbekommen!
(Nach etwas längerem probieren)

Implentiert wurde eine Base64 Funktion, die eine Textdatei ausliest und codiert.

Problem: Dies Funktioniert nur auf Kommandozeilen ebene!
Ich würde gerne den decodierten String wieder in eine Textdatei schreiben. Doch er schreibt mir an bestimmten Stellen immer das/die Zeichen "\00" hinein.
Woher diese kommen verstehe ich nicht und die Textdatei lässt sich auch nicht ohne Probleme öffnen.

Wenn ich den Dekodierten und Kodierten String aber auf Kommandozeile ausgebe bzw. ein "cat output.txt" machen wird alles richtig dargestellt.

Hinweis:
Der Code sollte noch eine Base16 und Base32 enthalten. Dieser wurde aus Übersichtgründen herausgenommen. (hätte auch noch nicht funktioniert)



Hier mal mein Code.

Programmaufruf:
Stufe 1:
./base binary // Liest die angegebene Textdatei aus und verschluesselt sie. Dabei wird eine Datei "verschluesselung_base64" erzeugt.
Stufe 2:
./base output.txt // Legt die Datei output.txt an und schreibt den dekodierten String hinein. Dabei wird die Datei "verschluesselung_base64" automatisch ausgelesen


base

Code: Alles auswählen

#!/usr/bin/python

import sys
import base64
from basetable import my_base16, my_base32, my_base64


def menue():

	print "Welchen Algrorithmus wollen sie fuer die Ko/Dekodierung verwenden?"

	print "Base16 - (1)"
	print "Base32 - (2)"
	print "Base64 - (3)"
	print "Beenden - (4)"


	while True:
		try:
			eingabe = 0
			while ((eingabe < 1) or (eingabe > 4)):
				eingabe = int(raw_input("Bitte Nummer eingeben: "))
			return eingabe
		except ValueError:
		        print "Nummer zwischen 1 und 4 eingeben!"



def main(arg):

	try:
		eingabe = menue()
	
#		if eingabe == 1:
#			option = encode_decode()
#			my_base16(arg, option)
#		elif eingabe == 2:
#			option = encode_decode()
#			if option == 1 and text == '':
#				raise IOError("Die Datei 'binary' enhaelt keine Zeichenkette!")
#			else:
#				my_base32(text,option)		
		elif eingabe == 3:
			option = encode_decode()
			my_base64(arg, option)
		elif eingabe == 4:
			print "Programm wird beendet!"

	
	except Exception, err:
		print "Fehler: %s" %err	

def encode_decode():
	print "Was moechten sie machen?"
	print "kodieren   - (1)"
	print "dekodieren - (2)"
	
	while True:
		try:
			eingabe = 0
			while ((eingabe < 1) or (eingabe > 2)):
				eingabe = int(raw_input("Bitte Nummer eingeben: "))
			return eingabe
		except ValueError:
		        print "1 oder 2 eingeben!"

if __name__ == "__main__":
   	try:
		main(sys.argv[1])
	
	except Exception:
		print "Keine oder falsche Argumente uebergeben!"


binary:

Code: Alles auswählen

Hallo Welt! Wie gehts
Das Leben ist
schoen
basetable.py

Code: Alles auswählen


import base64
import StringIO


def encode_base64(argument, lookup):
	
	foutput = open("verschluesselung_base64", "w")
	finput = open(argument, "r")

	#aus = ''

	#for line in finput:
	#	encoded = base64.b64encode(line)
	#	aus = aus + encoded
	#print "Decode: %s" %aus

	ausgabe = ''
	for line in finput:

		it = []
		it = ( line[i:i+3] for i in xrange(0, len(line), 3) )

		#for i in line:
			

		for item in it:
			#print item

			if len(item) == 2:

				bin = 0
				bin = ((ord(item[0])) << 16) | ((ord(item[1])) << 8)
				arr = []
				arr = [((bin >> 18) & 63), ((bin >> 12) & 63), ((bin >> 6) & 63)]
				ausgabe += lookup[arr[0]] + lookup[arr[1]] + lookup[arr[2]] + '='

			elif len(item) == 1:			
			
				bin = 0
				bin = ((ord(item[0])) << 16)
				arr = [] 
				arr = [((bin >> 18) & 0x00003F), ((bin >> 12) & 0x00003F)]
				ausgabe += lookup[arr[0]] + lookup[arr[1]] + '=' + '='

			else:
				bin = 0
				bin = ((ord(item[0])) << 16) | ((ord(item[1])) << 8) | (ord(item[2]))
				arr = []				
				arr = [((bin >> 18) & 0x00003f), ((bin >> 12) & 0x00003F), ((bin >> 6) & 0x00003F), (bin & 0x00003F)]
				ausgabe += lookup[arr[0]] + lookup[arr[1]] + lookup[arr[2]] + lookup[arr[3]]

	
	#print ("Kodiert: %s") %ausgabe
	foutput.write(ausgabe)
	foutput.close()
	finput.close()


def decode_base64(argument, lookup):


	alpha = { "A":0, "B":1, "C":2, "D":3, "E":4, "F":5, "G":6, "H":7, "I":8, "J":9, "K":10, "L":11, "M":12, "N":13,
		  "O":14, "P":15, "Q":16, "R":17, "S":18, "T":19, "U":20, "V":21, "W":22, "X":23, "Y":24, "Z":25, "a":26,
		  "b":27, "c":28, "d":29, "e":30, "f":31, "g":32, "h":33, "i":34, "j":35, "k":36, "l":37, "m":38, "n":39,
		  "o":40, "p":41, "q":42, "r":43, "s":44, "t":45, "u":46, "v":47, "w":48, "x":49, "y":50, "z":51, "0":52,
		  "1":53, "2":54, "3":55, "4":56, "5":57, "6":58, "7":59, "8":60, "9":61, "+":62, "/":63 }


	finput = open("verschluesselung_base64", "r")
	foutput = open(argument, "w")

	kette = ''

	for line in finput:	

		#line = line.strip()

		it = ( line[i:i+4] for i in xrange(0, len(line), 4) )
		
		for item in it:
			
		
			anzahl = item.count("=")
			org = len(item) - anzahl
			newitem = item[0:org]
			#print "%s --- %i --- %i --- %s" %(item, anzahl, org, newitem)

			laenge = len(newitem)

			if laenge == 3:
				bin = 0
				bin = ((alpha[newitem[0]]) << 18) | ((alpha[newitem[1]]) << 12) | ((alpha[newitem[2]]) << 6)
			
				kette = kette + chr((bin >> 16) & 0x0000FF) + chr((bin >> 8) & 0x0000FF) + chr(bin & 0x0000FF)	
			
			elif laenge == 2:
				bin = 0
				bin = ((alpha[newitem[0]]) << 18) | ((alpha[newitem[1]]) << 12)
			
				kette = kette + chr((bin >> 16) & 0x0000FF) + chr((bin >> 8) & 0x0000FF) + chr(bin & 0x0000FF)	

			elif laenge == 1:
				bin = 0
				bin = ((alpha[newitem[0]]) << 18)
			
				kette = kette + chr((bin >> 16) & 0x0000FF) + chr((bin >> 8) & 0x0000FF) + chr(bin & 0x0000FF)

			else:
				bin = 0 				
				bin = ((alpha[newitem[0]]) << 18) | ((alpha[newitem[1]]) << 12) | ((alpha[newitem[2]]) << 6) | (alpha[newitem[3]])
				kette = kette  + chr((bin >> 16) & 0x0000FF) + chr((bin >> 8) & 0x0000FF) + chr(bin & 0x0000FF)					


	#print "Dekodiert: %s" %kette
	#kette = kette.strip()
	foutput.write(kette)
	finput.close()
	foutput.close()




# 4 Bit pro Zeichen
def my_base16(argument, option):

	table = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', "A", "B", "C", "D", "E", "F"]


	if option == 1:
		encode_base16(argument, table)

	else:
		decode_base16(argument)
	

# 5 Bit pro Zeichen
def my_base32(text, option):

	code = {0:"A", 1:"B", 2:"C", 3:"D", 4:"E", 5:"F", 6:"G", 7:"H", 8:"I", 9:"J", 10:"K",
		11:"L", 12:"M", 13:"N", 14:"O", 15:"P", 16:"Q", 17:"R", 18:"S", 19:"T", 20:"U",
		21:"V", 22:"W",	23:"X", 24:"Y", 25:"Z", 26:'2', 27:'3', 28:'4', 29:'5', 30:'6',
		31:'7'}

	if option == 1:
		encode_base32(text, code)
	else:
		decode(text, code)

# 6 Bit pro Zeichen
def my_base64(argument, option):


	code = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R",
		"S", "T", "U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j",
		"k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", '0', '1',
		'2', '3', '4', '5', '6', '7', '8', '9', "+", "/"]


	if option == 1:
		encode_base64(argument, code)
	else:
		decode_base64(argument, code)

BlackJack

@fstrauss: Vorweg etwas zu Dateien: Wenn Du Binärdaten hast, solltest Du die Dateien auch unbedingt im Binärmodus öffnen, sonst kann das Betriebssystem Dir die Daten beim lesen oder schreiben verfälschen.

Wo genau siehst Du denn die '\x00'? Das sehe ich an dem Code nämlich nicht. Ich sehe aber wo die Nullbytes herkommen. Beim dekodieren schaffst Du es ja interessanterweise aus 1, 2, 3, oder 4 kodierten Zeichen *immer* drei dekodierte Bytes zu erzeugen. ;-)

Ich würde das übrigens nicht „Verschlüsselung“ nennen.
fstrauss
User
Beiträge: 10
Registriert: Montag 12. September 2011, 11:29

Mit der "verschlüsselung" gebe ich dir recht.
Genau genommen ist ja eine Codierung!

Wenn du den Code einmal ausführst, einmal zum kodieren und danach zum dekodieren erzeut er ja eine Textdatei mit dekodierten Klartext.
Wenn ich diese Textdatei öffnen will (gedit) werden die "\00" rot hervorgehoben und gedit bringt die Meldung: "Die geöffnete Datei enthält einige ungültigen Zeichen...."


Hinweis: Es ist kein "\x00" sondern "\00"


Zum Dekodieren:

Nehmen wir an ich lese die kodierten Zeichen "abc=" aus.
In base64 würde das bedeuten, dass das Gleichheitszeichen angehängt wurde, da nur zwei Byte zur kodierung verwendet wurden z.B "Fa". In base64 müssen aber 24 Bitblöcke kodiert werden.

In meiner Dekodierfunktion nehme ich dann die drei Zeichen "abc" welche 18 Bit repräsentieren und fülle die restlichen Bit mit 0 auf.
Nun kann ich daraus wieder 3 * 8 Bit (also 3 Zeichen herstellen)
PS: Bei 4 Zeichen werden keine Nullbits angehängt!

Das ist doch Korrekt?!
BlackJack

@fstrauss: Da steht auch nicht '\00' in der Datei also nicht die drei Zeichen '\', '0', und '0' sondern ``gedit`` zeigt Dir als Benutzer auf diese Weise Nullbytes an, weil die keinem Zeichen zugeordnet werden. Das kann in anderen Editoren anders aussehen. Einige werden sich weigern die Datei zu öffnen, andere werden die Bytes zumindest in der Anzeige einfach unterschlagen. Wie das auch bei ``cat`` der Fall ist. Du bekommst da nämlich auch nicht das richtige Ergebnis. Die Konsole zeigt Nullbytes einfach nur nicht an — vorhanden sind sie trotzdem. Vergleiche einfach mal die Dateilängen.

Die Fehlerquelle hatte ich Dir ja bereits genannt.
fstrauss
User
Beiträge: 10
Registriert: Montag 12. September 2011, 11:29

Aso,

das bringt mich zumindest ein kleines Stück weiter.


Aber mit der "Fehlerquelle" kann ich nichts anfangen, da ich in meinem Code bzw. der Logik keinen Fehler sehe!

Wenn ich die kodierte Datei auslese, sagen wir 4 Zeichen, dann wird doch jedes Zeichen durch 6 Bits dargestellt?!
Wenn ich 4 Zeichen habe ergibt das 3 Byte und ich kann 3 Zeichen daraus machen.

lese ich jedoch nur 3 Zeichen aus (das "=" muss ich ja wegbekommen) habe ich 18 Bit und kann daraus keine 3 zeichen erstellen. Also muss ich noch mit 6 * binär 0 auffüllen um auf 24 Bit und somit 3 Zeichen zu kommen.

PS: Kann es sein das unten ausgeführte ausschnitt zur lösung meines Problems führt?
Kann es gerade nicht testen?

Wenn nicht, weiß ich nicht wie ich es korrigieren kann.

Code: Alles auswählen

def decode_base64(argument, lookup):


        alpha = { "A":0, "B":1, "C":2, "D":3, "E":4, "F":5, "G":6, "H":7, "I":8, "J":9, "K":10, "L":11, "M":12, "N":13,
                  "O":14, "P":15, "Q":16, "R":17, "S":18, "T":19, "U":20, "V":21, "W":22, "X":23, "Y":24, "Z":25, "a":26,
                  "b":27, "c":28, "d":29, "e":30, "f":31, "g":32, "h":33, "i":34, "j":35, "k":36, "l":37, "m":38, "n":39,
                  "o":40, "p":41, "q":42, "r":43, "s":44, "t":45, "u":46, "v":47, "w":48, "x":49, "y":50, "z":51, "0":52,
                  "1":53, "2":54, "3":55, "4":56, "5":57, "6":58, "7":59, "8":60, "9":61, "+":62, "/":63 }


        finput = open("verschluesselung_base64", "r")
        foutput = open(argument, "w")

        kette = ''

        for line in finput:    

                #line = line.strip()

                it = ( line[i:i+4] for i in xrange(0, len(line), 4) )
               
                for item in it:
                       
               
                        anzahl = item.count("=")
                        org = len(item) - anzahl
                        newitem = item[0:org]
                        #print "%s --- %i --- %i --- %s" %(item, anzahl, org, newitem)

                        laenge = len(newitem)

                        if laenge == 3:
                                bin = 0
                                bin = ((alpha[newitem[0]]) << 18) | ((alpha[newitem[1]]) << 12) | ((alpha[newitem[2]]) << 6)
                       
                                kette = kette + chr((bin >> 16) & 0x0000FF) + chr((bin >> 8) & 0x0000FF) + chr(bin & 0x0000FF)     
                       
                        elif laenge == 2:
                                bin = 0
                                bin = ((alpha[newitem[0]]) << 18) | ((alpha[newitem[1]]) << 12)
                       
                                kette = kette + chr((bin >> 16) & 0x0000FF) + chr((bin >> 8) & 0x0000FF)   

                        elif laenge == 1:
                                bin = 0
                                bin = ((alpha[newitem[0]]) << 18)
                       
                                kette = kette + chr((bin >> 16) & 0x0000FF) 

                        else:
                                bin = 0                                
                                bin = ((alpha[newitem[0]]) << 18) | ((alpha[newitem[1]]) << 12) | ((alpha[newitem[2]]) << 6) | (alpha[newitem[3]])
                                kette = kette  + chr((bin >> 16) & 0x0000FF) + chr((bin >> 8) & 0x0000FF) + chr(bin & 0x0000FF)                                    


        #print "Dekodiert: %s" %kette
        #kette = kette.strip()
        foutput.write(kette)
        finput.close()
        foutput.close()

Zuletzt geändert von fstrauss am Freitag 28. Oktober 2011, 14:12, insgesamt 1-mal geändert.
BlackJack

@fstrauss: So in der Richtung müsste die Lösung aussehen, ja.
fstrauss
User
Beiträge: 10
Registriert: Montag 12. September 2011, 11:29

Hab es gerade versucht und bekomme nur noch mehr "\00"
Antworten