This commit is contained in:
mikgaw@st.amu.edu.pl 2024-02-18 20:47:15 +01:00
commit 0aa97df223
14 changed files with 371785 additions and 0 deletions

3
.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View File

@ -0,0 +1,22 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="GrazieInspection" enabled="false" level="GRAMMAR_ERROR" enabled_by_default="false" />
<inspection_tool class="LanguageDetectionInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyPep8NamingInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
<option name="ignoredErrors">
<list>
<option value="N802" />
<option value="N803" />
</list>
</option>
</inspection_tool>
<inspection_tool class="PyUnresolvedReferencesInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="ignoredIdentifiers">
<list>
<option value="str.append" />
</list>
</option>
</inspection_tool>
</profile>
</component>

View File

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

7
.idea/misc.xml Normal file
View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Black">
<option name="sdkName" value="Python 3.9" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.9" project-jdk-type="Python SDK" />
</project>

8
.idea/modules.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/cesar-cipher-cracker.iml" filepath="$PROJECT_DIR$/.idea/cesar-cipher-cracker.iml" />
</modules>
</component>
</project>

1250
1250_eng_words.txt Normal file

File diff suppressed because it is too large Load Diff

39
README.md Normal file
View File

@ -0,0 +1,39 @@
# cesar-cipher-crakcer
Program łamie szyfr cezara używając analizy częstotliwości wystepowania znaków w języku.
====
The program shows success rates in cracking cesar ciphers
Example of long plaintext in Polish: Cześć, oto przykładowy tekst po Polsku ze znakami interpunkcyjnymi;,/$!? i kropkami..
Encrypted text with key 5: fbizgśźśuwbąńódhśaąźińyźuśuśoyńżbibrdńdpmmrźiwużrńfąnrąpmmńwśuńdpm
Result of ciphertext-only attack: cześćotoprzykładowytekstpopolskuzeznakamiinterpunkcyjnymiikropkami
====
Example of long plaintext in English: Once upon a time I decrypt some texts.
Encrypted text with key 9: xwlndyxwjcrvnrmnlahycbxvncngcb
Result of ciphertext-only attack: onceuponatimeidecryptsometexts
====
Now I will check how short of a word can be decrypted using this frequency analyzer.
100 3-letters long English words. Decryption succes rate: 13%
100 4-letters long English words. Decryption succes rate: 27%
100 5-letters long English words. Decryption succes rate: 23%
150 6-letters long English words. Decryption succes rate: 49%
200 7-letters long English words. Decryption succes rate: 45%
200 8-letters long English words. Decryption succes rate: 52%
200 9-letters long English words. Decryption succes rate: 63%

Binary file not shown.

74
data.py Normal file
View File

@ -0,0 +1,74 @@
letterFrequencyEng = {'e': 12.0,
't': 9.10,
'a': 8.12,
'o': 7.68,
'i': 7.31,
'n': 6.95,
's': 6.28,
'r': 6.02,
'h': 5.92,
'd': 4.32,
'l': 3.98,
'u': 2.88,
'c': 2.71,
'm': 2.61,
'f': 2.30,
'y': 2.11,
'w': 2.09,
'g': 2.03,
'p': 1.82,
'b': 1.49,
'v': 1.11,
'k': 0.69,
'x': 0.17,
'q': 0.11,
'j': 0.10,
'z': 0.07}
letterFrequencyPol = {
'a': 8.91,
'ą': 0.99,
'b': 1.47,
'c': 3.96,
'ć': 0.30,
'd': 3.25,
'e': 7.66,
'ę': 1.14,
'f': 0.30,
'g': 1.42,
'h': 1.08,
'i': 8.21,
'j': 2.28,
'k': 3.51,
'l': 2.10,
'ł': 2.16,
'm': 2.80,
'n': 5.52,
'ń': 0.20,
'o': 7.75,
'ó': 0.85,
'p': 3.13,
'r': 4.69,
's': 4.32,
'ś': 0.45,
't': 3.98,
'u': 2.50,
'w': 4.65,
'y': 3.76,
'z': 5.64,
'ź': 0.06,
'ż': 1.11
}
# to input more words change file name to words_end.txt
with open('1250_eng_words.txt', 'r') as f:
words = f.read()
allEnglishWords = words.split()
eng_3 = [word for word in allEnglishWords if len(word) == 3]
eng_4 = [word for word in allEnglishWords if len(word) == 4]
eng_5 = [word for word in allEnglishWords if len(word) == 5]
eng_6 = [word for word in allEnglishWords if len(word) == 6]
eng_7 = [word for word in allEnglishWords if len(word) == 7]
eng_8 = [word for word in allEnglishWords if len(word) == 8]
eng_9 = [word for word in allEnglishWords if len(word) == 9]

