Ein Caesar-Cipher ist eine lineare Substitutionsziffer. Erklärung:
Haben Sie p seien Sie Ihr Klartext. Haben k unser numerischer Schlüssel sein (< 26 wegen dieser Erklärung). Haben c ein Zeichen in p. Haben I (c) sein der Index von c in p. Haben fc (i) eine Funktion sein, die einen Index i zu seinem Buchstaben im Alphabet abbildet. Haben e (c) das "verschlüsselte" Zeichen von c sein.
Dann:
e (c) = fc (I (c) + k)
oder in Klartext: Jedes Zeichen wird durch den Wert von k verschoben. Es ist daher eine lineare Substitution, da es immer um den gleichen Betrag verschoben wird und die Zeichen ersetzt werden.
Das Problem mit diesem Verschlüsselungsalgorithmus ist, dass Sie nicht wirklich den Klartext verschlüsseln oder Entropie hinzufügen. (In harten Worten, die Caesar-Cipher ist näher an einer Codierung als an einer Verschlüsselung).
Da wissen wir, dass alle übereinstimmenden Buchstaben in unserem Chiffre-Text für die genau gleiche Klartext-Zeichen ersetzen.
Das bedeutet, Sie können statistische Analysen auf Ihrem Cipher-Text durchführen und einfach die Briefverteilung analysieren. Verschiedene Töne/Buchstaben treten unterschiedlich oft auf.
Also, wie wenden wir diese Technik an?
Aufgrund Ihres Namens würde ich annehmen, dass Sie Deutscher sind und ich nehme an, dass Ihr Chiffre-Text auch ist.
In Deutsch, die am häufigsten verwendeten Buchstaben sind E und I.
Wir sind fast da!
Jetzt können Sie einfach den häufigsten Buchstaben in Ihrem Chiffre-Text finden und den Unterschied zwischen diesem Buchstaben und E (Differenz zwischen ihren Indizes, natürlich) berechnen. Das wird dir den geheimen Schlüssel geben!
Hier ist ein Codebeispiel:
"""
This module aims to break Caesar-ciphers from German plaintext
based on statistics of letter distribution.
The caesar cipher is a character substitution algorithm.
Bob chooses a number as the key n.
Bob then shifts every character of the plain-text by n, cycling
through the entire alphabet.
e.g.: if n = 3: "ABC" -> "DEF".
Since it has a very small keyspace (26^1), it can be easily broken,
and Mallory could even guess or bruteforce the key.
(Note: You could choose a number higher than 26. However, this won't
increase your keyspace since any number x will
be reduced to 1-26. See: (x - (26*(x // 26)).
Common letters in the german language are (in descending order):
"E","N","I","S","R" (subject to verification)
The statistical approach works well for long sentences since one has
a greater samplesize for distribution analysis.
If two or more letters appear the same amount of times, you have to
check which key is actually correct, either
by simply reading the outputs or running them against a
distribution_dict of that language.
"""
ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
SPECIAL_CHARS = " ,.-;:_?!="
def encrypt(plain_text, key):
"""
Encrypts plaintext using a caesar.
:param plain_text: The plaintext
:param key: The key (Integer)
:return: The cipher-text
"""
cipher_text = ""
for letter in plain_text:
if letter in SPECIAL_CHARS:
cipher_text += letter
continue
index = ALPHABET.find(letter.upper())
new_index = flatten(index + key)
cipher_text += ALPHABET[new_index]
return cipher_text
def decrypt(cipher_text, key=None):
"""
This function decrypts plaintext. If no key is specified, it
will be found using distribution analysis.
:param cipher_text: The cipher-text
:param key: The key
:return: the plain-text
"""
if key is None:
key = find_key_from_cipher(cipher_text)
plain_text = ""
for letter in cipher_text:
#Skipping special characters (incomplete solution)
if letter in SPECIAL_CHARS:
plain_text += letter
continue
index = ALPHABET.find(letter.upper())
new_index = flatten(index - key)
plain_text += ALPHABET[new_index]
return plain_text
def flatten(number) :
"""
Flattens the key back to be in range(1,26)
:param number:
:return:
"""
return number - (26*(number//26))
def find_key_from_cipher(cipher_text):
index_of_most_common_letter = 4 #Index of 'e'
#Calculate distribution
distribution_dict = analyse_letter_distribution(cipher_text)
#Get common letters
common_letters = sorted(distribution_dict, key=distribution_dict.get, reverse=True)
#Use most common letter to get key
key = ALPHABET.find(common_letters[0].upper()) - index_of_most_common_letter
return key
def analyse_letter_distribution(cipher_text):
distribution_dict = {}
for letter in cipher_text:
if letter in SPECIAL_CHARS:
continue
if letter not in distribution_dict:
distribution_dict[letter] = 1
else:
distribution_dict[letter] += 1
if len(distribution_dict.values()) != len(distribution_dict.values()):
print("Multiple letters appear the same amount of times! Uh oh.")
return distribution_dict
if __name__ == "__main__":
secret = encrypt("This sentence is encrypted. Encryption is broken by using awesome encryption algorithms!",5)
print(decrypt(secret))
Eine letzte Anmerkung: Da es sich um eine statistische Analyse ist dieser Ansatz funktioniert am besten, wenn das aufgenommene Chiffre-Text lang ist.
Eine letzte letzte Anmerkung: Diese Beschreibung ist ein wenig unvollständig (und die Formatierung sieht hässlich aus, ich bin auf dem Handy.) Ich empfehle dieses german book von Klaus Schmeh für weitere Lektüre.
Hilfe mit was genau ?? –
Entschuldigung, wir brauchen mehr Informationen, um dir zu helfen ... hast du schon etwas Code, den du posten kannst? – Dadep
Wenn Sie Text aus einer bekannten Sprache entschlüsseln, können Sie einfach jeden möglichen Schlüssel ausprobieren und sehen, wie viele der resultierenden Wörter in einer Wortliste dieser Sprache sind. –