Ich habe übrigens mal eine Häufigkeitsanalyse der Buchstaben dieses Threads gemacht:
Code:
insgesamt 14078
e 2053 = 14,5%
n 1303 = 09,3%
i 1135 = 08,1%
s 1061 = 07,5%
t 988 = 07,0%
Verglichen hiermit passt das schon ganz gut.
Also dieser Thead ist z.B. schon sehr gut für eine Häufigkeitsanalyse geeignet. In der Regel reichen schon 200 Wörter.
Ich habe auch mal ein kleines Pythonskript geschrieben, dass die Verschlüsselung bricht:
Es nimmt einfach an, dass am häufigsten das Leerzeichen und am Zweithäufigsten das kleine "e" vorkommt. Nun zählt es für die jewelige Vermutete Schlüssellänge die Buchstaben jeweils einzeln zusammen und schaut, wenn z.B. in einer Spalte (wie weiter oben gepostet) Q am häufigsten und T am zweithäufigsten ist, welcher Schlüsselbuchstabe ein ' ' zu 'Q' und welcher ein 'e' zu 'T' machen würde. Sind beide gleich, wird angenommen, dass der jeweilige Schlüsselbuchstabe gefunden wurde.
Wenn für die Vermutete Schlüssellänge alle Buchstaben gefunden wurden, wird der Schlüssel ausgegeben. Ich habe als Eingabedatei ein HTML der Druckversion dieses Threads genommen und bis zu einer Schlüssellänge von 6 hat es den Schlüssel jedesmal herausbekommen. Bei längeren Schlüsseln reicht die Statistik nicht mehr aus.
Es ist übrigens egal, ob Addition oder XOR genommen wird. Beide Verfahren sind gleichwertig.
Hier mal der Code in Python, jedoch ohne weitere Kommentare:
Code:
def encrypt(buffer, key):
keypos = 0
cypher = []
for ch in buffer:
cypher.append( chr((ord(ch)+ord(key[keypos]))%256) )
keypos = (keypos+1)%len(key)
return "".join(cypher)
def try_crack(cypher, keylength):
hists = []
for x in xrange(keylength):
hists.append({})
bin = 0
retval = []
for ch in cypher:
hists[bin][ch] = hists[bin].setdefault(ch, 0) + 1
bin = (bin+1)%keylength
for hist in hists:
hist = hist.items()
hist.sort(lambda a,b:-cmp(a[1], b[1]))
# Welcher Schlüsselbuchstabe macht ein ' ' zu unserem häufigsten Zeichen?
test_space = chr((ord(hist[0][0])-ord(' '))%256)
# Dito für 'e' und zweithäufigstes Zeichen
test_e = chr((ord(hist[1][0])-ord('e'))%256)
# Wenn beide übereinstimmen, ist es ein guter Kandidat für das Schlüsselzeichen
if test_space == test_e:
retval.append(test_space)
else:
return None
return "".join(retval)
x = open("a.html").read()
cipher = encrypt(x,"test12")
for i in xrange(1,10):
key = try_crack(cipher, i)
if key != None:
print "Key might be",key
#Ausgabe:
# Key might be t
# Key might be ttttt
# Key might be test12
#Die ersten beiden sind Fehltreffer, der dritte ist der richtige
Lesezeichen