20
input_cesar.txt Normal file
View File

@ -0,0 +1,20 @@
loxklomnzkxycorrjkvruetkczkintowakyrkgxtzotznkcuxrjycuxyzcorjloxknuzyvuzygyirosgzkingtmkxgoykyznkxoyqrkbkrotznkaqznoyyasskxrgyzekgxynkgzcgbkyygcznuaygtjyulloxkyhxkgquazutkkbktjkyzxueotmnuskygzckttotmz
utkgyzrutjutznoyekgxngygrxkgjeykktnatjxkjyulmxgyyloxkygtjutkulznkaqyrgxmkyzkbkxngyhkkthaxtotmotznkyiuzzoynnomnrgtjyluxznkvgyzzcuckkqysuxkloxkixkcygxktuczxgototmotyqorrylxusyuaznkxtkaxuvkgtjznkaygxkkax
uvkycorjloxkyrotqkjzuirosgzkingtmknomnrgtjcorjloxkiuarjhkrgxmkyzkbkxotaqnuccorjloxkyyzgxzgtjnuczuyzuvznksloxkinoklygxkvgxzoiargxreruuqotmzukdvgtjznktashkxulyvkiogroyzzkgsyzxgotkjothaxtyavvxkyyoutzkint
owakyznkjkrohkxgzkhaxtotmulrgtjzuqkkvgloxkiutzgotkjgzznksusktzpayzlobkaqatozygixuyysuxkzngtloxkgtjxkyiakykxboikyyvkiogroykotznklomnzotmloxkcoznloxkzkintowaksuyzreotsuuxrgtjgxkgyhazinoklloxkulloikxvgar
nkjrkecorjloxkrkgjluxznktgzoutgrloxkinoklyiuatiortliiygojsuxkatozyotirajotmznuykotykxboikyzngzyzxgjjrkaxhgtgtjxaxgrgxkgycuarjhkzxgotkjottkccgeyulcorjloxklomnzotmznkeiuarjznkthkjkvruekjtgzoutgrreotznkk
bktzulgyomtoloigtzloxknkygojnkgjjkjznkxoyqgtjznxkgzulyainsgpuxcorjloxkycgyirkgxremxucotmotznkaqgrrulznoyrkgxtotmlxusotzkxtgzoutgrvgxztkxycnugxkvxuhghreyzorryuskekgxygnkgjulayoygbkxeyktyohrkcgeulzxeotm
zumkzaygnkgjulznkiaxbknkygojozoynuvkjgaqcojkzxgototmvxumxgsskcorrhkykzavgyvgxzulgtgzoutgrgizoutvrgtjxgctavotxkyvutykzuznkrkyyutyrkgxtzlxusrgyzekgxyhrgfkyutkulznkykxboikyrkgjotmznkcgeoyyaxxkeloxkgtjxky
iakcnoinngygrxkgjejkgrzcoznsuxkzngtcorjloxkyznoyekgxznksuyzxkiktzcorjloxkcgyrgyzsutzngzlxktyngsiussuttkgxlgxtngsgvuvargxhkgazeyvuzznkigaykulznknkizgxkloxkoytuzekzqtucthazznkjgsgmkoyirkgxzuykklxusnkgzn
rgtjzujkyurgzoutcnkxkutikznkxkcgyxoinnkgznrgtjnuskzuxgxkyvkiokyotirajotmygtjrofgxjyznkxkoytucjkyurgzoutcnktznkhhiboyozkjburatzkkxylxusznkgsvnohogtgtjxkvzorkiutykxbgzoutingxozeckxkcgrqotmznkyiuxinkjkgx
znyzxkzinkjuazotgrotkroqkgvuroikluxktyoiyzkgsykgxinotmluxixkgzaxkyzngzyaxbobkjznkhrgfkolznkosskjogzkosvgizoyynuiqotmznkrutmzkxskllkizygxkkwagrreiutikxtotmcnoryzckigtygbkyuskulznkykgtosgryzngzyaxbobkjz
nkloxkckruykgtgclarruzgtjckruykgrrzngzhoujobkxyozeozzgqkyekgxyoltuzjkigjkyluxzngzzuiuskhgiqgmgotkdvrgotkjzxayzkknucgxjottyluxiuatzxeyojkxgtmkxjgxxktnorrcnuyavvuxzkjloxklomnzkxyzgiqrotmznkhrgfknkxkykko
tmznkglzkxsgzngtjqtucotmsuxkcorjloxkyiuarjhkutznkoxcgeoyngxjzuzgqkzuiuskhgiqgtjykkgyozkroqkznoygtjqtucoluatjznoyyvkiokyubkxnkxkgtjckngjysuuznytgqkyubkxznkxkozjukyzgqkozyzurrnkygojskgtcnorkayotmgjxutkc
oznznkxsgrosgmotmzuyaxbkeznkyozkluxnojjktyahzkxxgtkgthaxtyoysgzzugqrkegloxkotbkyzomgzoutyulloikxluxyaxxkeloxkgtjxkyiaknkoyutkulznkaqytgzoutgrcorjloxkzgizoigrgjboyuxygmxuavulyvkiogroyzulloikxycnugrxkgj
engbkznkyqorryrkgxtzghxugjgtjcnucorrhkzxgototmatozynkygeyznkqotjulzkintowakynkyykktaykjotnuzyvuzygylgxlratmgylxgtikgtjyuaznglxoigcorrhkbozgrotznkaqotznkekgxyzuiuskuaxirosgzkoyingtmotmozyingtmotmhkeutj
xkiumtozoutnkkdvrgotkjcngzaykjzuhkgtotkzuekgxieirkznoyoykbkxeekgxtucckgxknkgjotmzucgxjygtuxznkxtskjozkxxgtkgtirosgzkotznkyuaznkgyzulktmrgtjcoznotznktkdzjkigjkgtjznoycorrhkhayotkyygyayagrjgeotjgeuazsgt
eulznkcorjloxklomnzotmskznujyhkotmxurrkjuazgixuyyznkaqxkreutgzuurhudulyqorrylxusixkgzotmtgzaxgrloxkhxkgqygtjxkjaiotmznklakrrugjulbkmkzgzoutzuykzzotmiutzxurrkjhaxtyjkrohkxgzkregxuatjcorjloxkyzuyzuvznko
xyvxkgjzumkznkxznkecuarjxkjaikznktkkjluxnamkgsuatzyulcgzkxotgjxuamnzgtjxkjaikznktashkxulgvvrogtikytkkjkjutyozkhazznkloxkhxomgjkyatoutygeytkczxgototmgtjzkintowakygxktuzktuamnzuzgiqrkznkxoyotmingrrktmky
ulirosgzkingtmkozygeysuxkixkcygxktkkjkjglzkxekgxyuliazyzngzngbkykktznkruyyulznuaygtjyulloxklomnzkxyyotiksgzzcxgiqznkloxkhxomgjkyatoutymktkxgrykixkzgxeigrrkjluxsuxklatjotmlxusznkmubkxtsktzygeotmxoyotmz
ksvkxgzaxkygtjznkyeyzksgzoiatjkxlatjotmulznkloxkgtjxkyiakykxboikgxkgxkiovkluxjkyzxaizoutznkmubkxtsktzygojozcgymobotmloxkgtjxkyiakgaznuxozokygxuatjhtznoyekgxgtjkgingaznuxozecgyghrkzujkiojkcngzozyvktzoz
utgyvuqkyvkxyutygojznknuskulloikcuxqyiruykrecoznznktgzoutgrloxkinoklyiuatiorgtjktmrgtjgtjcgrkycorjloxkluxaszuiutzotakzuosvxubkuaxxkyvutykzucorjloxkygtjsozomgzkznks

