From 3dc63370f2be9afe868b79d836613aba24f1a06d Mon Sep 17 00:00:00 2001 From: Neil Smith Date: Fri, 25 Oct 2013 16:15:48 +0100 Subject: [PATCH] Done affine ciphers and breaking them, done challenge 2 --- 2013/2a.plaintext | 9 +++++++++ 2013/2b.plaintext | 1 + cipher.py | 47 ++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 2013/2a.plaintext create mode 100644 2013/2b.plaintext diff --git a/2013/2a.plaintext b/2013/2a.plaintext new file mode 100644 index 0000000..4cb23e7 --- /dev/null +++ b/2013/2a.plaintext @@ -0,0 +1,9 @@ +HARRY, + +I CASHED IN A FAVOUR WITH A FRIEND IN THE SURETE AND HE GOT ME ACCESS TO THE PICTURE. OUR GUYS CAN HAVE FIFTEEN MINUTES WITH HER AFTER CLOSING TIME ON FRIDAY. THEY WON’T ALLOW ANYTHING TOO INVASIVE BUT WE SHOULD GET SOME PICTURES OF THE CANVAS AND FRAME, AND THEY ARE OFFERING TO BRIEF US ON THE PAINTING’S MOVEMENTS DURING THE WAR. + +RECORDS FROM BUCHENWALD WERE SKETCHY BUT WE TRACED THE FAMILY THAT OWNED THE APARTMENT IN MONTMARTRE. AS YOU GUESSED, THEY MOVED THERE WHEN BUCHENWALD OPENED. THE FATHER, DANIEL, WAS JEWISH, THOUGH THEY SEEM TO HAVE MANAGED TO CONCEAL THAT FACT. SOME OF THEM MOVED TO SWITZERLAND, THE OTHERS TO FRANCE, THOUGH THE TEAM DID HEAR REPORTS THAT DANIEL’S BROTHER IN LAW WAS MORE OR LESS FORCED TO TAKE UP WORK AS A GUARD IN THE CAMP SO WE HAVE ANOTHER LINK BETWEEN THE FAMILY AND OUR MYSTERIOUS ARTIST. + +HOW SHE GOT TO FRANCE IS A MYSTERY, TRAVEL FOR A YOUNG JEWISH GIRL WOULD HAVE BEEN HAZARDOUS UNLESS SHE WAS CARRYING OFFICIAL PAPERS. WE WILL TRY TO TRACK DOWN THE BUCHENWALD GUARD THOUGH I DON’T HOLD UP MUCH HOPE. NO ONE WHO DID THAT JOB PUT IT ON THEIR CV AFTERWARDS. + +PHIL diff --git a/2013/2b.plaintext b/2013/2b.plaintext new file mode 100644 index 0000000..26beede --- /dev/null +++ b/2013/2b.plaintext @@ -0,0 +1 @@ +HELMUTS COUSINS ARE I SUPPOSE KIND IN THEIR OWN WAY BUT THERE IS LITTLE WARMTH IN THE KINDNESS I RECEIVE ANNA TRIES TO MAKE ME COMFORTABLE BUT SHE IS AFRAID THE SS OFFICER WHO BRINGS US THE PAINTINGS IS CRUEL AND COWARDLY AND HE BEATS ANNA IF MY WORK IS NOT GOOD ENOUGH HE IS SCARED THAT IF HE BEATS ME HE MIGHT DAMAGE MY HANDS AND TOO SCARED TO BEAT HER HUSBAND DANIEL A BEAR OF A MAN WHO TOWERS OVER HIM IT DOESNT MATTER THE REAL POWER LIES WITH THE BULLY HE COULD HAVE US ALL SHOT AND WE ALL KNOW IT DANIEL SCARES ME TOO BUT ONLY BECAUSE HE REMINDS ME OF HELMUT AND THAT REMINDS ME OF THE CAMP HE NEVER SPEAKS NEVER LOOKS ME IN THE EYE AND NEVER WANTS ANYTHING FROM ME I THINK HE HATES ME FOR BRINGING THE SS TO HIS HOUSE BUT FOR ANNAS SAKE HE BRINGS ME WHAT I NEED WHAT I MOST NEED IS A WAY OUT OF HERE WHEN I AM GONE ANNAS BEATINGS WILL STOP AND MAYBE DANIEL WILL STOP HATING ME BUT I AM WATCHED ALL DAY AND THE HOUSE IS LOCKED AT NIGHT THAT WILL NOT STOP ME FROM TRYING \ No newline at end of file diff --git a/cipher.py b/cipher.py index 7acaf6c..f2c6775 100644 --- a/cipher.py +++ b/cipher.py @@ -7,6 +7,14 @@ with open('count_1l.txt', 'r') as f: (letter, count) = line.split("\t") english_counts[letter] = int(count) +modular_division = [[0]* 26 for i in range(26)] +for i in range(26): + for j in range(26): + t = (i*j) % 26 + # therefore, i = t / j + modular_division[t][j] = i + + def sanitise(text): sanitised = [c.lower() for c in text if c in string.ascii_letters] return ''.join(sanitised) @@ -68,7 +76,29 @@ def affine_cipher_letter(letter, multiplier, shift, one_based=True): else: return letter - +def affine_decipher_letter(letter, multiplier, shift, one_based=True): + if letter in string.ascii_letters: + if letter in string.ascii_lowercase: + alphastart = ord('a') + else: + alphastart = ord('A') + letter_number = ord(letter) - alphastart + if one_based: letter_number +=1 + after_unshift = letter_number - shift + deciphered_letter_number = modular_division[after_unshift % 26][multiplier] + if one_based: deciphered_letter_number -=1 + deciphered_letter = chr(deciphered_letter_number % 26 + alphastart) + return deciphered_letter + else: + return letter + +def affine_cipher_message(message, multiplier, shift, one_based=True): + big_cipher = [affine_cipher_letter(l, multiplier, shift, one_based) for l in message] + return ''.join(big_cipher) + +def affine_decipher_message(message, multiplier, shift, one_based=True): + big_decipher = [affine_decipher_letter(l, multiplier, shift, one_based) for l in message] + return ''.join(big_decipher) def caesar_break(message): @@ -85,3 +115,18 @@ def caesar_break(message): best_fit = fit return best_key +def affine_break(message): + best_key = (0, 0, 0) + best_fit = float("inf") + for multiplier in range(1, 26, 2): + for shift in range(26): + for one_based in [True, False]: + plaintxt = affine_decipher_message(message, multiplier, shift, one_based) + lettertxt = letter_frequencies(plaintxt) + total1 = scale_freq(lettertxt) + total2 = scale_freq(english_counts) + fit = value_diff(total2, total1)c + if fit < best_fit: + best_key = (multiplier, shift, one_based) + best_fit = fit + return best_key -- 2.34.1