65
input_plaintext.txt Normal file
View File

@ -0,0 +1,65 @@
Firefighters will deploy new techniques learnt in the world's worst wildfire hotspots as climate change raises the risk level in the UK this summer.
Last year's heatwaves saw thousands of fires break out, one even destroying homes at Wennington, east London.
This year has already seen hundreds of grass fires and one of the UK's largest ever has been burning in the Scottish Highlands for the past two weeks.
More fire crews are now training in skills from southern Europe and the US.
Are Europe's wildfires linked to climate change?
Highland wildfire could be largest ever in UK
How wildfires start and how to stop them
Fire chiefs are particularly looking to expand the number of specialist teams trained in "burn suppression" techniques - the deliberate burning of land to keep a fire contained.
At the moment, just five UK units across more than 50 fire and rescue services specialise in the "fighting fire with fire" technique, mostly in moorland areas.
But Chief Fire Officer Paul Hedley, wildfire lead for the National Fire Chiefs Council (NFCC), said more units - including those in services that straddle urban and rural areas - would be trained in new ways of wildfire fighting.
They could then be deployed nationally, in the event of a significant fire, he said.
He added the risk and threat of such major wildfires was "clearly growing in the UK".
"All of this learning from international partners, who are probably still some years ahead of us, is a very sensible way of trying to get us ahead of the curve," he said.
It is hoped a UK-wide training programme will be set up as part of a national action plan drawn up in response to the lessons learnt from last year's blazes.
One of the services leading the way is Surrey Fire and Rescue, which has already dealt with more than 80 wildfires this year.
The most recent wildfire was last month at Frensham Common, near Farnham, a popular beauty spot.
The cause of the 10-hectare fire is not yet known - but the damage is clear to see.
From heathland to desolation
Where once there was rich heathland, home to rare species, including sand lizards, there is now desolation.
When the BBC visited, volunteers from the Amphibian and Reptile Conservation charity were walking the scorched earth, stretched out in a line like a police forensics team, searching for creatures that survived the blaze.
If the immediate impact is shocking, the long-term effects are equally concerning.
"Whilst we can save some of these animals that survived the fire, we lose an awful lot and we lose all that biodiversity. It takes years, if not decades, for that to come back again," explained trustee Howard Inns.
For countryside ranger Darren Hill, who supported firefighters tackling the blaze here, seeing the aftermath, and knowing more wildfires could be on their way, is hard to take.
"To come back and see a site like this, and know I found this species over here and we had smooth snakes over there, it does take its toll," he said.
Meanwhile, using a drone with thermal imaging to survey the site for hidden subterranean burns is Matt Oakley, a fire investigations officer for Surrey Fire and Rescue.
He is one of the UK's national wildfire tactical advisors - a group of specialist officers who already have the skills learnt abroad and who will be training units.
He says the kind of techniques he's seen used in hotspots as far-flung as France and South Africa will be vital in the UK in the years to come.
"Our climate is changing - it's changing beyond recognition," he explained. "What used to be a nine to 12-year cycle, this is every year now.
"We are heading towards a northern Mediterranean climate in the southeast of England within the next decade and this will be business as usual day in, day out,"
Many of the wildfire-fighting methods being rolled out across the UK rely on a 'toolbox' of skills, from creating natural firebreaks and reducing the 'fuel-load' of vegetation to setting controlled burns deliberately around wildfires to stop their spread.
Together they would reduce the need for huge amounts of water in a drought and reduce the number of appliances needed on site.
But the Fire Brigades Union says new training and techniques are not enough to tackle the rising challenges of climate change. It says more crews are needed after years of cuts that have seen the loss of thousands of firefighters since 2010.
Matt Wrack, the Fire Brigades Union's general secretary, called for more funding from the government, saying: "Rising temperatures and the systematic underfunding of the fire and rescue service are a recipe for destruction."
The government said it was giving fire and rescue authorities around £2.6bn this year, and each authority was able to decide what it spent it on.
A spokesperson said: "The Home Office works closely with the National Fire Chiefs Council and England and Wales Wildfire Forum to continue to improve our response to wildfires and mitigate them."

178
main.py Normal file
View File

@ -0,0 +1,178 @@
import math
from collections import *
from string import ascii_lowercase
import re
import data
import random
ALPHABET_ENG = ascii_lowercase
ALPHABET_POL = "aąbcćdeęfghijklłmnńoóprsśtuwyzźż"
letterFrequencyEng = {'e': 12.0,
't': 9.10,
'a': 8.12,
'o': 7.68,
'i': 7.31,
'n': 6.95,
's': 6.28,
'r': 6.02,
'h': 5.92,
'd': 4.32,
'l': 3.98,
'u': 2.88,
'c': 2.71,
'm': 2.61,
'f': 2.30,
'y': 2.11,
'w': 2.09,
'g': 2.03,
'p': 1.82,
'b': 1.49,
'v': 1.11,
'k': 0.69,
'x': 0.17,
'q': 0.11,
'j': 0.10,
'z': 0.07}
def lclear(text):
return re.sub(r'[^a-ząćęłńóśźż]', '', text.lower())
def encrypt(plaintext: str, key: int, alphabet: str):
# plaintext = plaintext.lower().replace(" ", "").replace(",", "").replace(".", "")
plaintext = lclear(plaintext)
alphabet_size = len(alphabet)
ciphertext = ''
for char in plaintext:
char_index = alphabet.index(char)
encrypted_char = alphabet[(key + char_index) % alphabet_size]
ciphertext += encrypted_char
return ciphertext
def decrypt_with_key(ciphertext: str, key: int, alphabet: str):
alphabet_size = len(alphabet)
plaintext = ''
for char in ciphertext:
char_index = alphabet.index(char)
decrypted_char = alphabet[(char_index - key) % alphabet_size]
plaintext += decrypted_char
return plaintext
def difference(text: str, alphabet: str, frequency: dict):
alphabet_size = len(alphabet)
counter = Counter(text)
return sum([abs(counter.get(letter, 0) * 100 / len(text) - frequency[letter]) for letter in
alphabet]) / alphabet_size
def break_cipher(ciphertext: str, alphabet: str, frequency: dict):
lowest_difference = math.inf
encryption_key = 0
alphabet_size = len(alphabet)
for key in range(1, alphabet_size):
current_plaintext = decrypt_with_key(ciphertext, key, alphabet)
current_difference = difference(current_plaintext, alphabet, frequency)
if current_difference < lowest_difference:
lowest_difference = current_difference
encryption_key = key
return encryption_key
def read_file(filename):
counter = 0
longtxt = ''
with open(filename, encoding='utf8') as f:
for line in f:
longtxt += lclear(line.strip())
counter += 1
f.close()
return lclear(longtxt)
def write_to_file(filename, content):
with open(filename, 'w') as f:
current_line_length = 0
for word in content:
word_length = len(word)
while word_length > 0:
if current_line_length + word_length > 200:
f.write('\n')
current_line_length = 0
chars_to_write = min(word_length, 200 - current_line_length)
f.write(word[:chars_to_write] + '')
current_line_length += chars_to_write
word = word[chars_to_write:]
word_length -= chars_to_write
plaintext = read_file('input_plaintext.txt')
ciphertext = encrypt(plaintext, 6, ALPHABET_ENG)
write_to_file('input_cesar.txt', ciphertext)
plaintextPol1 = 'Cześć, oto przykładowy tekst po Polsku ze znakami interpunkcyjnymi;,/$!? i kropkami..'
ciphertextPol1 = encrypt(plaintextPol1, 5, ALPHABET_POL)
ciphertextPol1_key = break_cipher(ciphertextPol1, ALPHABET_POL, data.letterFrequencyPol)
ciphertextPol1_decrypted = decrypt_with_key(ciphertextPol1, ciphertextPol1_key, ALPHABET_POL)
print('\nThe program shows success rates in cracking cesar ciphers\n')
print('Example of long plaintext in Polish: ', plaintextPol1)
print('Encrypted text with key 5: ', ciphertextPol1)
print('Result of ciphertext-only attack: ', ciphertextPol1_decrypted, '\n')
plaintextEng1 = 'Once upon a time I decrypt some texts.'
ciphertextEng1 = encrypt(plaintextEng1, 9, ALPHABET_ENG)
ciphertextEng1_key = break_cipher(ciphertextEng1, ALPHABET_ENG, data.letterFrequencyEng)
ciphertextEng1_decrypted = decrypt_with_key(ciphertextEng1, ciphertextEng1_key, ALPHABET_ENG)
print('Example of long plaintext in English: ', plaintextEng1)
print('Encrypted text with key 9: ', ciphertextEng1)
print('Result of ciphertext-only attack: ', ciphertextEng1_decrypted, '\n\n')
print(
'Now I will check how short of a word can be decrypted using this frequency analyzer.\n')
def check_success_rate(wordlist: list):
correct_counter = 0
for word in wordlist:
ciphertext = encrypt(word, random.randint(1, 26), ALPHABET_ENG)
key = break_cipher(ciphertext, ALPHABET_ENG, data.letterFrequencyEng)
if decrypt_with_key(ciphertext, key, ALPHABET_ENG) == word:
correct_counter += 1
return correct_counter / len(wordlist)
percentage = "{:.0%}".format(check_success_rate(data.eng_3))
print(len(data.eng_3), ' 3-letters long English words. Decryption succes rate: ', percentage, "\n")
percentage = "{:.0%}".format(check_success_rate(data.eng_4))
print(len(data.eng_4), ' 4-letters long English words. Decryption succes rate: ', percentage, "\n")
percentage = "{:.0%}".format(check_success_rate(data.eng_5))
print(len(data.eng_5), ' 5-letters long English words. Decryption succes rate: ', percentage, "\n")
percentage = "{:.0%}".format(check_success_rate(data.eng_6))
print(len(data.eng_6), ' 6-letters long English words. Decryption succes rate: ', percentage, "\n")
percentage = "{:.0%}".format(check_success_rate(data.eng_7))
print(len(data.eng_7), ' 7-letters long English words. Decryption succes rate: ', percentage, "\n")
percentage = "{:.0%}".format(check_success_rate(data.eng_8))
print(len(data.eng_8), ' 8-letters long English words. Decryption succes rate: ', percentage, "\n")
percentage = "{:.0%}".format(check_success_rate(data.eng_9))
print(len(data.eng_9), ' 9-letters long English words. Decryption succes rate: ', percentage, "\n")
print('the Random words were generated using https://randomwordgenerator.com/')
# print('I also uploaded the file with 370105 english words. To pass it as input data change line 62 in file data.py')

370105
words_eng.txt Normal file

File diff suppressed because it is too large Load Diff