Removed cipher challenge files
authorNeil Smith <neil.git@njae.me.uk>
Thu, 7 Jan 2016 16:58:02 +0000 (16:58 +0000)
committerNeil Smith <neil.git@njae.me.uk>
Thu, 7 Jan 2016 16:58:02 +0000 (16:58 +0000)
59 files changed:
2012/1a.ciphertext [deleted file]
2012/1a.plaintext [deleted file]
2012/1b.ciphertext [deleted file]
2012/1b.plaintext [deleted file]
2012/2a.ciphertext [deleted file]
2012/2a.plaintext [deleted file]
2012/2b.ciphertext [deleted file]
2012/2b.plaintext [deleted file]
2012/3a.ciphertext [deleted file]
2012/3a.plaintext [deleted file]
2012/3b.ciphertext [deleted file]
2012/3b.plaintext [deleted file]
2012/4a.ciphertext [deleted file]
2012/4a.plaintext [deleted file]
2012/4b.ciphertext [deleted file]
2012/4b.plaintext [deleted file]
2012/5a.ciphertext [deleted file]
2012/5a.plaintext [deleted file]
2012/5b.ciphertext [deleted file]
2012/5b.plaintext [deleted file]
2012/6a.ciphertext [deleted file]
2012/6a.plaintext [deleted file]
2012/6b.ciphertext [deleted file]
2012/6b.plaintext [deleted file]
2012/7a.ciphertext [deleted file]
2012/7a.plaintext [deleted file]
2012/7b.ciphertext [deleted file]
2012/7b.plaintext [deleted file]
2012/8a.ciphertext [deleted file]
2012/8a.plaintext [deleted file]
2012/8b.ciphertext [deleted file]
2012/8b.plaintext [deleted file]
2013/1a.ciphertext [deleted file]
2013/1a.plaintext [deleted file]
2013/1b.ciphertext [deleted file]
2013/1b.plaintext [deleted file]
2013/2a.ciphertext [deleted file]
2013/2a.plaintext [deleted file]
2013/2b.ciphertext [deleted file]
2013/2b.plaintext [deleted file]
2013/3a.ciphertext [deleted file]
2013/3b.ciphertext [deleted file]
2013/4a.ciphertext [deleted file]
2013/4b.ciphertext [deleted file]
2013/5a.ciphertext [deleted file]
2013/5b.ciphertext [deleted file]
2013/6a.ciphertext [deleted file]
2013/6b.ciphertext [deleted file]
2013/7a.ciphertext [deleted file]
2013/7b.ciphertext [deleted file]
2013/mona-lisa-words.txt [deleted file]
2013/solutions.txt [deleted file]
SIGNED.md [new file with mode: 0644]
cipher-training.sublime-project [new file with mode: 0644]
cipher.py
cipher.sublime-project [deleted file]
cipherbreak.py
language_models.py
segment.py

diff --git a/2012/1a.ciphertext b/2012/1a.ciphertext
deleted file mode 100644 (file)
index c5bd87f..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-UG LMIZ KPIZTMA, 
-
-Q PIDM LMKGXPMZML BPM NQZAB AMKBQWV WN UG CVKTM’A EQTT IVL Q IU LMMXTG AILLMVML IVL XMZXTMFML JG QB. Q PIL PWXML BPIB QB EWCTL MFXTIQV BPM AIL KQZKCUABIVKMA WN PQA LMIBP IVL ITTWE UM BW ZMUMUJMZ PQU EQBP BPM INNMKBQWV Q ZMKITT NZWU UG KPQTLPWWL. WN KWCZAM Q SVME BPIB BQJMZQCA PIL JMMV MVOIOML QV AMKZMB OWDMZVUMVB EWZS XZQWZ BW BPM EIZ, JCB Q PIL ZMNCAML BW JMTQMDM BPIB PM KWCTL PIDM PIL IVGBPQVO BW LW EQBP BPWAM NWCT VME EMIXWVA BPIB AW AKIZZML UG OMVMZIBQWV. Q IU VWB ACZM BPIB Q EIVB BW ZMIL BPM ZMAB WN PQA TMBBMZ BW UM. JMNWZM Q ZMIL QB Q KWCTL VWB PIDM IKKMXBML BPIB PM PIL KWTTIJWZIBML EQBP BPM MVMUG, JCB Q PIL VWB ZMITQHML BPIB PM EIA IKYCIQVBML EQBP PIPV, I NIKB Q ZMIL EQBP LQABIABM, IVL PQA KTIQU BW PIDM UIQVBIQVML BPIB ZMTIBQWVAPQX IB BPM ZMYCMAB WN BPM OWDMZVUMVB QA BPM EWZAB AWZB WN AMTN-RCABQNQKIBQWV. 
-
-Q IU XCHHTML JG BQJMZQCA’A ABZIVOM QVABZCKBQWV BPIB Q APWCTL LMKGXPMZ BPM LWKCUMVB. QB AMMUA I BZQDQITQHQVO, QN VWB BW AIG NZQDWTWCA, ZMYCMAB. QB QA PIZL BW AYCIZM BPQA EQBP BPM ACQKQLM VWBM WN I BZIQBWZ, JCB XMZPIXA Q PIDM JMMV PMZM WV UITBI NWZ BWW TWVO. QB QA UIVG GMIZA AQVKM Q AXMVB BQUM QV BPM KWUXIVG WN NZQMVLA WZ ZMTIBQDMA IVL, BPWCOP Q NQVL BPM AWTQBCLM KWVAWTQVO, QB UISMA UM I XWWZ RCLOM WN KPIZIKBMZ. 
-
-Q IU AWZZG BW AIG BPIB Q IU IAPIUML WN UG CVKTM IVL Q PIDM LMKQLML VWB BW KWVBQVCM EQBP BPQA CVXTMIAIVB OIUM. Q EQTT PIDM VWBPQVO UWZM BW LW EQBP PQU, JCB Q AMM VW VMML BW ILL BW BPM MUJIZZIAAUMVB WN PQA NZQMVLA IVL NIUQTG IVL Q EWCTL IAS GWC BW UIQVBIQV BPM OZMIBMAB LQAKZMBQWV QV GWCZ KWUUCVQKIBQWVA KWVKMZVQVO BPQA LQAIXXWQVBQVO LWKCUMVB, IA Q PIDM LWVM QV MVKZGXBQVO BPQA TMBBMZ. 
-
-GWCZA AQVKMZMTG, 
-
-VQKPWTIA 
\ No newline at end of file
diff --git a/2012/1a.plaintext b/2012/1a.plaintext
deleted file mode 100644 (file)
index ce786bd..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-My Dear Charles, 
-
-I have decyphered the first section of my Uncle’s will and I am deeply saddened and perplexed by it. I had hoped that it would explain the sad circumstances of his death and allow me to remember him with the affection I recall from my childhood. Of course I knew that Tiberius had been engaged in secret government work prior to the War, but I had refused to believe that he could have had anything to do with those foul new weapons that so scarred my generation. I am not sure that I want to read the rest of his letter to me. Before I read it I could not have accepted that he had collaborated with the enemy, but I had not realized that he was acquainted with Hahn, a fact I read with distaste, and his claim to have maintained that relationship at the request of the government is the worst sort of self-justification. 
-
-I am puzzled by Tiberius’s strange instruction that I should decypher the document. It seems a trivializing, if not to say frivolous, request. It is hard to square this with the suicide note of a traitor, but perhaps I have been here on Malta for too long. It is many years since I spent time in the company of friends or relatives and, though I find the solitude consoling, it makes me a poor judge of character. 
-
-I am sorry to say that I am ashamed of my Uncle and I have decided not to continue with this unpleasant game. I will have nothing more to do with him, but I see no need to add to the embarrassment of his friends and family and I would ask you to maintain the greatest discretion in your communications concerning this disappointing document, as I have done in encrypting this letter. 
-
-Yours sincerely, 
-
-Nicholas 
\ No newline at end of file
diff --git a/2012/1b.ciphertext b/2012/1b.ciphertext
deleted file mode 100644 (file)
index ec0ba85..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-V, GVOREVHF UNJXFZBBE, ORVAT BS FBHAQ ZVAQ, UREROL ERIBXR NYY BGURE JVYYF NAQ PBQVPVYF V ZNL CERIVBHFYL UNIR RKRPHGRQ. GUVF QBPHZRAG VF ZL SVANY QRPYNENGVBA BS VAGRAG SBE GUR QVFCBFNY BS NAL NFFRGF GUNG ERZNVA HAQRE ZL BJAREFUVC NAQ PBAGEBY, NAQ VF ZL SVANY BCCBEGHAVGL GB FRG GUR ERPBEQ FGENVTUG PBAPREAVAT GUR NJSHY RIRAGF BS GUR YNFG SVSGRRA LRNEF. VG VF NYFB ZL SVANY YRGGRE GB LBH, QRNE AVPUBYNF. 
-V PBHYQ ORTVA VA NAL AHZORE BS JNLF, OHG CREUNCF V FUBHYQ FGNEG ONPX VA AVARGRRA GUVEGRRA, JURA V ERPRVIRQ NA VAIVGNGVBA SEBZ CEBS. BGGB UNUA GB NGGRAQ N ZRRGVAT BS GUR QRHGFPURA PURZVFPURA TRFRYYFPUNSG MH OREYVA. GUR FBPVRGL JNF GB OR NQQERFFRQ OL CEBS. RZVYR SVFPURE BA UVF JBEX PBAPREAVAT PBEEBFVIR TNFRF NAQ GURVE RSSRPGF BA GUR UHZNA OBQL. GUVF JNF N FHOWRPG GUNG V SBHAQ CREFBANYYL QVFGNFGRSHY OHG CEBSRFFVBANYYL BS CEBSBHAQ VZCBEGNAPR, FVAPR V BJARQ NAQ BCRENGRQ N AHZORE BS SNPGBEVRF ZNAHSNPGHEVAT PURZVPNY CEBQHPGF, NAQ V GBBX GUR FNSRGL BS GUBFR CYNAGF NAQ ZL RZCYBLRRF IREL FREVBHFYL. GUR IVFVG JNF CEBQHPGVIR NAQ V YRNEARQ N YBG, CREUNCF ZBER GUNA JNF TBBQ SBE ZR. 
-BA ZL ERGHEA V JNF ZRG SEBZ GUR OBNG VA FBHGUNZCGBA OL GJB TRAGYRZRA SEBZ NA BETNAVMNGVBA GURL PNYYRQ IREBAN - IBYHAGRRE RAGRECEVFRF, EBLNY BEQANAPR NFFBPVNGVBA. GUVF GBC-FRPERG TBIREAZRAG NTRAPL JNF ERFCBAFVOYR SBE ERPEHVGVAT YRNQREF BS GUR ZNAHSNPGHEVAT VAQHFGEVRF GB FHCCBEG GUR QVCYBZNGVP NAQ ZVYVGNEL RSSBEGF BS GUR SBERVTA BSSVPR, NAQ GURL NFXRQ ZR GB CEBIVQR GURZ JVGU N ERCBEG BA SVFPURE’F JBEX. V UNQ QRRC ERFREINGVBAF, OHG V ERPBTAVFRQ GUR TEBJVAT GUERNG BS JNE NAQ V JNF VAPERNFVATYL NSENVQ GUNG PURZVPNY JRNCBAF ZVTUG OR HFRQ. VA NAL PNFR GUR GJB TRAGYRZRA, JUB, SBE BOIVBHF ERNFBAF, V AVPXANZRQ INYRAGVAR NAQ CEBGRHF, JRER IREL CREFHNFVIR. V YRNEARQ YNGRE GUNG GURL ORYBATRQ GB N TEBHC JVGUVA IREBAN XABJA NF GUR SNOHYVFGF, QRQVPNGRQ GB JUNG JR JBHYQ ABJ PNYY VASBEZNGVBA JNESNER. GURL JRER FXVYYRQ CEBCBARAGF BS CEBCNTNAQN NAQ ZVFVASBEZNGVBA, NAQ ZNFGREF BS N JUBYR CNABCYL BS ZRGUBQF BS CREFHNFVBA. 
-XABJVAT BS LBHE BJA QERNQSHY RKCREVRAPRF V NZ NFUNZRQ GB NQZVG GUNG V SBHAQ ZLFRYS NGGENPGRQ OL GUR ARJ PUNYYRATRF BS JBEX JVGU GUR NTRAPL. NG GUNG FGNTR V JNF NYZBFG RAGVERYL PBAPREARQ JVGU VAIRFGVTNGVAT ZRGUBQF BS CEBGRPGVBA NTNVAFG GUR ENINTRF BS PUYBEVAR NAQ ZHFGNEQ TNF NGGNPXF NAQ V JNF PBAIVAPRQ GUNG ZL JBEX PBHYQ FNIR YVIRF. V ERQVFPBIRERQ N YBIR SBE GUR QNVYL EVGHNYF BS GUR YNOBENGBEL NAQ RAWBLRQ GUR PYBFR PBYYRTVNY NGZBFCURER VA GUR FRPERG JBEYQ BS IREBAN. NG GURVE ERDHRFG V ZNVAGNVARQ ZL PBAGNPGF JVGU GUR TREZNA FPVRAGVFGF, PBAIVAPRQ GUNG QVNYBT ZVTUG CERIRAG GUR SHYY UBEEBEF BS GUR PBZVAT JNE, OHG VA WHAR AVARGRRA SBHEGRRA N PBAIREFNGVBA JVGU I NAQ C YRQ GB ZR GB ERNYVFR GUNG, OL CEBIVQVAT BHE NEZL JVGU CEBGRPGVBA SEBZ GUR RSSRPGF BS GURFR GREEVOYR JRNCBAF, ZL ERFRNEPU PBHYQ CERPVCVGNGR GURVE HFR OL BHE BJA FVQR. 
-SEVTUGRARQ OL GUVF NAQ OL GUR TEBJVAT CBYVGVPNY VAFGNOVYVGL VA RHEBCR V ERFVTARQ VZZRQVNGRYL SEBZ GUR NTRAPL NAQ ERGHEARQ GB GUR YNOBENGBEVRF BS GUR PBZCNAL V UNQ SBHAQRQ. GUR GJB TRAGYRZNA BS IREBAN JRER, GB FNL GUR YRNFG, HAUNCCL, OHG V PBAIVAPRQ GURZ GUNG ZL SNPGBEVRF JRER FGVYY IVGNY GB OEVGVFU RPBABZVP VAGRERFGF NAQ SBE N JUVYR GURL YRSG ZR NYBAR. GUVF FGBEL ZVTUG UNIR RAQRQ GURER VS V UNQ ABG ERPRVIRQ GUR GRYRTENZ SEBZ LBHE ZBGURE BA WNAHNEL SVSGU, AVARGRRA SVSGRRA. 
\ No newline at end of file
diff --git a/2012/1b.plaintext b/2012/1b.plaintext
deleted file mode 100644 (file)
index b319044..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-Plaintext
-
-I, Tiberius Hawksmoor, being of sound mind, hereby revoke all other wills and codicils I may previously have executed. This document is my final declaration of intent for the disposal of any assets that remain under my ownership and control, and is my final opportunity to set the record straight concerning the awful events of the last fifteen years. It is also my final letter to you, dear Nicholas. 
-I could begin in any number of ways, but perhaps I should start back in Nineteen Thirteen, when I received an invitation from Prof. Otto Hahn to attend a meeting of the Deutschen chemischen Gesellschaft zu Berlin. The society was to be addressed by Prof. Emile Fischer on his work concerning corrosive gases and their effects on the human body. This was a subject that I found personally distasteful but professionally of profound importance, since I owned and operated a number of factories manufacturing chemical products, and I took the safety of those plants and my employees very seriously. The visit was productive and I learned a lot, perhaps more than was good for me. 
-On my return I was met from the boat in Southampton by two gentlemen from an organization they called VERONA - Volunteer Enterprises, Royal OrdNance Association. This top-secret government agency was responsible for recruiting leaders of the manufacturing industries to support the diplomatic and military efforts of the Foreign Office, and they asked me to provide them with a report on Fischer’s work. I had deep reservations, but I recognised the growing threat of war and I was increasingly afraid that chemical weapons might be used. In any case the two gentlemen, who, for obvious reasons, I nicknamed Valentine and Proteus, were very persuasive. I learned later that they belonged to a group within VERONA known as the Fabulists, dedicated to what we would now call information warfare. They were skilled proponents of propaganda and misinformation, and masters of a whole panoply of methods of persuasion. 
-Knowing of your own dreadful experiences I am ashamed to admit that I found myself attracted by the new challenges of work with the agency. At that stage I was almost entirely concerned with investigating methods of protection against the ravages of Chlorine and Mustard Gas attacks and I was convinced that my work could save lives. I rediscovered a love for the daily rituals of the laboratory and enjoyed the close collegial atmosphere in the secret world of VERONA. At their request I maintained my contacts with the German scientists, convinced that dialog might prevent the full horrors of the coming war, but in June Nineteen Fourteen a conversation with V and P led to me to realise that, by providing our army with protection from the effects of these terrible weapons, my research could precipitate their use by our own side. 
-Frightened by this and by the growing political instability in Europe I resigned immediately from the agency and returned to the laboratories of the company I had founded. The two gentleman of VERONA were, to say the least, unhappy, but I convinced them that my factories were still vital to British economic interests and for a while they left me alone. This story might have ended there if I had not received the telegram from your mother on January Fifth, Nineteen Fifteen. 
\ No newline at end of file
diff --git a/2012/2a.ciphertext b/2012/2a.ciphertext
deleted file mode 100644 (file)
index 4328c08..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-TF KLHY UPJOVSHZ 
-
-P RUVD OVD ZOVJRPUN AOLZL YLCLSHAPVUZ TBZA OHCL ILLU MVY FVB, HUK NPCLU FVBY WHZA LEWLYPLUJLZ UV VUL JVBSK ISHTL FVB MVY AOL KLJPZPVU FVB OHCL THKL AV ABYU FVBY IHJR VU FVBY BUJSL’Z ZAYHUNL YLXBLZA. UVULAOLSLZZ, DOPSL DL HYL ZAPSS BUZBYL VM AOL WBYWVZL VM AOL KVJBTLUA P AOPUR PA DVBSK IL H TPZAHRL AV YLSPUXBPZO AOL AHZR OL OHZ ZLA FVB. 
-
-P TBZA HKTPA AOHA P MPUK PA HSTVZA PTWVZZPISL AV YLJVUJPSL FVBY JBYYLUA CPLD VM APILYPBZ DPAO AOL THU DL IVAO RULD, HUK ZV P OHCL AHRLU AOL SPILYAF VM KLJPWOLYPUN AOL ULEA JOHWALY VM OPZ DPSS TFZLSM, PU AOL OVWL VM YLCLHSPUN TVYL PUMVYTHAPVU AOHA TPNOA OLSW BZ AV BUKLYZAHUK OPT ILAALY. P RUVD AOHA PAZ JVUALUAZ DPSS UVA LUAPYLSF YLHZZBYL FVB, IBA P AOPUR FVB VDL PA AV FVBYZLSM, PM UVA AV APILYPBZ, AV YLHK VU. 
-
-PU AOL TLHUAPTL HSSVD TL AV ZOHYL ZVTL YLTHYRZ JVUJLYUPUN AOL DPSS. AOYVBNOVBA TF WYVMLZZPVUHS SPML, P OHCL OHK AOL TPZMVYABUL AV YLHK H UBTILY VM MPUHS SLAALYZ DYPAALU IF TLU KYPCLU AV ZLSM KLZAYBJAPVU HUK P TBZA ALSS FVB AOHA AOPZ OHZ HU LUAPYLSF KPMMLYLUA MLLS AV PA. AOLYL PZ H MYHURULZZ DOPJO ZBNNLZAZ AOHA APILYPBZ PZ TVYL JVUJLYULK MVY AOL AYBAO AV IL RUVDU AOHU OL PZ AV WYVALJA OPZ YLWBAHAPVU. P OHCL H MLLSPUN AOHA APILYPBZ BUKLYZAVVK AOHA AOPZ DVBSK IL OHYK MVY FVB, IBA DOLAOLY FVB SPRL PA VY UVA P HT JLYAHPU AOHA FVB DPSS SLHYU AOL AYBAO PM FVB JVTWSLAL AOL JOHSSLUNL OL OHZ SLMA FVB. 
-
-FVB ZHPK AOHA DL ZOVBSK THPUAHPU AOL NYLHALZA KPZJYLAPVU, IBA P HT ZBYL APILYPBZ DVBSK YLTPUK FVB AOHA H JHLZHY ZOPMA JFWOLY JVBSK UVA WVZZPISF WYVCPKL FVB DPAO AOL KLNYLL VM ZLJBYPAF FVB YLXBPYL. P ZBNNLZA AOHA FVB TPNOA MVSSVD APILYPBZ’Z SLHK HUK BZL ZVTLAOPUN TVYL ZLJBYL SPRL HU HMMPUL ZOPMA JFWOLY MVY FVBY YLWSF. 
-
-FVBYZ, 
-
-
-JOHYSLZ
\ No newline at end of file
diff --git a/2012/2a.plaintext b/2012/2a.plaintext
deleted file mode 100644 (file)
index 92f8c1f..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-My dear Nicholas 
-
-I know how shocking these revelations must have been for you, and given your past experiences no one could blame you for the decision you have made to turn your back on your uncle’s strange request. Nonetheless, while we are still unsure of the purpose of the document I think it would be a mistake to relinquish the task he has set you. 
-
-I must admit that I find it almost impossible to reconcile your current view of Tiberius with the man we both knew, and so I have taken the liberty of deciphering the next chapter of his will myself, in the hope of revealing more information that might help us to understand him better. I know that its contents will not entirely reassure you, but I think you owe it to yourself, if not to Tiberius, to read on. 
-
-In the meantime allow me to share some remarks concerning the will. Throughout my professional life, I have had the misfortune to read a number of final letters written by men driven to self destruction and I must tell you that this has an entirely different feel to it. There is a frankness which suggests that Tiberius is more concerned for the truth to be known than he is to protect his reputation. I have a feeling that Tiberius understood that this would be hard for you, but whether you like it or not I am certain that you will learn the truth if you complete the challenge he has left you. 
-
-You said that we should maintain the greatest discretion, but I am sure Tiberius would remind you that a Caesar shift cypher could not possibly provide you with the degree of security you require. I suggest that you might follow Tiberius’s lead and use something more secure like an affine shift cypher for your reply. 
-
-Yours, 
-
-
-Charles
\ No newline at end of file
diff --git a/2012/2b.ciphertext b/2012/2b.ciphertext
deleted file mode 100644 (file)
index ea3676a..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-CUF YFRX CULC BDH ULA QFFY IZVJFA HI QB TZOZCLSB IDOZVF CSBZYP CD MDOHYCFFS KDS BDHS ODVLO SFPZTFYC KZOOFA TF RZCU ASFLA. BDH RFSF YDC LODYF, Z OLCFS TFC TLYB HYAFSLPF QDBX RUD ULA AFVFZMFA CUF SFVSHZCZYP XFSPFLYCX LYA TLAF CUFZS RLB CD CUF QLCCOFKZFOAX DK KSLYVF LYA QFOPZHT, QHC BDHS VDHSLPF XULTFA TF ZYCD EDZYZYP CUF KZPUC TBXFOK. 
-
-LC CULC CZTF Z ULA DYOB EHXC QFPHY CD UFLS XCDSZFX DK CUF TZXFSB DK CSFYVU RLSKLSF QHC ZC RLX VOFLS CD TLYB DK HX CULC CUZX RLX L YFR JZYA DK RLS, DYF ZY RUZVU CFVUYDODPB RDHOA IOLB L VFYCSLO SDOF. CUZX KLVC RLX YDC ODXC DY TB FSXCRUZOF FTIODBFSX RUD RFSF NHZVJ CD OFLSY CULC Z ULA EDZYFA HI LYA CD TB XHSISZXF CUF CRD PFYCOFTFY KSDT MFSDYL TFC TF LX Z AZXFTQLSJFA DY CUF VDYCZYFYC RZCU L CUDHXLYA DCUFS YFR SFVSHZCX. Z RLX CLJFY CD L VULCFLH KDS QSZFKZYP DY CUF PFSTLY AFMFODITFYC DK PLX RFLIDYX, LYA DY CUF CRFYCB KZSXC DK LISZO YZYFCFFY KZKCFFY Z RLX XFYC QB CSLZY CD EDZY CUF XFVDYA LSTB XFVCDS ZY CUF BISFX XLOZFYC LC XC EHOZFY. 
-
-CUF KDOODRZYP ALB Z RLX ZYCSDAHVFA CD CUF KHOO UDSSDS DK TDAFSY RLSKLSF. LC KZMF D’VODVJ CUF OFLA IZIFX OLZA DMFS CUF FAPF DK CUF PFSTLY CSFYVUFX UZXXFA LYA L TZXC SDOOFA CDRLSAX HX LVSDXX CUF DIFY OLYA. ZC RLX BFOODRZXU-PSFFY, L UFOOZXU, XHOIUHSDHX ULGF, LYA CUF FKKFVCX RFSF LOTDXC ZYXCLYCLYFDHX. MFSDYL ULA LYCZVZILCFA CUF LCCLVJ LYA TB DSAFSX RFSF CD SFVDSA TB DQXFSMLCZDYX DY CUF AFIODBTFYC DK CUF RFLIDY. Z OFLSYFA OLCFS CULC CUF MLOMFX RFSF DIFY KDS EHXC KZMF TZYHCFX QFKDSF CUF PLX VBOZYAFSX RFSF FTICB LYA CUF PLX RLX QODRY QB L PFYCOF YDSCUFSY QSFFGF LC LQDHC KZMF TZOFX LY UDHS. QHC CUF FKKFVCX RFSF KFOC KDS UDHSX LKCFSRLSAX, LYA CUF OFZXHSFOB ILVF DK CUF QZOODRZYP VODHA QFOZFA ZCX AFXCSHVCZMF IDRFS LX ZC ASZKCFA LODYP L XFVCZDY DK CUF CSFYVUFX LC OFLXC L ULOK TZOF ZY OFYPCU. 
-
-CUF PLX OFKC TLYB XHSMZMDSX HYLQOF CD XIFLJ, LYA CUZX ZYVSFLXFA CUF ILYZV, FXIFVZLOOB LTDYP CUF BDHYPFS CSDDIX. CUDXF RUD RFSF YDC DMFSRUFOTFA QB CUF VUDJZYP VUODSZYF RZCUASFR CD QDFXZYPUF, QHC KFLS DK CUF CFSSZKBZYP YFR RFLIDY XFFIFA CUSDHPU CUF OZYFX LYA CULC IDXZCZDY CDD RLX XDDY ODXC. 
-
-RUZOF DCUFS MFSDYL LPFYCX VDYCZYHFA CD CLJF DQXFSMLCZDYX LVSDXX CUF QLCCOFKZFOA Z RLX XFYC CD CUF SFLS CD FWLTZYF CUF XHSMZMDSX, LYA CD SFVDSA CUF FKKDSCX DK CUF TFAZVX CD LOOFMZLCF CUF XDOAZFSX’ XHKKFSZYP.
\ No newline at end of file
diff --git a/2012/2b.plaintext b/2012/2b.plaintext
deleted file mode 100644 (file)
index 8868a59..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-The news that you had been picked up by Military Police trying to volunteer for your local regiment filled me with dread. You were not alone, I later met many underage boys who had deceived the recruiting sergeants and made their way to the battlefields of France and Belgium, but your courage shamed me into joining the fight myself. 
-
-At that time I had only just begun to hear stories of the misery of trench warfare but it was clear to many of us that this was a new kind of war, one in which technology would play a central role. This fact was not lost on my erstwhile employers who were quick to learn that I had joined up and to my surprise the two gentlemen from VERONA met me as I disembarked on the continent with a thousand other new recruits. I was taken to a chateau for briefing on the German development of gas weapons, and on the twenty first of April nineteen fifteen I was sent by train to join the Second Army sector in the Ypres Salient at St Julien. 
-
-The following day I was introduced to the full horror of modern warfare. At five o’clock the lead pipes laid over the edge of the German trenches hissed and a mist rolled towards us across the open land. It was yellowish-green, a hellish, sulphurous haze, and the effects were almost instantaneous. VERONA had anticipated the attack and my orders were to record my observations on the deployment of the weapon. I learned later that the valves were open for just five minutes before the gas cylinders were empty and the gas was blown by a gentle northern breeze at about five miles an hour. But the effects were felt for hours afterwards, and the leisurely pace of the billowing cloud belied its destructive power as it drifted along a section of the trenches at least a half mile in length. 
-
-The gas left many survivors unable to speak, and this increased the panic, especially among the younger troops. Those who were not overwhelmed by the choking chlorine withdrew to Boesinghe, but fear of the terrifying new weapon seeped through the lines and that position too was soon lost. 
-
-While other VERONA agents continued to take observations across the battlefield I was sent to the rear to examine the survivors, and to record the efforts of the medics to alleviate the soldiers’ suffering.
\ No newline at end of file
diff --git a/2012/3a.ciphertext b/2012/3a.ciphertext
deleted file mode 100644 (file)
index 19b7e9f..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-TD SVJI PEJIQVL, 
-
-JO DZRI RIBHWB H JT PZWOHWRHWB OZ SVPDCEVI TD RWPQV’L XHQQ. EHL LOJOVTVWO OEJO “OEV SJWBVI SHS WZO VWS XHOE OEV XJI” HL LZTVXEJO JQJITHWB. XJL HO EHL HWOVWOHZW OZ LRBBVLO OEJO H JT JO LZTV IHLN? PZRQS EHL JPOHZWL SRIHWB OEV XJI IVJQQD MV CZLHWB J SJWBVI OZ TV JYOVI JQQ OEHL OHTV? HO HL PQVJI OEJO XV XHQQ EJUV OZ PZTCQVOV OEV SVPIDCOHZW HY XV JIV OZ RWSVILOJWS. 
-
-H SHS WZO VWPZRWOVI UVIZWJ SRIHWB OEV XJI, JWS EJUV EVJIS WZOEHWB JMZRO HO SRIHWB TD VAHQV EVIV ZW TJQOJ, MRO H OEHWN HO THBEO MV OHTV OZ TJNV SHLPIVOV VWFRHIHVL JMZRO HO HW QZWSZW. XZRQS DZR ZMQHBV TV HW OEHL? 
-
-ZWV ZOEVI OEHWB. JQTZLO PVIOJHWQD H JT KRTCHWB JO LEJSZXL, MRO TD QJWSQJSD IVTJINVS OEJO ZUVI OEV QJLO XVVN ZI LZ LEV EJL WZOHPVS OXZ TVW QZHOVIHWB HW OEV WVHBEMZRIEZZS ZY TD JCJIOTVWO. H PJWWZO MVQHVUV OEJO OEHL HL PZWWVPOVS XHOE TD RWPQV’L XHQQ, MRO EHL XJIWHWB EJL JQJITVS TV JWS H EJUV VWBJBVS OEV JLLHLOJWPV ZY J QZPJQ SVOVPOHUV OZ NVVC XJOPE. 
-
-H OJNV DZRI CZHWO JMZRO LVPRIHWB ZRI PZTTRWHPJOHZWL. OHMVIHRL HL PQVJIQD TZIV PZWPVIWVS OZ LVPRIV OEVLV QJOVI LVPOHZWL ZY OEV SZPRTVWO JL XVQQ, JWS H EJS OZ XZIN EJIS OZ MIVJN OEV NVDXZIS PDCEVI EV RLVS EVIV. IVORIWHWB OZ OEV XJIOHTV PZWUVWOHZW ZY YHUV QVOOVI MQZPNL IVJQQD SZVL JSS OZ OEV LVPRIHOD ZY OEV OVAO, JWS H EJS OZ PJIID ZRO YIVFRVWPD JWJQDLHL ZW OEHL LVPOHZW ZY OEV XHQQ. H LRBBVLO OEJO HW OEV YRORIV XV OZZ RLV OEV XJIOHTV PZWUVWOHZW. H OEHWN OEJO XHOE OEHL CIVPJROHZW OEV JYYHWV LEHYO PDCEVI LEZRQS JYYZIS RL LRYYHPHVWO LVPRIHOD HW ZRI QVOOVIL OZ ZWV JWZOEVI. 
-
-DZRIL, 
-
-WHPEZQJL 
\ No newline at end of file
diff --git a/2012/3a.plaintext b/2012/3a.plaintext
deleted file mode 100644 (file)
index cf16276..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-My dear Charles, 
-
-At your urging I am continuing to decypher my Uncle’s will. His statement that “the danger did not end with the war” is somewhat alarming. Was it his intention to suggest that I am at some risk? Could his actions during the war really be posing a danger to me after all this time? It is clear that we will have to complete the decryption if we are to understand. 
-
-I did not encounter VERONA during the war, and have heard nothing about it during my exile here on Malta, but I think it might be time to make discrete enquiries about it in London. Would you oblige me in this? 
-
-One other thing. Almost certainly I am jumping at shadows, but my landlady remarked that over the last week or so she has noticed two men loitering in the neighbourhood of my apartment. I cannot believe that this is connected with my Uncle’s will, but his warning has alarmed me and I have engaged the assistance of a local detective to keep watch. 
-
-I take your point about securing our communications. Tiberius is clearly more concerned to secure these later sections of the document as well, and I had to work hard to break the keyword cypher he used here. Returning to the wartime convention of five letter blocks really does add to the security of the text, and I had to carry out frequency analysis on this section of the will. I suggest that in the future we too use the wartime convention. I think that with this precaution the affine shift cypher should afford us sufficient security in our letters to one another. 
-
-Yours, 
-
-Nicholas 
\ No newline at end of file
diff --git a/2012/3b.ciphertext b/2012/3b.ciphertext
deleted file mode 100644 (file)
index c5d4a88..0000000
+++ /dev/null
@@ -1 +0,0 @@
-IVEEU UEOIC UIVES PHPII POYCB ACGPZ ELPHO PIPHI GCDVW OPBTI VESEB EGPZH CKEGG EPOIE TIEGG WUWET IVPII VEUGC BIZWB EDCHW IWCBH LCJZT RGEPY JDIVE NHEBI NCJBS CUUWO EGHIC VCZTI VEZWB EPBTD GCHEO JIETT EHEGI EGHLW IVUEG COWIN WIVCJ SVIWV PTHEE BIVEL CGHII VPILP GOCJZ TCUUE GWBIV EVCHD WIPZH IGEPI WBSIV EIEGG WUWET KWOIW AHCUI VESPH RJIIV EUWGW BSHFJ PTHLE GELCG HEPBT WLPHH EBIRN KEGCB PICLW IBEHH CBEWG EPZWQ EBCLI VPIIV EWGWB IEBIW CBLPH ICUGW SVIEB AEANG EDCGI HCBIV EUWGH ISPHP IIPOY APTEO ZEPGA NZCPI VWBSU CGIVW HBELI NDECU LPGUP GEPBT IVENB EETET ICUWB TLPNH ICDGE HHJGE AEICL CGYCB IVETE KEZCD AEBIC UCJGC LBLEP DCBIV ENCJB SHJRP ZIEGB VPTUZ ETIVE IGEBO VEHPH IVESP HGCZZ ETPZC BSIVE AVEVP TJGSE TIVEC IVEGH ICGJB ICCPB TIVPI PTTET ICVWH SJWZI WBIVE ENEHC UIVEO CJGIA PGIWP ZVELP HHEBI ICIVE UWGWB SHFJP TPBTK EGCBP OVCHE ICJHE VWHTE PIVPH PLPGB WBSIC AEIVE WGDZP BAWSV IVPKE RPOYU WGETW UWVPT OVCHE BICRZ PAECJ GSEBE GPZHU CGIVW HHPKP SEIGE PIAEB ICUNC JBSPB TUGWS VIEBE TAEBR JIWBH IEPTW BANPB SEGUC ZZCLW BSIVE PIIPO YPIND GEHWO VCHEI CRZPA EIVEE BEANU CGIVW HTEPI VICCP BTUWB PZZNP SGEET ICZEP TPIEP ALCGY WBSCB SPHLE PDCBH WOPBI UCGSW KEANH EZUUC GLVPI VPDDE BETZP IEGPB TWIWH OZEPG IVPIH IPBTW BSRNI VEUWG WBSHF JPTWB IVEOC ZTTPL BWAPT EIVEL CGHIT EOWHW CBCUA NZWUE IVENC JBSAP BHICC TPZCB EPBTR GPKEP BTVEG EAWBT ETAEC UNCJL EVPTH ICDDE TNCJU GCAXC WBWBS IVEPG ANCBO ERJIH CCBNC JLCJZ TREHW MIEEB PBTLE LCJZT BCIRE PRZEI CDGEK EBINC JXCWB WBSIV EGESW AEBII VEBWO CBKWB OETAN HEZUI VPIRN VPHIE BWBSI VEEBT ICIVE LPGWL CJZTH PKEAP BNZWK EHPBT WAWSV IHPKE NCJPZ ZHWTE HWBIV PIIEG GWRZE OCBUZ WOILE GEEBS PSETW BPTEH DEGPI EHEPG OVUCG PBELL EPDCB ICRGE PYIVE TEPTZ NHIPZ EAPIE CUIGE BOVLP GUPGE RJIEK EBWUI VWBSH VPTIJ GBETC JITWU UEGEB IZNWI LCJZT REHIW ZZVPG TICHP NIVPI WAPTE IVEGW SVITE OWHWC BIVPI ACGBW BSWLW ZZJBT EGHIP BTWUN CJOPB IUCGS WKEAE RJIPH NCJLW ZZZPI EGHEE IVWBS HLEGE ICREO CAEUP GACGE OCADZ WOPIE TPBTT PBSEG CJHUC GJHRC IVPBT WPAHC GGNIC HPNIV PIIVE TPBSE GTWTB CIEBT LWIVI VELPG
\ No newline at end of file
diff --git a/2012/3b.plaintext b/2012/3b.plaintext
deleted file mode 100644 (file)
index 064e0fd..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-The effect of the gas attack on morale was catastrophic and the generals over-reacted. Terrified that the front line positions would break up they sent young officers to hold the line and prosecuted deserters with ferocity. I thought I had seen the worst that war could offer in the hospitals treating the terrified victims of the gas, but the firing squads were worse, and I was sent by VERONA to witness one. I realize now that their intention was to frighten me. My reports on the first gas attack made clear my loathing for this new type of warfare and they needed to find ways to pressure me to work on the development of our own weapon. 
-
-The young subaltern had fled the trenches as the gas rolled along them. He had urged the others to run too, and that added to his guilt in the eyes of the court martial. He was sent to the firing squad and VERONA chose to use his death as a warning to me. Their plan might have backfired if I had chosen to blame our generals for this savage treatment of young and frightened men, but instead, in my anger following the attack at Ypres, I chose to blame the enemy for this death too and finally agreed to lead a team working on gas weapons. 
-
-I can’t forgive myself for what happened later, and it is clear that, standing by the firing squad in the cold dawn, I made the worst decision of my life. The young man stood alone and brave and he reminded me of you. We had stopped you from joining the army once, but soon you would be sixteen and we would not be able to prevent you joining the regiment then. I convinced myself that by hastening the end to the war I would save many lives, and I might save you. 
-
-All sides in that terrible conflict were engaged in a desperate search for a new weapon to break the deadly stalemate of trench warfare but even if things had turned out differently it would be still hard to say that I made the right decision that morning. I will understand if you can’t forgive me, but as you will later see things were to become far more complicated and dangerous for us both and I am sorry to say that the danger did not end with the war. 
\ No newline at end of file
diff --git a/2012/4a.ciphertext b/2012/4a.ciphertext
deleted file mode 100644 (file)
index 0a4d99b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-SEJKG XTOIN URGYE UAXAT IRKYX KBKRG ZOUTI UTIKX TOTMN OYCUX QUTSK ZKUXU RUMEH KMOTY ZUKDV RGOTN OYSUB KOTZU SGZNK SGZOI YLURR UCOTM ZNKCG XOGRC GEYCU TJKXK JCNEN KNGJR KLZZN KRGHU XGZUX OKYGT JLGIZ UXOKY HAZNO YKDVK XOKTI KULOT JAYZX ESAYZ NGBKY UAXKJ GYNKY GCZNK YALLK XOTMZ NGZTK COTBK TZOUT YCKXK IGAYO TMUTZ NKHGZ ZRKLO KRJYO NGBKT UQTUC RKJMK ULZNK CUXQN KYAHY KWAKT ZREJO JGTJZ NKLKC VKUVR KONGB KGYQK JNGBK HKKTY ZXGTM KREAT GHRKU XVKXN GVYXK RAIZG TZZUZ KRRSK GTEZN OTMUL BGRAK ZNKJK ZKIZO BKEUA NOXKJ ZURUU QOTZU ZNKSE YZKXO UAYLO MAXKY UTZNK OYRGT JNGYI UTZGI ZKJSK COZNG XKVUX ZUTNO YOTBK YZOMG ZOUTY NKCGY GHRKZ UZXGI KZCUS KTCNU NGJHK KTSGQ OTMKT WAOXO KYGHU AZEUA XIOXI ASYZG TIKYH AZATL UXZAT GZKRE ZNKEY KKSZU NGBKH KKTGR KXZKJ ZUNOY OTBKY ZOMGZ OUTYG TJRKL ZSGRZ GZCUC KKQYG MUNKN GYGIU TZGIZ OTZNK YNOVV OTMIU SVGTE CNUCG YGHRK ZUZXG IQZNK OXSUB KSKTZ YBOGZ NKCOX KRKYY ZKRKM XGVNG TJZNK EJOYK SHGXQ KJLXU SGIUS SKXIO GRYNO VOTZO RHAXE GZNOY AXMOT MGIRK XQCGY GYYOM TKJZU LURRU CZNKS GTJZN KECKX KRGYZ YKKTK TZKXO TMGHA ORJOT MOTCN OZKNG RROLK GXZNG ZEUAS GEHKU LOTZK XKYZZ UZNKM UBKXT SKTZH AZOGS GZGRU YYZUQ TUCCN EKBKT NGBOT MJKIO VNKXK JZNKL UAXZN YKIZO UTULZ NKCOR RCNOI NGMGO TCGYK TIXEV ZKJAY OTMGQ KECUX JIOVN KXOZO YYZOR RTUZI RKGXN UCZNK KBKTZ YULYU RUTMG MUIUA RJVUY KGXOY QZUEU ATUCU TZNKU ZNKXN GTJOZ OYIRK GXZNG ZZOHK XOAYJ OJTUZ KTZOX KREZX AYZZN KBKXU TGGMK TZYON UVKZN GZZNK LOLZN INGVZ KXCNO INOCO RRRKG BKZUE UACOR RHKMO TZUKD VRGOT CNEQO TJXKM GXJYI NGXRK Y
\ No newline at end of file
diff --git a/2012/4a.plaintext b/2012/4a.plaintext
deleted file mode 100644 (file)
index 503102f..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-My dear Nicholas, 
-
-Your Uncle’s revelation concerning his work on meteorology begins to explain his move into mathematics following the War. I always wondered why he had left the laboratories and factories, but his experience of industry must have soured as he saw the suffering that new inventions were causing on the battlefields. I have no knowledge of the work he subsequently did, and the few people I have asked have been strangely unable, or perhaps reluctant, to tell me anything of value. 
-
-The detective you hired to look into the mysterious figures on the island has contacted me with a report on his investigations. He was able to trace two men who had been making enquiries about your circumstances, but unfortunately they seem to have been alerted to his investigations and left Malta two weeks ago. He has a contact in the shipping company who was able to track their movements via the wireless telegraph, and they disembarked from a commercial ship in Tilbury. At his urging a clerk was assigned to follow them and they were last seen entering a building in Whitehall. I fear that you may be of interest to the government, but I am at a loss to know why. Even having deciphered the fourth section of the will, which again was encrypted using a keyword cipher, it is still not clear how the events of so long ago could pose a risk to you now. On the other hand it is clear that Tiberius did not entirely trust the VERONA agents. I hope that the fifth chapter, which I will leave to you, will begin to explain why. 
-
-
-Kind regards, 
-
-Charles 
\ No newline at end of file
diff --git a/2012/4b.ciphertext b/2012/4b.ciphertext
deleted file mode 100644 (file)
index 423e6b3..0000000
+++ /dev/null
@@ -1 +0,0 @@
-FDBTS LKIWB DBXWO SYLII SYQFL KLZQD SSTSK QPLZQ DSKSV QZSUJ LKQDP QDSOB FKZSI IFKYS PPBKQ IWBKE QDSQO SKYDS PBKEL ROALL QPZFI ISEUF QDUBQ SOFPM SKQJB KWDLR OPUFQ DZFKC SOPZO LXSKB PFQLL HOSBE FKCPL ZUFKE EFOSY QFLKB KEZLO YSBKE SVMSO FJSKQ SEUFQ DKLXX ISESP FCKPZ LOLRO CBPUS BMLKF UBPDB RKQSE AWQDS JSJLO WLZQD SEBUK ZFOFK CPNRB EBKEA WQDSP RZZSO FKCLZ LROQO LLMPZ LIILU FKCQD SCSOJ BKBQQ BYHBK EFUBP PSFXS EAWBK ROCSK YWQDB QAILY HSEBI IZSSI FKCLZ YLJJL KDRJB KFQWU FQDQD SSKSJ WQDSZ BARIF PQPDB EELKS QDSFO GLAUS IIFQN RFYHI WASYB JSBMM BOSKQ QLJSQ DBQZL OSYBP QFKCB QJLPM DSOFY YLKEF QFLKP ULRIE ASLZY ORYFB IFJML OQBKY SFKES QSOJF KFKCD LUBKE UDSKQ LRPSQ DSUSB MLKUF QDLRQ RKERI WGSLM BOEFX FKCLR OLUKQ OLLMP BZQSO PSTSO BIJLK QDPFK QDSQO SKYDS PQBHF KCJSB PROSJ SKQPF OSQRO KSEQL TSOLK BDNBK EASCB KULOH LKBKS UPQBQ FPQFY BIJLE SILZU FKEJL TSJSK QPABP SELKQ DSULO HLZAB WSPWL RDBEG LFKSE RMBKE ASSKP SKQQL QDSZO LKQAW QDFPQ FJSBK EBPFI BALRO SEFAS CBKQL DSBOQ BISPL ZWLRO DSOLF PJFKA BQQIS FUBPB PDBJS EQLAS SKGLW FKCQD SYLJZ LOQPL ZQDSY DBQSB RARQA WQDSK FUBPL APSPP SEUFQ DQDSA SIFSZ QDBQJ WULOH YLRIE SKEQD SUBON RFYHI WBKEQ DBQFJ FCDQP BTSWL RBKED RKEOS EPLZQ DLRPB KEPLZ WLRKC JSKIF HSWLR ZFKBI IWASC FKKFK CQLJB HSMOL COSPP LKQDS EFZZF YRIQQ BPHLZ BKBIW XFKCU FKEMB QQSOK PFPDL USEJW ULOHQ LTBIS KQFKS BKEMO LQSRP BKEQL JWPRO MOFPS QDSWF JJSEF BQSIW OSBPP FCKSE JSQLB KLQDS OEFTF PFLKF YBKPS SKLUQ DBQQD SPBZS ESMIL WJSKQ LZQDS USBML KUBPB PSYLK EBOWY LKYSO KZLOQ DSJBK EQDSW USOSM OSLYY RMFSE UFQDQ DSISQ DBIML USOFQ ULRIE YLKTS WFQDF KHQDS WUSOS EFPBM MLFKQ SEQDB QFDBE ZBFIS EQLSK CBCSF KQDSE SPFCK LZKSU MLFPL KPARQ FYLRI EKSTS OELQD BQFPQ FIIOS YBIIS EJWDL OOLOB PFIFP QSKSE QLDBD KFKAS OIFKE SPYOF AFKCQ DSSZZ SYQPL ZJRPQ BOECB PQDSO SUBPP LJSQD FKCYD FIIFK CFKQD SYLKQ OBPQA SQUSS KQDSY LIEEF PMBPP FLKLZ BPYFS KQFZF YISYQ ROSBK EQDST FISKS PPLZQ DSOSP RIQPD SOSML OQSEB KEFYL RIEKL QAOFK CJWPS IZQLU LOHFK QDSIB ALOBQ LOFSP ILLHF KCABY HFYBK PSSQD BQQDS ZBARI FPQPK SSESE JSLRQ LZQDS UBWFK LOESO QLYBO OWLRQ QDSKS VQPQS MLZQD SFOMI BKDLU STSOF KOSBP PFCKF KCJSQ DSQUL CSKQI SJSKZ OLJTS OLKBD BEJBE SBTSO WABEJ FPQBH S
\ No newline at end of file
diff --git a/2012/4b.plaintext b/2012/4b.plaintext
deleted file mode 100644 (file)
index 1426fca..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-I have only a hazy recollection of the events of the next few months. The rain fell incessantly and the trenches, and our boots, filled with water. I spent many hours with fingers frozen as I took readings of wind direction and force, and experimented with nozzle designs for our gas weapon. I was haunted by the memory of the dawn firing squad and by the suffering of our troops following the German attack and I was seized by an urgency that blocked all feeling of common humanity with the enemy. The Fabulists had done their job well. 
-It quickly became apparent to me that forecasting atmospheric conditions would be of crucial importance in determining how and when to use the weapon without unduly jeopardizing our own troops. After several months in the trenches taking measurements I returned to VERONA HQ and began work on a new statistical model of wind movements based on the work of Bayes. You had joined up and been sent to the front by this time, and as I laboured I began to hear tales of your heroism in battle. I was ashamed to be enjoying the comforts of the Chateau, but by then I was obsessed with the belief that my work could end the war quickly and that I might save you and hundreds of thousands of young men like you. 
-Finally beginning to make progress on the difficult task of analyzing wind patterns I showed my work to Valentine and Proteus and to my surprise they immediately reassigned me to another division. 
-I can see now that the safe deployment of the weapon was a secondary concern for them and they were preoccupied with the lethal power it would convey. I think they were disappointed that I had failed to engage in the design of new poisons, but I could never do that. I still recalled my horror as I listened to Hahn in Berlin describing the effects of mustard gas. There was something chilling in the contrast between the cold dispassion of a scientific lecture and the vileness of the results he reported, and I could not bring myself to work in the laboratories. 
-Looking back I can see that the Fabulists needed me out of the way in order to carry out the next step of their plan, however, in reassigning me, the two gentlemen from VERONA had made a very bad mistake.
\ No newline at end of file
diff --git a/2012/5a.ciphertext b/2012/5a.ciphertext
deleted file mode 100644 (file)
index 1e73c50..0000000
+++ /dev/null
@@ -1 +0,0 @@
-DISFL TSFXI GYJLT UGZAM SBBSF IZHHA YIYPJ ZLXIG MAFWE AFOFU HUGTU ZHIXX URIZL IINBX SUZGH TIRSB GUZTU GTUGH AFPSZ DUEUZ DIIDH UOIFU JGEAJ ZDTUY GIXEL SJRTH JBUZS LAZGB UFSLP OIPAZ DTUGB AMIFH ALAZH FAXHT IZBIF TSBGT UGDIS HTMSG ZAHHT SHAES LAMSF DOJHV JGHBA GGUOX PHTIF IGJXH AEEAJ XBXSP HUOIF UJGUY BXUIG HTSHH TIESO JXUGH GMIFI UZKAX KIDUZ YPUZV JFPSZ DUETI UGLAF FILHH TIZEA FHTIE UFGHH UYIGU ZLIYP IKSLJ SHUAZ EFAYH TIOSH HXIEU IXDUT SKISZ IMIZI YPHAE UZDSZ DHAEU RTHUG MAFID JFUZR HTIXA ZRMII WGAEY PHFIS HYIZH UZHTI EUIXD TAGBU HSXSH IHSBX IGHTS HUMAJ XDZIK IFOIS FSFYG SRSUZ YPZJF GIYUG GOFUH HSUZJ FRIDY IHAHS WILAJ FSRIO JHSXX OFSKI FPMSG RAZID UGGAX KIDOP HTIOJ FZUZR BSUZA EHTIL AFFAG UKIRS GZAMU EIIXS ZIMEU FIHTI SZRIF GHUFF IDUZY IOPJZ LXIHU OIFUJ GGSLL AJZHF IURZU HUZRY PAXDE URTHU ZRGBU FUHSZ DUTSK IDILU DIDHA HSWIA ZHTIU ZKIGH URSHU AZAEH TIESO JXUGH GYPGI XEPAJ GSPHT SHYPI ZIYUI GYSPG HUXXO ISLHU KIUZX AZDAZ GAUMU XXIYO SFWAZ HTIZI NHGHI SYIFH AHTIL UHPLA JXDUS GWPAJ HABXI SGISF FSZRI SLLAY YADSH UAZEA FYIUM UXXHI XIRFS BTYPH FSKIX BXSZG OPHTI MSPHT ILPBT IFJGI DOPHU OIFUJ GUZHT UGHIN HMSGD IKUXU GTXPD UEEUL JXHHA DILFP BHOJH GUZLI MIZAM WZAMH TSHTI MSGHF SUZID UZLFP BHAXA RPMIY URTHI NBILH EJHJF ILTSB HIFGH AOIUZ LFISG UZRXP TSFDH ADILP BTIFU LAZDJ LHIDY PAMZF IGISF LTSZD DUGLA KIFID HTSHH TUGHP BIMSG EUFGH OFAWI ZOPLT SFXIG OSOOS RIHAG SKIPA JHUYI UMUXX HIXXP AJHTS HHTIW IPTSG XIZRH THTFI IPAJF GGUZL IFIXP ZULTA XSG
\ No newline at end of file
diff --git a/2012/5a.plaintext b/2012/5a.plaintext
deleted file mode 100644 (file)
index dd8c594..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-Dear Charles, 
-
-Much is now apparent to me. My Uncle’s work for British Intelligence explains the gaps in his history, and if indeed Tiberius found himself caught up in a conspiracy beyond his power to control then perhaps his death was not that of a coward but, just possibly, the result of foul play. 
-
-Tiberius implies that the Fabulists were involved in my injury and if he is correct then for the first time since my evacuation from the Battlefield I have a new enemy to find and to fight. I swore during the long weeks of my treatment in the field hospital at Etaples that I would never bear arms again. My nurse, Miss Brittain, urged me to take courage, but all bravery was gone, dissolved by the burning pain of the corrosive gas. Now I feel a new fire, the anger stirred in me by Uncle Tiberius’s account. Reigniting my old fighting spirit and I have decided to take on the investigation of the Fabulists myself. You say that my enemies may still be active in London so I will embark on the next steamer to the City. Could I ask you to please arrange accommodation for me? I will telegraph my travel plans. 
-
-By the way the cypher used by Tiberius in this text was devilishly difficult to decrypt, but since we now know that he was trained in cryptology we might expect future chapters to be increasingly hard to decypher. I conducted my own research and discovered that this type was first broken by Charles Babbage. To save you time I will tell you that the key has length three. 
-
-Yours sincerely, 
-
-Nicholas
\ No newline at end of file
diff --git a/2012/5b.ciphertext b/2012/5b.ciphertext
deleted file mode 100644 (file)
index 39ff6f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-FIPYR YREBN IASHC NXMBI YCWGQ RKOXM KRCGG MNIZB IYUML QHGFM QSSLS RJYRB YRYXS SDTMC XMPVM YQDYV RIAGD LGXXF OEBWM PKPRI MUKWP OUSSV CNXMB INYVR DSAYQ KKRBO VBORL SWRYR URSRB EGXIB WIGXX FOIJO QCXXQ YJKIR CGXYC OYXHG DUSSG IVCZO GYWIY ZTYBI LDXFK XRRIK OXFYH QYJAY RBSXG YRYVT PYFYL MJSXG OWBOZ CVSNO HZIFY IIQSR URMAR MFKHZ OGMWI YNIND HSBML QQWGS PUSLG MLNJM BIAKW RSREM SSVHE SZCEW YMVSM MYVEB FELDE EOMLD LCDEQ USDMV WZXYX EJIWG CKJKH YCMUK WRYIQ MENOX FOLMB VMBWM PGFOQ GMEJG IYZSL CMRRM LURMG XFKXT KPCXX GXIYX HNBSR OYQRE BSRRO RBOHR YGJYM QDIPW IGXRY FEJSR ROPJS KCXGC SRMBH CBXMK ZMSHY XCARE LMIRR ERSQG QLRER AYZCB XFOMP NVCKH DEPQO GPOXZ EXRRI POPYD MMXWF STZOX UOILD LCKHK SVYVX WMSBO FPOEI SRENM TSWGY RGXVM YQDYV RIELN XFOEP WCBSZ GCMMX QGSFU KWAVS QOVRR ELDLC PEZEP GCXQR EBSQY QMLOH YXHRR IGXXC BEADM MXFCD ACORR RIQOE EORAS IQDSE OXFOV USXFW CDSIJ NIVZI PSILM IMXXF OGMXX GXILD QCKRR DLYDM UKWGX GPOEQ SREVC CXKYQ IBSRR RIRKW IYJZB IYUML QFYDX JOJGO PBKRB QIPWE LRMER GMWQY XHAYQ KERGM ERSSL CILMS SBEEO HZIXF OILQM LOIPC MLYYP SRABI YCMLQ PWCSN RMQDM AKXCN WGQRY VWSXM RGLMG IPOEB OTRKX GXXCB GCZXG XKROP CQVYZ LGMQC CWYQI QPVMW XFOJY BJGOP BCSDO YPYTC SXFBI UWCQO PDSRR YAMBO MXGCW SPOYL DMJYR CGMLD IPIAC NRCCH YIEDD IPXSM XMPOG CSZCN EKOWQ KKCDL YDKPS TNOHY XHFYV PSJGO HKORC GEQDL GCGGZ LCBAY CMBSH LYXFK ZCDMK OXMOR HYCKI XPSYK ZLGXH CMVWZ XGXKG DEQDL CZPYS RROBR BITOE JOHYM VGWML KPAYR QZMPK GWKXR RIFSK FOWRV ITOPQ SRZBM RSWFS RROPJ SKCXG CVIBL CRRID KFSVM QDWCF ILKWR RIDEP JRSPB SPYJK IMLFS JFIKO RRSRR RIGBW ARIKO AYCPY SHMEX ZOJMB IKOMA YYJNR MDXYU IGDML BINYV RSRED LCMSL CTGBE AIAYC MKZSQ CMZVI QSRAO MAYYJ NRMDF CCYPO AFYAY CMLFS JFIBO ZCXMD SGMEP BDVSC XQYQC YRCYY RCMBO SDFIP YRYDL CCIAE VGDCG XSSBY LSXUK WQYXG QLRDL YDMFK HLYGF KRAOX MDEIO ELIIT SHCXG CGMRR QCSVC KPGJI BDLYD MUYYJ NLYFI RYGMX GCKPK IHGCG MFIPI AFSPC SYLNI PDSMU JSBXF OVPOW CKVAR SDWCM GRGXX MDLCX IRGSP USDDV YSXMB WUSXF SRMEV GXXCV PGQIL MIQOV TSGCC YLPSP DYLKX CVCGG EQMPS WWWSR KIMLF IQDME KXGYR QKRBW CAKVC VIQCR CCWLO EPVCA YWRIS SISSB PGPIY XHWYY PBINE XYDMM XEKSW RKOCP SPGLG MLGME LXITO VDYVE SZCWC QOPDS GYXSL VCNBE WDLYD CMEAG VPZOE ZVIRY JMBKG FIKOM POGCS ZCNER OPCQV YWJPY QTOVM XEQEQ KYRGX KKOFY MORYC NBIQV EROVR RERWS LDLYC MPOEB SXGUR CGXFK XRRID KFSVM QDWFK HQYQC RSULI AYQCK AYBIM PQWSR ROVCC XGXXF OMPCI ABIRG SPUEL NMDEP JIFCV MCFIB DLYDM UKWZO MLQWC XXRYQ WNIYD LGXXF OXPOR ARIQS FMKVB OHRRI ZYERD SDVEL NIPCE LNWSB VMERB OHZIA CKVWC SJNMC BWPOX SBRGX KRYXF OJPYR RVMLO MREVL OHKIX FYYER XQDSD SRBSR EKAYI XMOBN YWCDL CPEZE PGCXQ ZPYXW
\ No newline at end of file
diff --git a/2012/5b.plaintext b/2012/5b.plaintext
deleted file mode 100644 (file)
index 7360eb0..0000000
+++ /dev/null
@@ -1 +0,0 @@
-VERONA had decided to reassign me to a new code-breaking division in London, an outpost of Room Forty within the Admiralty. I was required to report to Commander Denniston who trained me in the elements of my new task and it quickly became apparent that the methods of conditional probabilities developed by Bayes, in which I had become adept during my work on wind forecasting, could give us a crucial advantage in the task of cryptanalysis. Glad as I was to escape the horrors of chemical weapons, I think now that Valentine and Proteus had intended to cloister me in Naval Intelligence in order to avoid any chance that I might uncover their dreadful secret, but the relationship between the Admiralty codebreaking division in Room Forty and the Army division MIIb was closer than the Fabulists had imagined and the interaction between these agencies, together with my field experience on the continent, meant that I was increasingly engaged in the task of breaking battlefield and German High Command communications. Encouraged by the engineers in our increasingly sophisticated signals unit, who were adept at intercepting telegraphic messages from the far fields of Europe, I threw myself into work once more until one wintery Wednesday afternoon I received a message that gripped and horrified me. New as this cipher was I did not have time to enjoy my triumph in decrypting it, as the plaintext revealed a criminal conspiracy at the highest levels in British Intelligence led by the Fabulists. Even as the full horror of my involvement in their scheme was laid out before me I could not take it in. Reporting the conspiracy was impossible since I could not be sure who was involved. Even if I could trust someone outside of VERONA the security in our unit was so tight that I had no chance to take any evidence with me. I realized that I would have to conceal my discovery while I undertook further research of my own into the network of traitors within our intelligence services. Unfortunately I was clumsy in my investigations and my carelessness nearly cost you your life and your reputation, a mistake for which I can never forgive myself. I can only pray that you will be able to forgive me. I received a telegram from VERONA summoning me back to Ypres later that month. As I read it I knew that the Fabulists had somehow become aware of my interest in their secret work, and I fully believed that I was being sent to my death in the trenches I boarded the boat to Flanders and, surrounded by weary soldiers returning to the front line, I turned my thoughts to finding a way to expose the Fabulists plans.
\ No newline at end of file
diff --git a/2012/6a.ciphertext b/2012/6a.ciphertext
deleted file mode 100644 (file)
index 51f02eb..0000000
+++ /dev/null
@@ -1 +0,0 @@
-KILFB WRVCZ LHJVW BGHLF IAMRV RZILF IFBCP LBKWF ILZWT IJVIK LBGIF SCMLF IWBWP LHOWH WJIKJ CKLSU SJPCG IBJZI AIBAL JRVWB GJVIK IHRFW DJWCB CNOLZ IBJWB ILBKD FCJIM HJVIS RZLWA IKJCU ILRJW BGNCF JVIGC OIFBA IBJLB KPIFI LHYWB GWNWY BIPPV IFIJC NWBKS CMJVI SRZIL FZSPI FILPL FIJVL JSCMV LKZIN JALZJ LUMJN CFJMB LJIZS VLKBC JLHNL FLHWR LBJIZ ZJFLR IKSCM VIFIJ VISPI FIACH JWBHW HJIBJ JVLJJ VISBI IKIKJ CJLZY PWJVS CMHLS WBGJV LJJVI GCOIF BAIBJ PLHCP IKLHM UHJLB JWLZH MANFC AJVII HJLJI CNSCM FMBRZ ILBKJ VLJJV ISPWH VIKJC KWHRM HHJIF AHNCF FIDLS AIBJW VLOIJ CHLSJ VLJWP LHWAD FIHHI KUSJV IWFWB GIBMW JSJVI SAWGV JIEML ZZSVL OIRZL WAIKJ CUICN NIFWB GSCML HMACP IKJCJ WUIFW MHUMJ JVIJL ZIJVI SHDMB RLFFW IKXMH JJVIF WGVJZ IOIZC NJVFI LJJCU ILZAC HJRCB OWBRW BGWKI RWDVI FIKJV IZLJI HJRVL DJIFC NSCMF MBRZI HPWZZ PWJVZ WJJZI ACFIK WNNWR MZJSJ VLBWV LKIBR CMBJI FIKPW JVJVI DFIOW CMHHI RJWCB WJPLH OIFSH WAWZL FWBHD WFWJL BKWBK IIKMH IKJVI HLAIJ LUMZL FIRJL JVCMG VJVII BRFSD JWCBL ZGCFW JVAPL HHZWG VJZSK WNNIF IBJWU IZWIO IWJWH YBCPB LHJVI UILMN CFJRW DVIFW FIRCA AIBKJ VLJSC MHJLS LPLSN FCAZC BKCBN CFLZW JJZIP VWZIM BJWZP IVLOI RCBHW KIFIK PVLJP IAMHJ KCJCD FCJIR JSCMW VLOIR CBJLR JHPVC ALSUI LUZIJ CVIZD OIFSU IHJPW HVIHR VLFZI H
\ No newline at end of file
diff --git a/2012/6a.plaintext b/2012/6a.plaintext
deleted file mode 100644 (file)
index 2945c98..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-Dear Nicholas, things are much clearer now, and I realize the danger you are in. I was visited today by two gentlemen matching the description of Valentine and Proteus. They claimed to be acting for the government and were asking if I knew where to find you. They clearly were aware that you had left Malta, but fortunately had not, as far as I can tell, traced you here. 
-They were most insistent that they needed to talk with you, saying that the government was owed a substantial sum from the estate of your Uncle and that they wished to discuss terms for repayment. I have to say that I was impressed by their ingenuity. They might equally have claimed to be offering you a sum owed to Tiberius, but the tale they spun carried just the right level of threat to be (almost) convincing.
-I deciphered the latest chapter of your Uncle’s will with little more difficulty than I had encountered with the previous section. It was very similar in spirit, and indeed used the same tabula recta, though the encryption algorithm was slightly different. I believe it is known as the Beaufort cipher. 
-I recommend that you stay away from London for a little while, until we have considered what we must do to protect you. I have contacts who may be able to help.
-
-Very best wishes, 
-
-Charles 
\ No newline at end of file
diff --git a/2012/6b.ciphertext b/2012/6b.ciphertext
deleted file mode 100644 (file)
index 56cdfd7..0000000
+++ /dev/null
@@ -1 +0,0 @@
-IXWIF MKLOE HMRBZ FWLTQ AOQZQ WIBNH RQAAW HBRCF JAXBR CNLOL TQXBY PKCWF MGOPZ NCFMK OONNJ GRCMF KLCBY KTXXN WMSVN GIQNR BTNIN PSHZM AZXTE QFZDG JCAFF NGPNZ XQTAA TQWBM SIRGY WNLLX JGVTA DZKEZ PDWDN AMPOA OWNAG QTAJC XBOPW WAHDK DOBTP HFVXC BTPUJ WDOFE JPFXN LUEXU UXNTY GZQBB NWMQI QCVDA UATGO XDCNZ OGCKA GZQNP UGPAB RXBYK JCMTA HNJJI QAXIB SJAUN WZLDZ LNRZA MGPFH TXHRV KTGAU ABWZP YEHBY KMZQT XQQVK FWLTQ XXOPM NAZXV TZOLS JXHRQ KAARM HNOHT PBBRY FWLTQ XXFPJ MAOBS KLZXE UNOEL OJSBF VJFOL MUCKF FOMHD FVJFO QVBYK VPBPM HMHNV MNMFR WNQIQ HQNVJ ANRLD XWDGX NIGAS RCUAP RFVRR BSLHB OAAUA VDBBP MAQJR BXVMT CTUMV KTIMH UZKVT JKNRB XWPKQ NUZUR CYENR XGFTV WNQCW JGZAS BJOZQ TZVMD UGAIQ ZQUGN YXLTU MOGIN ZFQOA ETFAJ QQXJY DLMBY KMTAK PMNVZ ONKPF UAYAU EHMMS RBHRX QOVKP YWJQD VPFOL JGUAM EKQHQ LWRGY JAJBB YLOAS HTQKF KNMDX XNBNT FQCVD AKEFQ UVKPK AABAU GIJPW QCLNA XNOMS KOANC MHAXD GILTQ TOEQI QWXQA ZPIXW MOTJI XPPUS VKPPE RGOGY VNZIG ULJPK MZGMH PFPSS CNGDG XBMPA GPPKM AHCKE ITMHQ CCNGB NWRBM NGIXM HRUAT ATWIB BVMNI MAULQ PUQJD XJJPY DCYYO YLUEX ASMDY XNWRL BMFKL GHFVN IDLTQ RBNHB RSSYA ZPIQW HMXXB IISBY VKPRR MYUKO NXWTU CIRLO AXUHA XGVTS QLVNG BRHSR DDGXT EUNOC TKLNQ OGEAU AYDXC NBNZH NBJRS HTSCM WKPUE XFOAW POXSC KOGFH NABMH NOKQN BFBOI TUWIB HNMBB ZQBBA PGQPB BLQVF XABYK KTYMW QSGVT JMGDB HNXNK PRNHR CXSCD BTXIJ WMHEU YMTMT UMXNQ NZHNB KEPPG EUNVD FJLJG SIRGY XWYFW NWZWH QCNTX UEHMM AGQUW OCLXN AUEHB YKEPF IWUQA EXNKP RBBOA UAEUO HNBBI FMDVD CDITQ OKJBB IASOG FP
\ No newline at end of file
diff --git a/2012/6b.plaintext b/2012/6b.plaintext
deleted file mode 100644 (file)
index ba56488..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-The machinations of the Fabulists had been exposed to me in the intercept I decrypted for Room Forty. They were intent on developing cruel weapons capable of demoralizing and injuring large numbers of enemy soldiers in defiance of all natural laws of warfare. 
-
-I had already been exposed to the horror of modern conflict and their plans filled me with revulsion, but I could not have guessed at the full depth of their depravity until I had read the full text of their message, which was an invitation to a demonstration of the weapon. They proposed to test it on Prisoners of War held at a camp near the French border which at that stage was under VERONA guard, and I imagined, since it was difficult to believe that all of VERONA were privy to the Fabulists’ foul plot, that it was under the direct control of Proteus and Valentine. 
-
-In my horror I resolved to travel there at full speed determined to confront them and to expose their vile plan. The majority of soldiers, both commissioned officers and enlisted men, are decent honourable men who would be horrified by what I had uncovered. Unfortunately the one man I chose to entrust with the knowledge I had gained, a young lieutenant colonel, was a partner in the crimes of the Fabulists. He had proven his valour at the Front, and like me he had been revolted by what he had seen. I was sure he would share my revulsion, but his hatred of the enemy was too strong and he was excited by what I told him, sure that the new weapon would end the war. He saw victory where I saw a crime.
\ No newline at end of file
diff --git a/2012/7a.ciphertext b/2012/7a.ciphertext
deleted file mode 100644 (file)
index 2bc7ea0..0000000
+++ /dev/null
@@ -1 +0,0 @@
-AHDCE RLTAS RESRH OETFI YYOMU ANYJR AMTTL SEEAS KSEDN NSAMA IEART ODFYO ITREG VEUII BRKWS EINAH TIHTB NAEDE CSUNN OOFCS IUSEO MROMF TAIER ETHET STGTA AKTAU CBALI AHDYS WAASM TSDUE TAHHA IPTDN SEAIT THTIH MTENI DELFE STHIO PREAM LEENM IBROI GHNTA ENTGF EIRVL AMSNS GIIAB TRTMW IONYN INUEQ EERHI SIORL ENOAN HDNEA VTESI EBHLS HVDTT AEIAT LNAPN DENTS RUOEE GAIRH AIHKR NOINF GFAIC SILHE NTWIL IHWAL DPTEH ENCCE ONOAT SINOT CSRSF EHREO NFIFG OERIO CMVIE ROESE TLICT TAARH ERTAH YWEER AAMEO RFYRO TTUNG NEANL NSDIA DPTUC SEAAT IHTEG MNBIL WFOOL ATEDD NTLHY AMTSE RTEEI AERBR DNAGE MCINA IANRI ESYRG ULSHT ETTAO YHLEN ANROE SMIIT ASAVL ILLSA EHITH ATYTE NCRTE OTNEI RAOSW LHEIT EHMGO IKTNW RSBUE ITYSR SOIRI CTSIL IATCA HTTHT DOENY OIOTC DSREV HETTL DIEAN ASIAD UTMES RTIHH ATSYS HIWBI TRIEE RUCSN TTYDP ELTHS EACOS IETOI NHSFI WSLWL HCIUT SAHHE CRUHE TMSEA AEVLE BRAND TLOIU HNCLW SEHWY RPENV HEEHI DIEST LHYTA EEARE EYAIR OSGNA ATMOL UTSAL IUROE WHELV DAEBB AENTE LDEOP RCEYH IATPH SOHRT TFIIE LWLED FAHHE MUASD RBAXT IGTIR GENOH WETTI BOYWV OHTAE YASHA THOTM TEARS ATLNE MRIGL IVTEA HEORN ETEIB SIUTR SISEN AETMH HTTTA AOENW SEWTA YTETA FROFL HLEUP ODHET HRFIT EEHTC RAYVE IRGTH EENHR OORRO HTFTW AYDHI EDMNT AOEOM DYTMI NEINF TRDAI HOADM TINUG MIEWS CRHOF REAIE AYTMH TFILW IENEL VLEEE RHBTM GSAAE NNAII SRYCL EEUNY SORHA ILCOX XSXXX
\ No newline at end of file
diff --git a/2012/7a.plaintext b/2012/7a.plaintext
deleted file mode 100644 (file)
index 8b30107..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-Dear Charles, 
-
-The story of my injury at last makes sense and I am ready to forgive Tiberius. I knew that I had been unconscious for some time after the gas attack, but I had always assumed that I had spent that time in the Field Hospital, remembering nothing after leaving Miss Brittain. 
-
-My own enquiries here in London have established that Valentine and Proteus are high-ranking officials in Whitehall with deep connections across the Foreign Office. Moreover it is clear that they are aware of my return to England and I suspect that I am being followed and that my letters are being read. I am increasingly sure that the only reason I am still alive is that they are not certain who else might know Tiberius’s story. It is critical that they do not discover the details and I am sure that this is why Tiberius encrypted the last sections of his will with such care. He must have learned about Hill’s new cypher when he visited Yale three years ago. I am not at all sure I would have been able to decypher this part of the will if he had used a matrix bigger then two by two! 
-
-I have to say that the most alarming revelation here is Tiberius’ statement that he was “not yet aware of the full depth of their treachery”. Given the horror of what they did to me and to my men, I find it hard to imagine much worse. 
-
-I fear that my life will never be the same again. 
-
-Sincerely yours, 
-
-Nicholas 
\ No newline at end of file
diff --git a/2012/7b.ciphertext b/2012/7b.ciphertext
deleted file mode 100644 (file)
index 1f1c323..0000000
+++ /dev/null
@@ -1 +0,0 @@
-IBWUQ RCIHA QVILU DSARR EAVXD DQCIF XZPLX ZLDFX CIJOD RENUL GKULV NVHJO CSLUC IBDEX MPDRV HJBIX HAMWE AVXEX RXFJJ OEXCS LUHOQ ZGEYW TFKSY EAZEK JTJVF XUJSF SNNPC IALHA MWGFP FJBAZ RBZJY KLZND EQVUQ JHBJK XDCDD RJGCF SVQIA NJXKO MCFJD SQWOH QZDRP JNMIX KZBZF BGVIX IBWOO QWBDB QCIJM XCFOP IXNDC FILFJ LZRBL TQHUU AUMJX GADHA QVQWZ CXZVD SWTFS MQISV IOYTU YZCQW KIKDM EZCQW EQJBU CKZAD OWZXS RKHHA EXEQJ BILYK DBJIH AIOKQ HAIXU CKZIQ CFEXU CQRVX CYMUJ OGGKZ BZDFR LOBFJ DSIFD RKPOG BDCRO CVLNM IXLZS RKHMU KPSOO CXPVH VLXGU GEKVS MJYGP FCDMJ LBJBM UHAWB UCQRW UFOAP YHNDC FWBDB QCAZW BVHYV ANRIX ZNFYK EAVXS MKGEX QOLUH OQICO AZBZY HALYI WQESM ABJZX AZRPO QSBGF WBUUQ IWQWG PIMAR XFJJO EXCSL UHOQZ GESRM JLBJB MUHAW BUCEU IXCSL BXPLX VDGZE CYIKG FXLGL BXPVH IAVXY HULHA MWXZV HVKAN WGNJW BJTDV EOHAW BUCAI YKXYC SIAJV NDRBK ZVHLU HAMWL AANTF RICJP FLUUC KMWQB ZCILG IXYSO QKRVX YHCAU LDHDJ AZIBH AOCDV EQJII ALUSO SBPLU LANLQ IXACO QMINN LUHAS AHAVX WBVNJ IAZMU WOMKH VALLC CSDIA DUCGN DRMUO AZJIB HAIKL LSIPL ULIJY HKSDO QICIP POQSR OBNUV XAPEX QGSML UANHR WUUDV UQZND GFHAY TFXGA TAHAW BUCCO AYTAA CXGIX HAQIS CQVWB UUUCX EQDKH WAOQL ZVNLU UCSXQ VADYT DRCAY KXYNP NUOBV SDRKP HAVXW BANHR JGMXM JFJRI XZDOA YTALZ HAQVX DJOEX HAGRK HKQXG EXHRJ BQWDD YTECY KZWKU WBMIN NVKQH EXQOZ CDRVN MJZGI ONTDB LBEXJ TVKQM WBAZO PIXCA ULMMM IYCGC ZXWUU DJKEX DSGNA LYIEO TFIBH ACFQR CIWQR TIOZC CWPLV XRIIO HBCGC HIOYT MUULH ASBWB TAIBE XHRJB UCYCD RVXOW JIAZU CAIPF APEXC YJOQZ DRJTJ OOWVK YOJBS CADDB JIGMY KLUAZ WUWLA NMINN LUXZR IVXWB AZUCY PADAP KUSGL ULXPS GUYKA YVLVX ZGIXL ACSSR IODBY OBDSA PLJBH AWBHA IXWAI XKQHA IXQYF XTFAZ AZUCQ RDRPA ANJXD BMCIX AZIBV NJOQZ DRRBW TSAEQ JBOPI XIFJJ JBLZW QXPUC QRMUT FXPZX JOXZT XXZIO HAUUO BALGF CNEPU GEYSB DBYNI OIKSW ULJGC WTLGV UUCFR RANPP DRZXA POGAZ HAUUQ GXPXD NNUBA ZCFPL KRSRD RIFEP NJYTX ZVDCF GCTXJ JJBHA AZQIU BUTPL ULIBR XFJJO EXCSL UHOQZ GEAPY HNDCF EXHAC FOCUN PJQRF XSFSR OBDDB DQRWA FXLZJ GYCPL CIGFS VAZRB ZJYKK RULOC TFXPZ JILAN DFTFD SWWXY EXCYW UUDJK EXVHL UHAVX AZKEG HWBIX SNYKL UUCSX ANVHW GVHLU KZWUB DAGYK IANNJ DHHFX YCOCJ ODRGG SFSRQ ZDREO GNFXF EDRLB TFUCO LYHND CFHLF YUPQR TFDSI FDRQO WQLUA LJJPT UCOLY HNDCF BMGAW GDSEG IFADM UJOIX MZIXX ZPZHA MWEAV XAPOG EXQOA FWMMU XDPVW LWBHD RBZJY KDVYP PVBPJ BLXPL XJOQO AVXLB YYJVL ZXZXP NDCFS CYTFX RIKHV XXPJO UCQRQ IOWHB IJGIS RAZUC SKJOM AAUFX UDBZD VANPP KRYYJ KSNJT CFSMF JEBQW OHQZD RVNMJ ZGION TDBTZ DRVXO BQVNF YKEXH ASOGF KQFED RRZDV UUSAE BBPZC MKNNL UFJFE LZWUB QXDJO HASOU LMZKP WBADW DQZSW DBYIV XIBHA QVUDX YSBHA IBHAO CLGVX QWDRZ J
\ No newline at end of file
diff --git a/2012/7b.plaintext b/2012/7b.plaintext
deleted file mode 100644 (file)
index bdc2621..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-Of course the Fabulists were lucky that I had chosen the wrong confidante and, sensing the danger they were in, Valentine and Proteus knew immediately how to diffuse it. They arranged for you to be kidnapped from the trenches and smuggled back to the border under cover of a gas attack. I have never been able to forgive myself for the fact that my enemies chose to attack me by attacking you. Nor can I stop thinking about all those other young men in your regiment wounded or killed by their own side in order to stop me. 
-
-I received an official telegram telling me that your corps had been attacked at dawn and that you were missing and presumed dead. It was accompanied by a separate message from Valentine and Proteus telling me that you were alive, but my joy was short lived as I read on: they had arranged matters so that you could easily be found and they planned to brand you as a deserter. I was already convinced of their skills in deception and persuasion, and this threat filled me again with fear for you. The memory of the execution I had witnessed was still fresh in my mind and I could not bear the thought that you might suffer the same fate. 
-
-My only hope was to find you before they could fulfill their threat and I travelled that night to the Front in the hope of finding a clue to your location. Arriving at the Field Hospital I interrogated every conscious man I could find, but it was one of the nurses, almost too tired to speak, who set me on the path to finding you. She recalled you crashing into the tent carrying a mortally wounded companion and had treated you for shock and burns. You ignored her pleas to stay insisting that there were others who needed your help, and staggered off into the fog risking everything to save your men. 
-
-Even in that chaos the military police kept a close eye on troop movements and when I showed them my VERONA credentials they told me that men matching the description of Valentine and Proteus had been in the neighbourhood. Still unsure who to trust I searched for you alone in every abandoned building I could find, and three days later I found you, bandaged and unconscious, in a farmhouse in the woods to the south of the line. You had been badly burned by the gas, and I think you had been drugged by my tormenters. Perhaps they were showing a glimmer of empathy for your suffering, but it was more likely to have been a method to prevent your escape. 
-
-I hoisted you onto my shoulders and walked fifteen miles back to the Field Hospital, where I left you in the care of the Nurse, Miss Brittain, and left to confront the conspirators, not yet aware of the full depth of their treachery.
\ No newline at end of file
diff --git a/2012/8a.ciphertext b/2012/8a.ciphertext
deleted file mode 100644 (file)
index 805592d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-YIRFP HVVCS FTCMJ TVNVP TMCHZ VWFBM OMSSE IPWNO FAYIM WYIOM JGBMZ AYOGR ZPRHR DOSKV RAYJX JKCTT YSEAI HZKVL GWVBQ YJYDC EEDRW CEMVX ZCAAW SLHVT NLFFG LTMEH UEHIR BGIHI RZYOR QVHBS PQDOE INIZH FCJRK SATNX YSSAW YCWFT NLRJR GMSNB GOJTF KRRAY COADW SKVUE VRUWN RZEKA BROEC FVSFE ERZUN XUWFA KTVOE YJYTO ASZIZ AZEYM RHRLT XYOGH DWCOF THIJG NGZGF BGADR VRBNZ WYCPK DRXFR VZPRH VOIEK ZRANX RBQOI GVMBU CEMSE EVHKV RWCSC SBFOL VRBCP QVBGY JYNWY LPRUS ESOEE RVSCE CZOEG IRJVN BFVTB RZJZF FTGMX VGTJX RYRUK EESJL DJVOF AIINA NNRMK VNNZA GIEPJ WVHBD ZWKFB YQECS ATDRV OADKV FHRUN EERNL GXYOG TCIPG GAIHW CEIYS ECGFZ ICFRA YCWCE TCMJQ UAGPV BTEWY KHUEI MESIE MJVZG RZEUM JADXZ BTFJV KVRCJ QDOAD OSCSN VZXYS GRZRT VRSZM KVRRR LVBGH ZAYWF TGISZ BWNXY SEEDW ECGHD RXZRF OFLHG OXLRF TEVRU DEATE ERGHV XZGJH VXZKV LGHFB BWKPV OFEYS EHJOM VPOAD KPVOF EYSEH GRTXF TVNYQ VWJIG PTCAT VGKMB UNSFB NFOII HUEII NMRAM MKFRM VMEGS OMQVH BTCEE YLOPJ FFNLG CFIES PTGCE TJZVF GHZWV ZNSOQ FBGHN EERLE VVJOF NDGYC YANMY OIEAS LBQYJ YIGHP KSIHN NYIEQ BUMEX SZEIX ZBIAG YRPYE DRDMA ERMUS ATDXP WUAQI RTREG MEUGH VXZHJ IGPSS RSNIE HVAGW ZBPEM ICMLO PVJVN RMC
\ No newline at end of file
diff --git a/2012/8a.plaintext b/2012/8a.plaintext
deleted file mode 100644 (file)
index 8484476..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-Dear Charles, 
-
-This final cypher from Tiberius was a devil, it is somewhat related to the ADFGVX cypher, and I will send you more information about it shortly. In the meantime allow me to summarise its contents. The Fabulists have grown too powerful and both he and I are at mortal risk and must disappear. You can see immediately that his last message contained one shocking revelation at least, and once you have read the whole of the document you will understand. I shall be leaving before first light to take up a new life as a new man with a new purpose: to destroy Valentine and Proteus and all that they stand for. 
-
-I do not feel ready for this challenge, but then I never felt ready waiting for the command to leave the trenches either. When the whistle blows there is nothing left but to charge and pray, and that is what I will do now. Please don’t worry, and please don’t try to find me. I will contact you soon after the New Year. 
-
-It remains for me to thank you for all your support over these last months and years. As Nicholas I have found your support and encouragement invaluable. In my new identity I have a feeling that it will be essential. 
-
-Sincerely yours, 
-
-Harry 
\ No newline at end of file
diff --git a/2012/8b.ciphertext b/2012/8b.ciphertext
deleted file mode 100644 (file)
index 2dfdbea..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-WJX SUE IXNSON DHZDUFZ_L KU YTL VLGWSBBAT XWD JML UWFRO_CHQVH ODZRGKT – EUU BDTQXPS ELV MDSGB NDVA IOLQY_NRZ EUXXSOOX TDWKCZTL MU TH. WGW_ AJX NZYVT YMWSQTX. G ULPWO QI PFSUVK USNPYFPO GO VTIWX DDFVB _SWCLXO_Q FT PUW SAAVTB FA EQK _AB QXO, WKN WW FYWLES PZGOSOUN RQ WB NDVR JLZEGQWLP QXD S_IOXMC XUD MMLB NZY X_B MQ ENK PLDUWME. D SLAJWVD AQF WLKP VCLAS QI PFSUUK XZLTXUPO UO VTSUK DTZUCLYPV, SFC WGX_ XVUX IMD_AAZ O_ DCEYWNMKX OTK M ARB LPVEK WDVF NZ RIILLJI_H VTSWK UUDSN ZPOYTD RZWBJMMXAR ZENST. TUV OWDBHWFRY JKKALW NAM ZEAOUBKX AQ WGX REAJSKLVGMPLA ITO AH NTSZYG NUDUC BFEFIXW AIUILEH NB. YTYU IDEE UTCAWW HBA RBCH I NDXS, BKO W DBE GTCAWU IDVW GWIM WGX_ HIOXF RE OB RJWG. IHIVB NZYY YFEGO KFP FY UXTSTZT V_JX GMOLQ W KOU_N SVVR AAAUSD XNWG L YTV_D OBJUU ITYW DAX NON DAWV NVOZ UCKQOQ LSUO_BS QO. 
-VFY _EOXLHJ UHKE XUVG LQWIA PWJFGJ, THNX IKOALCCOX TS WGX RQF YXZHID FU QENXWOWBTX. Q AEB OBQVXT RXUN ITYV HAD VMCAXLW NF RFZX CSTJFD WXTWMPF IX JOS L IAS QKKZCI LF OFUB MA KQH DSZWJ WR JMUXF SV NBDUWC NZYJ. DHQS VBOX TEO VEGUOKWDVF, LAW OG W DVVE HAD QG GZSACKQ ZVQ UGA QJ DAHPXGOZA VB L_DB. W DVVE NVOOU BETJP NZ RIILLJISH W OEV WLRGNWKT QZD P OEW AQXL UFK SEQ, LRW UCLEOIV HAS FXA VTV UXMMUHCME OYY XNDB TZEE. LHQS OYY AM THNF Y_WB ZPJ ENDST IB BC QJ UUA, HMN PIEQWGJ OYY Z_DD W ANBED DCUT UUA QJ JXMB OU OTVSTAR O_ NEY O_NELSBPWLUC BDESHCAE. WGXY HRAX ZPLV FB TOWGZE SBRX EEQ LRW WE MXS XUVQ EUU FB_VONJGI_U MQ QRKF YSNXYTVV.
-W OO MZKKOI LHQS V SLEH XUD MQ UPFRRZ U TNZ XNMQ ZVQ UGA O_ FRDVW NN RWVGDSI UHM ZYQYESGNB MKH RWLL UOXX, M NUGX EEQ DPM’F JWMW. V SLEH AGRJL WJX _RQCKUF_NNF HV QFRJUH NLY NCYDDUS FF TUW UUA_O MPO, XUKKS, WHFER ZUXCUTJFX J TRNZPIIXA AURWGJ WIX SBW. VX SBO GF RGAEKO AKN WA TVUMF AITNJKK _FI SIS TDOI WF KLVR FB. WISH MQKNXFR WVPDSIM, 
-
-NWXVVWMC. 
\ No newline at end of file
diff --git a/2012/8b.plaintext b/2012/8b.plaintext
deleted file mode 100644 (file)
index a2f051a..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-The gas weapon developed by the Fabulists had one distinctive feature – the strange red marks that afflicted everyone affected by it. This was their undoing. I began to gather accounts of these marks appearing on the bodies of our own men, and it became apparent to me that Valentine and Proteus had sold the gas to our enemies. I labored for many years to gather evidence of their treachery, but they were skilled in deception and I was never able to establish their guilt beyond reasonable doubt. The Fabulists proved too valuable to the establishment and an uneasy truce settled between us. They were unsure how much I knew, and I was unsure what risk they posed to us both. While they could not be certain what proof I might have lodged with a third party they did not dare take action against me. 
-Now however they have grown strong, with influence at the top levels of government. I was warned that they had decided to take action against me and I was forced to fake my own death in order to escape them. That left you vulnerable, and so I have had to prepare for you to disappear as well. I have taken steps to establish a new identity and a new life for you, and Charles has all the resources you will need. What you do with this new start is up to you, but knowing you well I would urge you to join my friends in the intelligence services. They have need of people like you and we may have the opportunity to work together.
-I am afraid that I have had to choose a new name for you in order to prepare the documents you will need, I hope you don’t mind. I have taken the opportunity to honour the courage of the young man, Harry, whose execution I witnessed during the war. He was no coward and it seems fitting for his name to live on. With fondest regards, 
-
-Tiberius. 
\ No newline at end of file
diff --git a/2013/1a.ciphertext b/2013/1a.ciphertext
deleted file mode 100644 (file)
index aefe481..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-LMIZ XPQT, 
-
-PWE KWCTL Q XIAA CX BPM WXXWZBCVQBG BW EWZS WV BPQA? Q PIL I KZIKS IB IVWBPMZ WN BPM VWBMA GWC NWCVL QV UWVBUIZBZM. QB TWWSA TQSM BPM WTLMAB QBMU QV BPM XIKSMB IVL Q BPWCOPB QB UQOPB JM I OWWL XTIKM BW ABIZB. QB UISMA AWUM AMVAM WN BPM JCKPMVEITL ZMNMZMVKM QV BPM TIBMZ VWBM GWC AMVB. 
-
-QB LQLV'B MFXTIQV BPM XIZQA TQVS AW Q AMVB I BMIU QVBW BPIB VMQOPJWCZPWWL BW OIBPMZ QVBMT JCB BPMG LQLV'B KWUM CX EQBP DMZG UCKP. EM LQL OMB WVM ZMXWZB BPIB BPM PWCAM PIL JMMV WEVML JG I OMZUIV NIUQTG JMNWZM BPM EIZ, JCB BPIB QB PIL JMMV BISMV WDMZ JG IV AA WNNQKMZ QV VQVMBMMV NWZBG WVM. ACZMBM ZMKWZLA ACOOMAB BPIB BPM NIUQTG KIUM NZWU EMQUIZ QV ICOCAB VQVMBMMV BPQZBG AMDMV, EPQKP QA ACOOMABQDM OQDMV BPM BQUQVO IVL BPM OMWOZIXPG, AW Q PIDM AMVB BPM BMIU BW JCKPMVEITL BW AMM EPIB BPMG KIV NQVL. 
-
-Q IU RCUXQVO BW KWVKTCAQWVA PMZM, JCB BPM XWZBZIQB AIZIP UMVBQWVA PIA BW JM BPM UWVI TQAI. Q PIDM JMMV BZGQVO BW OMB IKKMAA BW QB, JCB BPM NZMVKP ICBPWZQBQMA IZM AXWWSML. BPM BPMNB WN BPM XIQVBQVO JG XMZCOOQI JIKS QV VQVMBMMV MTMDMV PIA UILM BPMU DMZG AMVAQBQDM. BPM VIUM KPICLZWV EIA UMVBQWVML UWZM BPIV WVKM, IVL Q VMML AWUM BQUM BW TWWS QVBW BPM PQABWZG. 
-
-QN GWC PIDM IVG QVNTCMVKM IB ITT IB BPM UCAMCU Q BPQVS EM VMML I XZWXMZ MFIUQVIBQWV WN BPM XIQVBQVO, IVL Q VMML BW SVWE EPIB PIXXMVML BW QB LCZQVO BPM EIZ. 
-
-ITT BPM JMAB, 
-
-PIZZG
\ No newline at end of file
diff --git a/2013/1a.plaintext b/2013/1a.plaintext
deleted file mode 100644 (file)
index da08fbf..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-DEAR PHIL, 
-
-HOW COULD I PASS UP THE OPPORTUNITY TO WORK ON THIS? I HAD A CRACK AT ANOTHER OF THE NOTES YOU FOUND IN MONTMARTRE. IT LOOKS LIKE THE OLDEST ITEM IN THE PACKET AND I THOUGHT IT MIGHT BE A GOOD PLACE TO START. IT MAKES SOME SENSE OF THE BUCHENWALD REFERENCE IN THE LATER NOTE YOU SENT. 
-
-IT DIDN'T EXPLAIN THE PARIS LINK SO I SENT A TEAM INTO THAT NEIGHBOURHOOD TO GATHER INTEL BUT THEY DIDN'T COME UP WITH VERY MUCH. WE DID GET ONE REPORT THAT THE HOUSE HAD BEEN OWNED BY A GERMAN FAMILY BEFORE THE WAR, BUT THAT IT HAD BEEN TAKEN OVER BY AN SS OFFICER IN NINETEEN FORTY ONE. SURETE RECORDS SUGGEST THAT THE FAMILY CAME FROM WEIMAR IN AUGUST NINETEEN THIRTY SEVEN, WHICH IS SUGGESTIVE GIVEN THE TIMING AND THE GEOGRAPHY, SO I HAVE SENT THE TEAM TO BUCHENWALD TO SEE WHAT THEY CAN FIND. 
-
-I AM JUMPING TO CONCLUSIONS HERE, BUT THE PORTRAIT SARAH MENTIONS HAS TO BE THE MONA LISA. I HAVE BEEN TRYING TO GET ACCESS TO IT, BUT THE FRENCH AUTHORITIES ARE SPOOKED. THE THEFT OF THE PAINTING BY PERUGGIA BACK IN NINETEEN ELEVEN HAS MADE THEM VERY SENSITIVE. THE NAME CHAUDRON WAS MENTIONED MORE THAN ONCE, AND I NEED SOME TIME TO LOOK INTO THE HISTORY. 
-
-IF YOU HAVE ANY INFLUENCE AT ALL AT THE MUSEUM I THINK WE NEED A PROPER EXAMINATION OF THE PAINTING, AND I NEED TO KNOW WHAT HAPPENED TO IT DURING THE WAR. 
-
-ALL THE BEST, 
-
-HARRY
\ No newline at end of file
diff --git a/2013/1b.ciphertext b/2013/1b.ciphertext
deleted file mode 100644 (file)
index 9e551da..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-YWBRBSGG WG HC PS TCIBR SJSFMKVSFS, SJSB WB HVWG GHWBYWBU DZOQS. HVS UIOFRG HOYS OKOM OBMHVWBU HVSM QOB HVOH AWUVH PFWBU IG GCAS XCM, PIH HVSM QOB'H HOYS SJSFMHVWBU. GCAS CT HVS UWFZG GWBU, CHVSFG HSZZ GHCFWSG HC YSSD HVS TSOF OH HVS SRUS CT CIF VSOFHG - WH BSJSF QCADZSHSZM ZSOJSG IG - OBR AM DWQHIFSG OFS OZZ W VOJS HC CTTSF WB FSHIFB. DODSF WG DFSQWCIG OBR ACGH CT AM DOWBHWBUG OBR GYSHQVSG OFS VWRRSB CB HVS FCIUV KCCRSB GZOHG CT CIF PIBYG IBRSF HVS HVWB AOHHFSGGSG. RSHOWZ WG WADCGGWPZS, PIH KCIZR PS VOFR SJSB CB TWBS QOBJOG UWJSB HVS DWUASBHG W QOB AOYS TFCA HVS PFWQY RIGH, GCWZ OBR GQFIPPM KSSRG WB HVS QOAD. W OA HVOBYTIZ SJSFMROM TCF AM UFOBRTOHVSF'G WBGWGHSBQS HVOH OB OFHWGH GVCIZR PS OPZS HC AOYS HVSWF CKB QCZCIFG. KVSB W RC TWBR DODSF, W KFWHS. HVWG UFSOGM GQFOD KOG HVS KFODDWBU CB O UIOFR'G GOBRKWQV OBR HVS UFSOGS KCIZR AOYS WH WADCGGWPZS HC DOWBH CB SJSB WT W KOBHSR HC, PIH QVOFQCOZ TOZZSB TFCA O UIOFR'G PFONWSF GSSAG HC KCFY TWBS. 
-
-HVS CHVSFG WB AM RCFAWHCFM HSZZ AS HC FSQCFR OG AIQV OG W QOB. BCBS CT IG YBCK WT KS KWZZ ZWJS HC HSZZ HVS KCFZR CT HVS HSFFWPZS HVWBUG HVOH VODDSB VSFS, GC W RFOK OBR, KVSB W QOB, W KFWHS, OZKOMG KWHV CBS SOF ZWGHSBWBU TCF HVS QFIBQV CT O PCCH CB HVS UFOJSZ CIHGWRS. HVS GHCBSG OFS GVOFD OBR HVS GCZRWSFG RCB'H UWJS IG TCCHKSOF. WH WG OBCHVSF KOM HC VIAWZWOHS IG OBR KSOF IG RCKB, PIH HVSM RC BCH FSOZWGS HVOH HVWG ASOBG HVOH KS QOB OZKOMG HSZZ KVSB HVSM OFS QCAWBU. YWBRBSGG WG HC PS TCIBR SJSFMKVSFS VSFS, SJSB WB HVSWF GHIDWR QFISZHM. 
\ No newline at end of file
diff --git a/2013/1b.plaintext b/2013/1b.plaintext
deleted file mode 100644 (file)
index 1e22a0f..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-KINDNESS IS TO BE FOUND EVERYWHERE, EVEN IN THIS STINKING PLACE. THE GUARDS TAKE AWAY ANYTHING THEY CAN THAT MIGHT BRING US SOME JOY, BUT THEY CAN'T TAKE EVERYTHING. SOME OF THE GIRLS SING, OTHERS TELL STORIES TO KEEP THE FEAR AT THE EDGE OF OUR HEARTS - IT NEVER COMPLETELY LEAVES US - AND MY PICTURES ARE ALL I HAVE TO OFFER IN RETURN. PAPER IS PRECIOUS AND MOST OF MY PAINTINGS AND SKETCHES ARE HIDDEN ON THE ROUGH WOODEN SLATS OF OUR BUNKS UNDER THE THIN MATTRESSES. DETAIL IS IMPOSSIBLE, BUT WOULD BE HARD EVEN ON FINE CANVAS GIVEN THE PIGMENTS I CAN MAKE FROM THE BRICK DUST, SOIL AND SCRUBBY WEEDS IN THE CAMP. I AM THANKFUL EVERYDAY FOR MY GRANDFATHER'S INSISTENCE THAT AN ARTIST SHOULD BE ABLE TO MAKE THEIR OWN COLOURS. WHEN I DO FIND PAPER, I WRITE. THIS GREASY SCRAP WAS THE WRAPPING ON A GUARD'S SANDWICH AND THE GREASE WOULD MAKE IT IMPOSSIBLE TO PAINT ON EVEN IF I WANTED TO, BUT CHARCOAL FALLEN FROM A GUARD'S BRAZIER SEEMS TO WORK FINE. 
-
-THE OTHERS IN MY DORMITORY TELL ME TO RECORD AS MUCH AS I CAN. NONE OF US KNOW IF WE WILL LIVE TO TELL THE WORLD OF THE TERRIBLE THINGS THAT HAPPEN HERE, SO I DRAW AND, WHEN I CAN, I WRITE, ALWAYS WITH ONE EAR LISTENING FOR THE CRUNCH OF A BOOT ON THE GRAVEL OUTSIDE. THE STONES ARE SHARP AND THE SOLDIERS DON'T GIVE US FOOTWEAR. IT IS ANOTHER WAY TO HUMILIATE US AND WEAR US DOWN, BUT THEY DO NOT REALISE THAT THIS MEANS THAT WE CAN ALWAYS TELL WHEN THEY ARE COMING. KINDNESS IS TO BE FOUND EVERYWHERE HERE, EVEN IN THEIR STUPID CRUELTY. 
\ No newline at end of file
diff --git a/2013/2a.ciphertext b/2013/2a.ciphertext
deleted file mode 100644 (file)
index 5de755e..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-AFEEZ, 
-D LFHARO DS F UFQVNE TDKA F UEDRSO DS KAR HNERKR FSO AR XVK PR FLLRHH KV KAR YDLKNER. VNE XNZH LFS AFQR UDUKRRS PDSNKRH TDKA ARE FUKRE LMVHDSX KDPR VS UEDOFZ. KARZ TVS’K FMMVT FSZKADSX KVV DSQFHDQR INK TR HAVNMO XRK HVPR YDLKNERH VU KAR LFSQFH FSO UEFPR, FSO KARZ FER VUUREDSX KV IEDRU NH VS KAR YFDSKDSX’H PVQRPRSKH ONEDSX KAR TFE.  
-ERLVEOH UEVP INLARSTFMO TRER HJRKLAZ INK TR KEFLRO KAR UFPDMZ KAFK VTSRO KAR FYFEKPRSK DS PVSKPFEKER. FH ZVN XNRHHRO, KARZ PVQRO KARER TARS INLARSTFMO VYRSRO. KAR UFKARE, OFSDRM, TFH GRTDHA, KAVNXA KARZ HRRP KV AFQR PFSFXRO KV LVSLRFM KAFK UFLK. HVPR VU KARP PVQRO KV HTDKCREMFSO, KAR VKAREH KV UEFSLR, KAVNXA KAR KRFP ODO ARFE ERYVEKH KAFK OFSDRM’H IEVKARE DS MFT TFH PVER VE MRHH UVELRO KV KFJR NY TVEJ FH F XNFEO DS KAR LFPY HV TR AFQR FSVKARE MDSJ IRKTRRS KAR UFPDMZ FSO VNE PZHKREDVNH FEKDHK.  
-AVT HAR XVK KV UEFSLR DH F PZHKREZ, KEFQRM UVE F ZVNSX GRTDHA XDEM TVNMO AFQR IRRS AFCFEOVNH NSMRHH HAR TFH LFEEZDSX VUUDLDFM YFYREH. TR TDMM KEZ KV KEFLJ OVTS KAR INLARSTFMO XNFEO KAVNXA D OVS’K AVMO NY PNLA AVYR. SV VSR TAV ODO KAFK GVI YNK DK VS KARDE LQ FUKRETFEOH. 
-YADM
diff --git a/2013/2a.plaintext b/2013/2a.plaintext
deleted file mode 100644 (file)
index 4cb23e7..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-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.ciphertext b/2013/2b.ciphertext
deleted file mode 100644 (file)
index e47d3cb..0000000
+++ /dev/null
@@ -1 +0,0 @@
-NKRSA ZYIUA YOTYG XKOYA VVUYK QOTJO TZNKO XUCTC GEHAZ ZNKXK OYROZ ZRKCG XSZNO TZNKQ OTJTK YYOXK IKOBK GTTGZ XOKYZ USGQK SKIUS LUXZG HRKHA ZYNKO YGLXG OJZNK YYULL OIKXC NUHXO TMYAY ZNKVG OTZOT MYOYI XAKRG TJIUC GXJRE GTJNK HKGZY GTTGO LSECU XQOYT UZMUU JKTUA MNNKO YYIGX KJZNG ZOLNK HKGZY SKNKS OMNZJ GSGMK SENGT JYGTJ ZUUYI GXKJZ UHKGZ NKXNA YHGTJ JGTOK RGHKG XULGS GTCNU ZUCKX YUBKX NOSOZ JUKYT ZSGZZ KXZNK XKGRV UCKXR OKYCO ZNZNK HARRE NKIUA RJNGB KAYGR RYNUZ GTJCK GRRQT UCOZJ GTOKR YIGXK YSKZU UHAZU TREHK IGAYK NKXKS OTJYS KULNK RSAZG TJZNG ZXKSO TJYSK ULZNK IGSVN KTKBK XYVKG QYTKB KXRUU QYSKO TZNKK EKGTJ TKBKX CGTZY GTEZN OTMLX USSKO ZNOTQ NKNGZ KYSKL UXHXO TMOTM ZNKYY ZUNOY NUAYK HAZLU XGTTG YYGQK NKHXO TMYSK CNGZO TKKJC NGZOS UYZTK KJOYG CGEUA ZULNK XKCNK TOGSM UTKGT TGYHK GZOTM YCORR YZUVG TJSGE HKJGT OKRCO RRYZU VNGZO TMSKH AZOGS CGZIN KJGRR JGEGT JZNKN UAYKO YRUIQ KJGZT OMNZZ NGZCO RRTUZ YZUVS KLXUS ZXEOT M
diff --git a/2013/2b.plaintext b/2013/2b.plaintext
deleted file mode 100644 (file)
index 007d090..0000000
+++ /dev/null
@@ -1 +0,0 @@
-helmut's 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 goodenough he is scared that if he beats me he might damage my hands and too scared to beat her husband daniela 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 away 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/2013/3a.ciphertext b/2013/3a.ciphertext
deleted file mode 100644 (file)
index 628c9b0..0000000
+++ /dev/null
@@ -1 +0,0 @@
-LODDA RLSKS KKRDS CRNAQ AQKIB NAXSF QUSBY RQKMS RLRLQ INNOJ AMOKQ BIYEL RIESF QIYDR QCLEY AKOLQ OJOCL QBIRL SBEUY CLKLI MQJYB JQDYN RDOFS INQRV YRRLQ AUOBO EQJRI CORCL OKCDO PSBEI XFODB SKLXD IURLQ VOCGI XRLQP OSBRS BEOBJ XIYBJ LSELC IBCQB RDORS IBKIX NQOJR LQAJS JBIRQ TPQCR RLSKO BJMQO DQRDA SBERI EQRPQ DUSKK SIBRI TDOAL QDVYR RLQCY DORID SKBIR GQQBX IDLQD RIVQU IFQJO EOSBO XRQDR LQAQO DKIXR DOFQN JYDSB ERLQM ODIYD OEQBR KODQR DASBE RIRDO CGLQD UIFQU QBRKJ YDSBE RLORR SUQRI KQQML QBKLQ USELR LOFQV QQBVD IYELR RIUIB RUODR DQKLQ NQXRP ODSKI BRLQR MQBRA QSELR LIXOY EYKRZ YKRVQ XIDQR LQIYR VDQOG IXMOD OBJRD OFQNN QJSBO CIBFI AIXRL SDRAK QFQBR DYCGK RIOPN OCQCO NNQJC LOUVI DJSMS NNNQR AIYGB IMSXS LQODO BAUID QOVIY RLQDR DOFQN KOKXI DKODO LMQXI YBJIY RONSR RNQUI DQOVI YRLQD XOUSN AIBQI XRLQV YCLQB MONJB QSELV IYDKU QBRSI BQJOC IBBQC RSIBM SRLSR ONAML SCLSK KYEEQ KRSFQ ESFQB RLQPQ DYEES OKRID ARLIY ELQTO CRNAM LORRL QCIBB QCRSI BUSEL RVQSO UBIRK YDQUI DQMLQ BSLOF QRSUQ PLSN
diff --git a/2013/3b.ciphertext b/2013/3b.ciphertext
deleted file mode 100644 (file)
index a68290d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-SYIEZ LKKZR IVPYI MPQVZ FSLML CKILV WMPFU BIVSZ PYHLZ EPMLE VULER LMOQP PYIHK FGIMM FKYIC HIVDI ITHCL ZEPFV LEZIC PYLPP YIGFK NIKZI MSFQC VOIJQ ZUBCW VIPIU PIVZG SIQMI VPYID MYISL MHLZE PIVFE LHFHC LKOFL KVKLP YIKPY LELMP KIPUY IVULE RLMLE VPYIH ZNDIE PMQMI VOWPY IDLMP IKSIK IRIKW VZGGI KIEPG KFDPY IFEIM SIQMI PFVLW EFSPY IWOKZ ENDIP YIHZN DIEPM ZLMBG FKMFG PUYLC BWOCF FVKIV MLENQ ZEILE VDQMP LKVWI CCFSF UYKIM GKFDP YIMFZ CMFGZ PLCWZ DZTPY IDSZP YCZEM IIVFZ COFZC IVLEV LNIVZ ELBIP PCIHK FHIKC WHKIH LKIVP YIMIH LZEPM LKIZE VZMPZ ENQZM YLOCI GKFDP YIFEI MQMIV FEPYI FKZNZ ELCLE VPYIU FHWZM DFKIC ZBICW PFOIO IPKLW IVOWL ULKIC IMMOK QMYMP KFBIF KLDZM HCLUI VYZNY CZNYP PYIHK FGIMM FKMII MJQZU BCWSY IEDWP ZKIVI WIMYL RIDZM MIVLP FEILE VZYLR IDLVI IEFQN YVICZ OIKLP IDZMP LBIMP FUFER ZEUIP YIDPF DFRID WMPQV ZFPFP YILPP ZUSYI KIPYI CZNYP ZMOIP PIKGK FDPYI KIZYL RILRZ ISFGP YIUZP WLEVL KIDZE VIKFG GKIIV FDPYI WMPZC CZEMZ MPPYL PZMCI IHYIK IZEPY IUICC LKOQP PYLPN ZRIMD ILEFP YIKGK IIVFD PYIGC ZUBIK ZENUL EVCIM ULMPV IIHMY LVFSM SYZUY YZVID WFPYI KSFKB ZGZUL EEFPO IGKII HIKYL HMMYI ULE
diff --git a/2013/4a.ciphertext b/2013/4a.ciphertext
deleted file mode 100644 (file)
index b724af7..0000000
+++ /dev/null
@@ -1 +0,0 @@
-EVWZE AGJUU WMWHM CWCIA GAHIW CUNDC CANIW DCVAH IDZAI VAEMW CIWCU MCTID DYWII DWIMZ ROALD GAIVA PMGMC TCDDC AYCDP HPVMI VMEEA CATID WITJG WCUIV ARAMG HWIPM HBWHH WCUUW KACVD PZDCU WIPMH MPMRW NMCJC TAGHI MCTIV ALGAC NVGAZ JNIMC NAIDZ AIUDD LWIMU MWCWL DZZDP ATJER DJGZA MTDCN VMBOD GTMCT TWHND KAGAT IVMII VAZDJ KGAHE MWCIW CUHPA GAIGM CHLAG GATID ZDJKW UCRIV AMOOM RATAZ DNTWA JIVAB JHAAT ABDCI MJOMC MCTLW CMZZR IDBDC IMZJC TAGIV AHJEA GKWHW DCDLI VABJH AJBHT WGANI DGXMN FJAHX MJXMG TOJIW VMKAM LAAZW CUPAM GABWH HWCUH DBAIV WCUWC MZZIV WHXJH INMCI EJIBR LWCUA GDCWI NVMHW CUJEI VAOMN YUGDJ CTHID GRDCD JGRDJ CUEMW CIAGW IHAAB HZWYA VAGLM BWZRV MKAVM TMZDC UWCIA GAHIW CMGIG AHIDG MIWDC MCTWU JAHHI VMIWH PVAGA HVAZA MGCAT VAGHY WZZHO JIVAG DOKWD JHJCT AGHIM CTWCU DLMLD GUAGH PDGYB MYABA PDCTA GWLHD BADCA WCIVA LMBWZ RBMRO AIVAB JNVZD KATUG MCTLM IVAGV MTMZA HHDOK WDJHH DJGNA DLWCN DBANM CRDJL WCTDJ IBDGA MODJI IVABP VMIEM GIDLW IMZRT WTIVA LMBWZ RNDBA LGDBD GWUWC MZZRW PWZZC AATIV MIQGM RDLIV AEMWC IWCUM HHDDC MHRDJ NMCUA IWITD CAWVM KAMVJ CNVIV ADZTZ MTRWH VWTWC UBDGA IVMCV AGLAA ZWCUH OAVWC TIVMI HBWZA MZZIV AOAHI VMGGR
diff --git a/2013/4b.ciphertext b/2013/4b.ciphertext
deleted file mode 100644 (file)
index b64946e..0000000
+++ /dev/null
@@ -1 +0,0 @@
-WPSHC TSGZR LSKON JZSHJ CWONJ NTLSB TJDLN TLYDC BTSCV WXKHJ NSVJW BTJDJ KGCJN TLSCM SHSOS WCHJJ NTPSZ ZWCJN THNSV DPHWS BCDJH KGTPN SJNTH SPAKJ WYTEJ BRNSC VHATN WCVBR ASLYJ DNWVT JNTGT VEWOB TCJWN SVATT CPDGY WCOSC VNTHS WVCDJ NWCON THTTB HJDNS MTHDI JTCTV AKJWY CDPWL SCCDJ JGKHJ SCRDC TNTGT HNTBK HJCDJ ATVWH LDMTG TVNTG TDGJN TRPWZ ZJSYT SPSRB RZSHJ NDETD IGTHL KWCON TGSCV GTJKG CWCON TGJDJ NTONT JJDBR EZSCH JDTHL SETSG TDIZT HHWBE DGJSC LTAKJ BRJGS MTZVD LKBTC JHSGT CDPLD BEZTJ TJNTE SETGH SCVWC YHPTG TNSGV JDSLF KWGTA KJWTQ LKHTV BKLND IWJAR TQEZS WCWCO JNSJW CTTVT VJDHY TJLNJ DHNSG ETCBR HYWZZ HPNWL NNSVV TJTGW DGSJT VWCJN TLSBE WSBHS MWCOH KLNID DVSHB WONJZ SHJBD HJZRN SGVAG TSVSC VNSGV LNTTH TSOSW CHJJN TVSRH PNTCW NDETJ DGKCI GDBJN WHEZS LTCDP WPWZZ CTTVJ DIWCV SPSRJ DHJTS ZBDCT RJDES RIDGB RXDKG CTRBR EZSLT NWONW CJNTS JJWLO WMTHB TSMWT PDIJN TLWJR PNWLN NSHSZ ZDPTV BTJDB SYTSB SEJDO KWVTB TDCJN TBDDC ZTHHC WONJP NTCWP WZZIW CSZZR GKCSC VWYTT EJNTB SEPWJ NNTGS CVPWJ NJNWH VWSGR KCVTG JNTAD SGVHW PWZZZ WMTSC VWPWZ ZATIG TTSCV HDPWZ ZHNT
diff --git a/2013/5a.ciphertext b/2013/5a.ciphertext
deleted file mode 100644 (file)
index 4d91f4b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-BSTWI STHTH ISEWA HIZDH AGASH RTAGP EYIGT EHAYR TITHA IZJOS ZYEIZ REFGP BITSA KEYIS ARIZR EFGPB IAKTO EYEGE DZGAM STWEA YRTAW XZHIR TRYIO EIIST HZYEA IWEAH ITIIE WWHJH ISAIH SEOZI AMAPL JILEP ZYRIS AITAX YZIHJ GEMSA ISABB EYERM SEGER TRHSE OZRTR ISEBA TYITY OOZMT ISSEG AYRTD TIRTR SZMFZ XETIT HYZML AFVTY ISEWZ JKGER TRRAY TEWZG ISEHH ZDDTF EGDZW WZMSE GMSZM AHSER TRSED TYRSE GISEI GATWT HOZTY OFZWR AYRME YEERA YEMTR EATMA HMZYR EGTYO TDISE GEXTO SILEH ZXEIS TYOTY ISEHH AYOWE ISZHE OJPHM EGEYZ ISTYO TDYZI ISZGZ JOSRZ PZJSA KEAFF EHHIZ AYPHH BABEG HDGZX ISAIB AGIZD BAGTH TYISE MAGXA PLEIS EPVYE MMSAI MAHOZ TYOZY TAXSE ARTYO RZMYI ZIAWV IZAWD GERZO EGTSE MAHIS EREAW EGBEG JOOTA HSZME RISEX ZYAWT HAIZL AFVTY XAPLE SEVYZ MHHZX EISTY OALZJ IHAGA HDAXT WPTIH AWZYO HSZIL JIJYW EHHPZ JFZXE JBMTI SHZXE ISTYO DGZXI SEYAQ TMAGG EFZGR TITHA WWMES AKEAY PYEMH ZYISE NGAPS AGGP
diff --git a/2013/5b.ciphertext b/2013/5b.ciphertext
deleted file mode 100644 (file)
index 12a3408..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-NEWJXVOIYZFLRFJINDFVEQAESOGFEZKMXECCIQCRNPZJTBEOJEPFSXVLNDOWXRTRTZBNLRPLJWS WXUKWOLQBIGJESRWEKBPXMPSRWRNMSEVVEGVMHTXLQCGZJCMKMZGMMPOIESQSYDHVTBPXMPGKEV TWHPFKEVPXMLHKLRVLJQHYEFDIJYRZWPQZJCSUEAFXMLHZAVNPGPQRYTJXYSSJWBHJNNSIZVUMY DZVWFQJYPBESJVLFEVVMFUYWPWRQPCVWJWEKBWXYSSZVVPWYCITXVQRXTQRRAGZJCPVGRTXFTBN LRPLJHWCPAGBYLDGINTFZEVVWRGQJOGRXVUJNPRNMGJQDHCIOGJMXLTKIEPSTYOEHCGVMLDJLRY MQWBFXEGXZCBKSZQVWZKUEAKIQTGFJGGRTFHUYEKRLEVVHNAWTHWKLYWGPXMVWPCTJHWCPAQXGP RZWPQZJCSUYAVMQEVVESVIWYCFRNPHNAZRRGQFJLPFEEFXMPHIEVPFDEVVRZAHTNIDIAVWFCSII NFCYZCKLRAATFZURBVFJLFRGYQWJTBJTREXNZBSYGKJNNOEWGGEQLPFEEFEKFZCXECMSEVVRVVL NYYKLRAANWZJYSHMHPHYIWQYWYSPXBVLJDHRXVQRBTZCFRFMKQWTYYVMSEVVFYCGPZIKFHVQDXO GMFEPJLFRRQVLJXOKGUGWNDHFPRYMQWUZZROIJYCLKUNMLSHKSPJIHVHYIJCCNHWCPUKHJEVZWQ KEWJIEHRTXMPPFEEFWNYHYIPGPQLFNLRTIXSSYEFNMAPRWSEVLJWOJXSGARZBKLFKJFYMKLVPKM LDGIAUXTXSZHBPSYHOEXBWVXECICSQVLZHKIARIWSOGWBPIILMZAVNPWPHLVACRICSKVVGZJTHZ 
-JAQXFYRPSHCVJCSRHVPKYSWJXUGRBTGYQRNYHVGRVNJ
diff --git a/2013/6a.ciphertext b/2013/6a.ciphertext
deleted file mode 100644 (file)
index c6c1475..0000000
+++ /dev/null
@@ -1 +0,0 @@
-CPYYL GVVIR PDDVU BCSUP QOWPW SYBYP ODBCS PBBPR CSIOZ PTSTV HYVTW PYOZC OGCRV TTPUI BVGVS YOUGZ ZSRYS BPYLY SHSYY OUGBV BCSWP OUBOU GPUIR DSPYD LTSUB OVUOU GZPYP ZSSTZ DONSB CSLNU SJPAV EBBCS ZRPTV EYHYO SUIDL ZZVHH ORSYJ PZWDP UUOUG BVWED DBCSL WORNS IEWCS YBYPO DBCSU OGCBP HBSYZ CSJSU BTOZZ OUGAE BLVER PUYSP IPAVE BBCPB OUBCS OYYSW VYBZB ODDUV MVLVU GSBBO UGPRR SZZBV BCSVY OGOUP DTOZZ TVUPO UBCSG PDDSY LPUIO PTASG OUUOU GBVBC OUNJS TOGCB USSIB VYVDD VEBPA DPRNA PGMVA LVEJP UBBVI VOBVY ZCPDD OALBC SJPLO JPZZE YWYOZ SIALB COZYS WVYBB CSVBC SYWPW SYZJS CPFSH YVTBC SUPQO ZPBBC OZDSF SDPYS SURYL WBSIE ZOUGA OHOIV YWDPL HPOYZ BLDSR OWCSY ZBCOZ VUSOZ UBTPL ASBCS ROWCS YRDSY NJPZV HHIEB LBCPB IPLJS GVBDE RNL
diff --git a/2013/6b.ciphertext b/2013/6b.ciphertext
deleted file mode 100644 (file)
index 80dac83..0000000
+++ /dev/null
@@ -1 +0,0 @@
-HITHH NFRFE RTEAO FFTNA SLTYO RRREQ THIMS ERULR HFSET AEEIU IWSIH BNRRT SIOII ENIRH MRPYT DTOEI RCITA LNBRP NHTOH ORLIE WTSHT ESPOS OTOYN UWHRE DHHCP ICMNO OTAHA SHTIJ EANET OFRNE USRAG MXURT TOWLE ATBRT EPPTR AAESE NETHH RISNR STSTR NFLDO GHAUM GSESE AKUNT IAHYT TNYUN TNNVH IGWLE WFIAP ASREL FAIEB APCMC PLAHE THTOL HWSUL ADSEU VEAEO TAEUT ATEEF EHLBH TRSHG ATLIA CEEHT RNHGA ASIET UFNNP UREHR ELITT MUDYI NNUEG ICOUE NDEEI AHSUE LHTNO AHTIE AINYF DNIAU OENAT IYEFO HEDAL UAROE RYHUR AERAT ERAHI AONGT WISWS AITBU LTAOM XLETO REOTO TONAO ORTGB CVAIP NLEEW FYRTA EOADU WWETR RTNLR PFPAI ELLRI MNTRO WIEQR ECUAR NDOTA FNROT ELETP ENRPM SHNDD ETDEW HEFOY PEDEN NSNEE GTATE EANES ERTGD LUEOS RBURO WHDGB RPAHE NYTTE KRERT RRHNF NEDOL TSWSI ANIYP OTHMO UOCTY EIEEP ONHKR NNTAI RLTEE IUREM NITAP HOEAO HHNOU UMTKV SENED EEOID PWKIE GTIII OSENH UUFAN BEUIT HRAER HIEEH UAYAS RUSIW GADSI SITRL GFPHI LTWII SIHES URMRO MACEI SOILV DEOEL USAIR IDEOT NFIES OBNTS APOFG SODRT FIRPL TANET RLYIO SOTYO ESSFN TPHEA IGEAO RAIEI TDMTA AEGRH YASRR CFELR TLEEA NEHVE HIVMH NASSI EROIX LMPSJ TTESO FBMRH NDIOC HECNB TTNCO MPUSE SOEHT ENETF IENOO TNWOO TEERI LTOIG DOSME HOIFM LROEF FDTUE SOFLE RWIIY QDBZO TTNRF ANTDI GONTA LAEPD SHEAM NTHLP SNBTU OAHAA LPLEM NPDRS HVNAI AELNH CALIS KACDO AEDTJ GHOIE ADGWA YNDET ENHEG EEUEO EEDNO RYYRF CTEMT TWNTG DETAS UOOOT FWYMI HRGRH OESIN RRAOF RETFE NPOYA ISSES STNHH AYEUL HIWPC TEATU APEAN LUEEL WAHAO ELURE SNBII EASAE TEAGC DCSOR EPSRO ENSEL VOSED UDSIT LTEIT TFSEO ESNLN GINOE RNTEI EIWWL WHTEI RSIIL HTDSR NDESR FHRNT LGRSU ASEDA DOYTA SADUT ENWIT CNAME TERTP OESYT OTOCN YUTSO GCMUD LPADL EADOT EFDSB FELEA HAXRS ONIDT IEIPR ASHIC DCSHI PBIEL SLNAL HORFR ENTAT ORAIE MKLAG RETMR DCWSN AYNWS VNULD OREKU TNNOU TIIUN NHVNI EILOH LTEFN AEATU IFTTA CETLN NRBHB EGLOS NAONM IFKOA RONSN VNFRE TRCFT HDETP SWSUC PERCW TPOAW FHDAY ISOOA GOAEL NDFIG NGRTE BLTLL GFO
diff --git a/2013/7a.ciphertext b/2013/7a.ciphertext
deleted file mode 100644 (file)
index e9b7458..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-WWPA, AWHCRH MDY IOT NJHGK HJWLSBALH HI AWL BBHLJT, X DTUI PC VC MGPSHN HCK AHXK AVL BCAXS PMILG JAVHPCN IPBL. PZ ESPUCLS AWL RYPAT DPZ SLAPKLGLS AD AWLXY NHGK DU UYXKPF PMILGUDVC, ADV AHIL UVG HCFDUT AD WGVRLHZ XA, PUS AWL QVPYS DPZ THHF IV SLIHRO UYDT IOT IPZT. LMJTSALCA XKTH IV BHZL IOT WPPCAXUV SDVZ SXRT WPYI VU AWL QVM IN AWL LHN - UD-VCL LHH NDPCN IV IBGU XA DCTY IV AVDR XM IOTF SPSU’I RCVL PI DPZ IOTYT, HCK IOTF LLGL EYTAIF JUAPZLAF IV QL AVDRXUV MDY HVBLDUT AD ZBBVNAL P WPPCAXUV PC HCFLHN. 
-HRJTZH AD AWL VHASTYN DPZ HAGHXNWAUVGDPYS HCK XA IVDR PYDBCK IDTUIF BPCBILH AD ZLPIJW AWL RVEF LPIO IOT VGPVPCHA. P WPS AWL EHXUIPCN PTDUV H QBCJW VU YTWGVSBRAXVCZ XU IOT TJZTBB ZWVE HCK RHBWTK DBI MDY IOT UXNWA XU IOT NJHGKH’ IPAWYDVB. AJYCZ DBI AWLN WGLULG AD BHL IOT KXYTJIVGZ’ UHRPAPIPTZ JW DU IOT ADW USDVG. DXAW AWL CLL LMOXIXAXVC VELCPCN DU HHIBGKPF IOT WAHRL LHH IJZN LCVJNW AD ZAPE VJA UPGZI AWPCN PUS, HH HGYPUVLS, P BHSL HBGL X DPZ UPGZI PCAD AWL HODW. X UDD WHKL IOT ODUDBG VU OPCXUV IDBVOI AWL ROTHELHA TCTY LVGR QF SH KPCJX. VG UDA. 
-IOT E-GHN YTZJSIZ RHBL QHRR IOXZ BVGUXUV HCK, PZ NVJ ZJZELRATK, IOXZ XZ DUT VU ZPYP’Z UHZLH. P PT IVAK XA XZ RSDZT AD WTYULRA, QBI, OXKSLC BCKTY IOT SPFTYH VU WPPCA, HOT ZRYXIQSTK P WXJIBGL DM IOT UPGX LPNAL TTQSTT XU ALPK. HOT ZXNCLS PI Z IVD. AWL ILRO VBNZ IOXUZ ZWL BHN OPCT BHLS H QPI VU VAK EPEL APZL P JGHNVC AD KTMPJT AWL QVPYS ITMDYT ZWL HAPYILS DDYZ VC PI. HCFLHN, AWHI STHKLH AWL FBTZIPDU DM LOTYT AWL WLAS IOT YTHA WPPCAXUV TXNWA QL. XA’H OPYS AD ITSXLKL IOPA HOT STMI PI DXAW AWL HZ PUS P RHC’A HLT OTY VVXUV VC AWL GBC DXAW PI ZIBRR JUSLG OTY RVPA. XA’H UDA APZL HOT JDBAK GVAS XA JW. 
-X DDYZLS AWYDBVO HVBL BVGL DM IOT UPGX WPWTYH HCK UVJUS AWPH UDAT. HI STHHA XA ILASH BH DWLGL HOT DTUI. SDVZZ APZL IOT JXWWLG JALGR LHH IPJZ IN AWL LHN. P WHKL BVKLS VC AD CTUXJT AD AGF IV UPCK PUN AGHRL DM HHGH IOTYT, IJA X OPCT H ULTSXUV AWL HVABIPDU IV IOXZ BFHATYN PH IPJZ PC WPYXZ LOTYT PI HAS QLVHC. P ALUA IOT WPPCAXUV HI AWL EHGPH VUMXJT. TPFQL NVJ JDBAK PYGHCNT AD YTAJYC PI? PI ZWVJSS IT LPZXLG AD NTA XA XU IOPU XA LHH AD LMAGHRA XA. 
-PSA AWL QLHA, 
-WHGYN
diff --git a/2013/7b.ciphertext b/2013/7b.ciphertext
deleted file mode 100644 (file)
index b842206..0000000
+++ /dev/null
@@ -1 +0,0 @@
-TTFTK IESFO EYTYL ETTKF OYUHT TIENH HNTPR NMEPL KLFHF NEFEN NNTMM OAIOH KTITM URPSO EGEOF CMYMH TEPOY ITKCO YTFTG PGTYM RHTEP CRNYD EFUOT CTKYR CCTIM ANRMQ LHMKT TTCTS THRYC YUHVG MTHYD EFYHE FYFNO PMHOE TGEET TTXKR QCTOF YNYTF HTMYE MNNFV NEHHT YTRFR TUOHT MOHRG RTXYO HNTUH RGHUB FHHTH OTGWG KITTY QHEOW TNHCY TGPGY WCWFM AIFTM RPCYF MTOET YIHEO NYDHT PTFAE TRHKY UTYTT NEAFH FMFUW CTHUY OMQGF TYIRT HHNOO TMNRG NMTTO HFMKO CYFTF HHTKO CAYQP HAECX YETFO TMHVO VHYIH EOYWC RTHUY OFMCH TETMF PUYMH TKRUG OOYTF TTNEA FFTTG PGKTQ OPBHN NYPTT MTTKY XLOCK KYHMA CCTYE KYUGM EVHMT XTUMT MTMMT HMKTS CFPOR HOTHT OTBRP IOTUB OOYRY YKFTY YNYEW GTTYH KYURT EMMOA YUEKL FRHYO TCMHY TECIY FTFNE FENCO TRQBB NUOYU HUAYQ TMMOO TATNY UFWIY HNTXT TONTY TURND CHFLI IPTNR TOOOR TDTTI EXYHO TETIE ETBZC LGBEW FBWWH YIWEO GOUOT ATBBZ VVAWI YMDVI ZGGBF ACDSI WAAGU EYNNZ LHALF XORPB ALEAE NFBID UATBV NXWLL YFIXT BHEUH YWVLH IYYMX DALXG SFDEG DEDDW EBVDK IDGGV LMBUD EWLKU WAWMV AAYHK DALXD OSWMK CNWUL GEWUM BHLOH NPYDE WIPWT BDGEU DEUVD FGXLI VEUDM AMERP FFCNK MZGLH WZHDC GKMZA BYOZL HKSOE EZGBT BQAKE NIHVV AVLHE UQRZH BUDFE WYKLA YKYBG EWQZK ENHHA IIYSB WFSIL LQBWV LWHXB WHWYF KRVMA BIGKZ IWOIW GFAHY NILXC MZHUL HLTWX RMAOT BDGHU LRAVQ DIVMM ATIUS BZOLS OLOAQ ZKENQ RVGLA BIGPF DKWTS XXAIX CTFNP GKYFI XTBWH XBWAF OHEUL WWNWL GDTWW WOEFH LOHBM ALGSG WWTHI UMGXT GRLOH YORKR OWKEY EHSXE LUDKD LELLR MBWWP MVFRQ RAGRD IYNGY BKYXD FRUOR TSLQB WCLWV FYIKX GBFBL DGMBL NNHFY LOTBC DSIWC DLBUD ABBTN PIABC PZOXE NLBNW VKTFI ZIGUO RGLFG HTQRP AVAHB ILWYS TMHFM GEGAF BBZHW XNRSB LBRL
diff --git a/2013/mona-lisa-words.txt b/2013/mona-lisa-words.txt
deleted file mode 100644 (file)
index 0ce029c..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-samothrace
-paume
-musees
-musee
-valenay
-jeu
-montal
-montauban
-louvigny
-abbaye
-curated
-jaujard
-jahan
-loc
-albinguillot
-dieu
-reinstallation
-koblenz
-fonkenell
-vaux
-laure
-guillaume
-chambord
diff --git a/2013/solutions.txt b/2013/solutions.txt
deleted file mode 100644 (file)
index 23c8cb2..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-# with open('2013/mona-lisa-words.txt') as f: mona_lisa_words = [line.rstrip() for line in f]
-# keyword_break(c4a, wordlist=mona_lisa_words)
-
-c1a = open('2013/1a.ciphertext').read()
-c1b = open('2013/1b.ciphertext').read()
-c2a = open('2013/2a.ciphertext').read()
-c2b = open('2013/2b.ciphertext').read()
-c3a = open('2013/3a.ciphertext').read()
-c3b = open('2013/3b.ciphertext').read()
-c4a = open('2013/4a.ciphertext').read()
-c4b = open('2013/4b.ciphertext').read()
-c5a = open('2013/5a.ciphertext').read()
-c5b = open('2013/5b.ciphertext').read()
-c6a = open('2013/6a.ciphertext').read()
-c6b = open('2013/6b.ciphertext').read()
-c7a = open('2013/7a.ciphertext').read()
-c7b = open('2013/7b.ciphertext').read()
-
-p1a = caesar_decipher(c1a, 8)
-p1b = caesar_decipher(c1b, 14)
-p2a = affine_decipher(c2a, 3, 3, True)
-p2b = caesar_decipher(c2b, 6)
-p3a = affine_decipher(c3a, 7, 8, True)
-p3b = keyword_decipher(c3b, 'louvigny', 2)
-p4a = keyword_decipher(c4a, 'montal', 2)
-p4b = keyword_decipher(c4b, 'salvation', 2)
-p5a = keyword_decipher(c5a, 'alfredo', 2)
-p5b = vigenere_decipher(sanitise(c5b), 'florence')
-p6a = keyword_decipher(c6a, 'parishighcommand', 2)
-p7a = vigenere_decipher(sanitise(c7a), 'hp')
-
diff --git a/SIGNED.md b/SIGNED.md
new file mode 100644 (file)
index 0000000..d07ec2a
--- /dev/null
+++ b/SIGNED.md
@@ -0,0 +1,130 @@
+##### Signed by https://keybase.io/neilnjae
+```
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v2
+
+iQIcBAABCAAGBQJWjpkcAAoJEJPB2e07PgbqyX4QAIMe/BAgFiLDcxDXp6IUQvd8
+TSkZitbbe4WVSiGZ2rsS/LbuHeJr7WGBnUYACp1AeMeJqE62mPl0xbForExH7rRS
+PWF9qw8H+Ie6Cu6KeF9hPbAje+24pntjUT/49slb3zNwcmPP3IytA20w50T6Arw7
+aDq7pZ8IUfWnxTR6ZeWLWDo1rRjNMumQ4CmjcP24HElEm84IJJE9sBpd1uqGDHzW
+q12wajgwO8jANVdAAxXHye3QieEINzvkCNBShhIwE1/oxYs0Gl94UwSVtHuAFqxv
+oul5THS9WFdDCafhgqQkjJC0iOgk9VY833TGIBYzHVA4ktPJmxVvjiDa2aG9vybZ
+JJ5MUriSjnf/K65KJl/5mt9bZtskteS5xP0njzjv2579vD2qiqTsX7h8WgYmTjKe
+ZxyICi/c5fg2188J0qyr0AUYX9blF3ixlGnovZqXbGa1hIjW2HgZUUrTrvkhyLw5
+RwH5B98LIsmVyI0ZNAQejkyHweUYscwyBS0SZDmu5r+23FJ4wlLNUHi2ThK0ep7e
+2ix7QQ3qKsaISDcl6xxARSnBPqScJVHwb8cxI47KeBkVwE48zqaw6BfxjF7IskeN
+ypU/7vjy5XjgwxnTanjYZr8LfnpO84I6qMibL1SRz6YgUkzml6Yp+Nq3viBuv1nh
+6rhe8Q/XLCg5I3VvegZt
+=Ry9+
+-----END PGP SIGNATURE-----
+
+```
+
+<!-- END SIGNATURES -->
+
+### Begin signed statement 
+
+#### Expect
+
+```
+size     exec  file                                            contents                                                                                                                         
+               ./                                                                                                                                                                               
+384              .gitignore                                    a93de2ae5c2a47a38599751d1f914566569dfa09dd1778e207117db6c71421dd                                                                 
+18025            LICENSE                                       a01259a1b522cf0de95824f9860613b453153eebac468e96196d5d7dba84786c                                                                 
+61               README.md                                     277247b410300ee16477b12ca54ad878d81c8061f6134e2e1cadccaf299de3a3                                                                 
+469              affine_break_parameter_trials.csv             1a9d635d0af2f41fc6f1e83ae87d6372034259321ba288a11fb024e98ed52f4f|dd9c840434de596a30c84e79de26a9824b36c217a84876c2aab0579b76999735
+6488666          big.txt                                       fa066c7d40f0f201ac4144e652aa62430e58a6b3805ec70650f678da5804e87b                                                                 
+514              caesar_break_parameter_trials.csv             6586223bcc00e06e3ff79d107202d6c29ef962a6dd544add00610c5907407e85|1cb7cc77831ef3ef4f994a9ea77e82a841b38acdde45ede9cedbe7a54f1e8e46
+135303           challenge6.ipynb                              5b37a8b10db4c8d9831827a2acdffdcdb65369557d15b3e08a900ee8e088da73                                                                 
+75506            challenge7.ipynb                              ee9a99fa7a9845ad7db77199927fe8ad1d05a6b0272e50d8175e874e7a3e4cdf                                                                 
+318              cipher-training.sublime-project               58e5d5b4e54fb29abecaef2d41266e3355adccb8b6a70bd595e509bd07c16587                                                                 
+42922            cipher.py                                     58637b8946b4fb973b19a374a2066a896d86c928dacaa1ccd2252e6f8bb6e810                                                                 
+28908            cipherbreak.py                                0fb22645ddce4e04c7e441a1f7bdc0e4a397a3c9b2cfb3098bcb213e79a361c9                                                                 
+11564            count_1edit.txt                               3bf563ef032ba151ec1a4b2d1f33f50c49f4a47e4dc5b8152394bc5b63f57655|b5fbacbebcc25f5011ce97bc9ac967a09c50eef28b4aa98379a6c426df6ac08b
+223              count_1l.txt                                  335388d457db6ef1da05d8b55ab879e9be7d4e021085efc8d9dfeac0e4a79aa9                                                                 
+4956241          count_1w.txt                                  51df159fd3de12b20e403c108f526e96dbd723d9cabdd5f17955cdc16059e690                                                                 
+9270             count_2l.txt                                  bc2895f800189070c193907cd8bca956ad65fed2e25c14300d4bb5b6a243ba99                                                                 
+5566017          count_2w.txt                                  781c0596c3eea532d30bef9f3dba1d5137d652f00376260822c761a7584dfb8c                                                                 
+220441           count_3l.txt                                  8702c95530c7d0d182ab94dc03ed7681fcf969819f6db011a58de31411dc6365                                                                 
+320508           count_big.txt                                 3ba257fba1934bd138413d8274e79b56c5992431a27692fd562929aa43ec01a3                                                                 
+3355             find_best_affine_break_parameters.py          6b11004bb93ac26ec7d42d33504e758edbaf9d55365ae2e4ca2fca7589263f25                                                                 
+3027             find_best_caesar_break_parameters.py          0347d80309179d937a88fd1c8684490a513ccd086366c5a0dd55b8a2fe5c565f                                                                 
+1236             find_wikipedia_titles.py                      f040bf855dfec7fff9d8e5eba2fb509179bc53bc02a20b26b7fc61fef983aa45                                                                 
+5645             language_models.py                            bfd5b60cdef8af20cdb061b24a1691f569984be3be333782c3d76e3370e16d14                                                                 
+368              lettercount.py                                ed36497d62cf75b91994055e4a18848b2fabe5ce793cd76a77fabfc94d81d4f3                                                                 
+592              make-cracking-dictionary.py                   71791e64e4853cd9ca292cb436bbe8c72dd60f509811174df93ed2067683d5c1                                                                 
+7077             norms.py                                      a657a36c1741e6f3a513386b318fcc99e6b11f98ec64a48284b47462ff2acf30                                                                 
+8411             norms.pyc                                     ac7a18765c7bcc27e406d8f38d943408097b3384a271502185d53482e6ec0da7|002b186e716cec64869a00bd2d72e16614931e696daa0cf3529d634a0f270e42
+112847           plot-caesar-parameters.ipynb                  639459b4b2e434f9f0852c012ed9a8a8d87bd1cb6c2d65ca5abfdb0e42c3dea6                                                                 
+881              segment.py                                    94d257cc6151861ef3d3033c4d2d03d8c121b0a982344abf400f65fd507fed28                                                                 
+4538523          shakespeare.txt                               6f9c770efced5c3d87efa6197cd3091b982341372e36c6357f865df91ddecde6                                                                 
+592309           sherlock-holmes.txt                           0027de6f4110440ea51d67a2f3af3484898c630808f13b1d4db108e6283e67a3|2034ee1ebdec47e839607124d22b674d4614e1cc6209d758f7b6e99e69ae8e08
+                 slides/                                                                                                                                                                        
+2493               affine-break.html                           e2ffcbe50ceefb51638a54163829f9eec880a43a900cb7d0e945ce2df153f036                                                                 
+6441               affine-encipher.html                        4f239d2d9e0ef1f5080d1ab3cbb7c876ea1997e5b6f2b6ba0ff5099297006d8c                                                                 
+3320               aims.html                                   a45e8f4b0cc2987656a1b008351e089dcdc2a717aa1b6aa540bf4e8a4435fe17                                                                 
+6835               alternative-plaintext-scoring.html          c313d095c04faa6dae6c57fc20dd5b94f08746c4e8352c73178f335328a8a02d                                                                 
+7831               c1a_frequency_histogram.png                 a79cdaebf4db843aae7e302c2cb3c4606908465f5d6aed702c5c33d591780561|13ea628dccda1a22116fce7fc348b0977b451ba76f671184e45dcad239db6dd6
+8116               caesar-break.html                           786312aa2d85b655d084af45120abb937d65137f19cb9f8e7635107569cbbc94                                                                 
+3793               caesar-encipher.html                        66d4b2d96571a9d7edb10f79d176327efbc3923af2e19c7f61800eea376716e3                                                                 
+7860               caesarwheel1.gif                            fd5a9d2d8ef261b0b7ec4536fc56a27ebec94ac91ff2ca136b74d5c066f3ecce|4c536ee4df63c73c2e5e213ca1f96c2fea0bc058efe991f78fd304ff215e6fcd
+8200               english_frequency_histogram.png             c4a1afec62d2fcda15824f71df3c997088c4a952ee5fe0bc6fa753ede08b2098|6eabd4ebdc616722c9fe3a419e8ca5fc309452120e5023b2e5cb783b9d6d2df8
+9192               fast-good-cheap.gif                         4bc052364a91f4c7f98d5ac4e5ac6abd3a3968cabc7f892eb7c3b987adf9e793|4359cbb234f29ca93ff2fa8dd931ce95dab97cd723788937c5d5d259f913afb7
+2714               further-work.html                           66339213b16c1a98e4afc5c1ec4878bb4839c43ae963e56dd4be624fc60b8895                                                                 
+31180              gcd.svg                                     d5b93a7fe870742df02c201d8e12172f2a67798376c54761281c0a660160e753                                                                 
+2870               index.html                                  f6c2cbaaaeb43db84e9e1bbd2654c31103e22ae3bdf683bfe6d6719a074c9024                                                                 
+5312               keyword-break.html                          3217d573ee8ce0ce73e57d23122dec2de39088d006eb0af16d14405361e99d6c                                                                 
+5456               keyword-encipher.html                       d8d54fc7ebc88b52bade6c3da2ba81bceb110beeb1a82ff5ffd3fa2593ecdab8                                                                 
+2989               pocket-enigma-break.html                    aff9bd947680764ebc7fbf7e62cee948f290b1b81f4c2c2f819734ed24c34da1                                                                 
+6195               pocket-enigma-encipher.html                 d930d9149da4ca6766343524aa7df77a64bceaa5264f97bad48574bf0f46e69b                                                                 
+108903             pocket-enigma-small.jpg                     df9796ce51dbd5b86c1c1ec8a3a6806a77a67025c4dd4400676d24ae53b02cfe|395240459ad459032cab96c25d7ad682faaf7e4e2d9c58f64175ce5eb5467235
+409764             pocket-enigma.jpg                           aeb79ca953b7fac863340d71f675a50029687aa97bae8af4068927414aeec96c|0fd2d5b1683451ecee1a6501c4ccfa311293e15bcdb063314776493e5746a04b
+3460               transposition-break.html                    5d3df37e584ac2b0cf2a6b49cc9276bf0964cf4290bda35e808467c12224b2ea                                                                 
+5758               transposition-encipher.html                 2c1c3e64dc875de00a481eefe782fd1a812a9035a10a27e993ccf9414e087762                                                                 
+52398              typingmonkeylarge.jpg                       04eba431d38b1d9b5a89065c6a6571e28cddb7052ade379b532d4475ab99cf4a|1357b8bbc859ae4487dac3e431463a2df0ac46851baf24e2811a70bc3b11100c
+15756              vector-dot-product.svg                      7dbdf0245ee01f8c920518164ef88f3978312a85ef0e9b6c7771c5a053227d26                                                                 
+9845               vector-subtraction.svg                      25bf3a4c46253c529f9fe801c350e26f34401e8176496b1de2041b329cd8f1d8                                                                 
+8918               word-segmentation.html                      f39cb54c31412c00c5bdeadcc235f261663596293ecb639921d6dc79ac1fafa8                                                                 
+451530           spell-errors.txt                              a4abe6ce6c24280f9a8d0485cbf78ddd2e58279ca01293692630a08ba4b13407                                                                 
+45378            unknown-word-probability-investigation.ipynb  a866c807557980091a284bec04ad49a22c3ff14554ea6dca3edd71157318d52a                                                                 
+3291641          war-and-peace.txt                             3ed0f41cfdf660846878943bad5b9d575bcae1e4a92ee9a7f43d3c9dba2af344|6799e48d3fd0a6f4c40b9951ec86de6da81f0b9cd36e413490ac511542ca54d3
+868202           words.txt                                     aa77abbcba3c6dee1306d93adcedc2b2ccb8a4e0344a39d0676732ff58ebd5e5                                                                 
+868384           words_2013.txt                                57faa4841fe28dd82a5da4488b6381c194df6e1ecc04e61fb9f60e842bbca18c                                                                 
+```
+
+#### Ignore
+
+```
+/SIGNED.md
+```
+
+#### Presets
+
+```
+git  # ignore .git and anything as described by .gitignore files
+```
+
+<!-- summarize version = 0.0.9 -->
+
+### End signed statement
+
+<hr>
+
+#### Notes
+
+With keybase you can sign any directory's contents, whether it's a git repo,
+source code distribution, or a personal documents folder. It aims to replace the drudgery of:
+
+  1. comparing a zipped file to a detached statement
+  2. downloading a public key
+  3. confirming it is in fact the author's by reviewing public statements they've made, using it
+
+All in one simple command:
+
+```bash
+keybase dir verify
+```
+
+There are lots of options, including assertions for automating your checks.
+
+For more info, check out https://keybase.io/docs/command_line/code_signing
\ No newline at end of file
diff --git a/cipher-training.sublime-project b/cipher-training.sublime-project
new file mode 100644 (file)
index 0000000..23662f1
--- /dev/null
@@ -0,0 +1,23 @@
+{
+       "folders":
+       [
+               {       "file_exclude_patterns":
+                       [
+                               "*.png",
+                               "*.jpg",
+                               "*.ipynb"
+                       ],
+                       "folder_exclude_patterns":
+                       [
+                               "*.ipynb_checkpoints",
+                               "__pycache__"
+                       ],
+                       "follow_symlinks": true,
+                       "path": "/home/neil/Documents/programming/cipher-training"
+               }
+       ],
+       "settings":
+       {
+               "tab_size": 4
+       }
+}
index f5c5d33f412108c045f47effc1e93c221e90c118..266237a65a70b070e2ea8bc41d49f273477eda2c 100644 (file)
--- a/cipher.py
+++ b/cipher.py
@@ -2,7 +2,10 @@ import string
 import collections
 import math
 from enum import Enum
-from itertools import zip_longest, cycle, chain
+from itertools import zip_longest, cycle, chain, count
+import numpy as np
+from numpy import matrix
+from numpy import linalg
 from language_models import *
 
 
@@ -451,7 +454,7 @@ def column_transposition_decipher(message, keyword, fillvalue=' ',
     'hellothere'
     """
     transpositions = transpositions_of(keyword)
-    message += pad(len(message), len(transpositions), '*')
+    message += pad(len(message), len(transpositions), fillvalue)
     if emptycolumnwise:
         rows = every_nth(message, len(message) // len(transpositions))
     else:
@@ -507,6 +510,388 @@ def scytale_decipher(message, rows):
         fillcolumnwise=True, emptycolumnwise=False)
 
 
+def railfence_encipher(message, height, fillvalue=''):
+    """Railfence cipher.
+    Works by splitting the text into sections, then reading across them to
+    generate the rows in the cipher. The rows are then combined to form the
+    ciphertext.
+
+    Example: the plaintext "hellotherefriends", with a height of four, written 
+    out in the railfence as 
+       h h i
+       etere*
+       lorfns
+       l e d
+    (with the * showing the one character to finish the last section). 
+    Each 'section' is two columns, but unfolded. In the example, the first
+    section is 'hellot'.
+
+    >>> railfence_encipher('hellothereavastmeheartiesthisisalongpieceoftextfortestingrailfenceciphers', 2, fillvalue='!')
+    'hlohraateerishsslnpeefetotsigaleccpeselteevsmhatetiiaogicotxfretnrifneihr!'
+    >>> railfence_encipher('hellothereavastmeheartiesthisisalongpieceoftextfortestingrailfenceciphers', 3, fillvalue='!')
+    'horaersslpeeosglcpselteevsmhatetiiaogicotxfretnrifneihr!!lhateihsnefttiaece!'
+    >>> railfence_encipher('hellothereavastmeheartiesthisisalongpieceoftextfortestingrailfenceciphers', 5, fillvalue='!')
+    'hresleogcseeemhetaocofrnrner!!lhateihsnefttiaece!!ltvsatiigitxetifih!!oarspeslp!'
+    >>> railfence_encipher('hellothereavastmeheartiesthisisalongpieceoftextfortestingrailfenceciphers', 10, fillvalue='!')
+    'hepisehagitnr!!lernesge!!lmtocerh!!otiletap!!tseaorii!!hassfolc!!evtitffe!!rahsetec!!eixn!'
+    >>> railfence_encipher('hellothereavastmeheartiesthisisalongpieceoftextfortestingrailfenceciphers', 3)
+    'horaersslpeeosglcpselteevsmhatetiiaogicotxfretnrifneihrlhateihsnefttiaece'
+    >>> railfence_encipher('hellothereavastmeheartiesthisisalongpieceoftextfortestingrailfenceciphers', 5)
+    'hresleogcseeemhetaocofrnrnerlhateihsnefttiaeceltvsatiigitxetifihoarspeslp'
+    >>> railfence_encipher('hellothereavastmeheartiesthisisalongpieceoftextfortestingrailfenceciphers', 7)
+    'haspolsevsetgifrifrlatihnettaeelemtiocxernhorersleesgcptehaiaottneihesfic'
+    """
+    sections = chunks(message, (height - 1) * 2, fillvalue=fillvalue)
+    n_sections = len(sections)
+    # Add the top row
+    rows = [''.join([s[0] for s in sections])]
+    # process the middle rows of the grid
+    for r in range(1, height-1):
+        rows += [''.join([s[r:r+1] + s[height*2-r-2:height*2-r-1] for s in sections])]
+    # process the bottom row
+    rows += [''.join([s[height - 1:height] for s in sections])]
+    # rows += [' '.join([s[height - 1] for s in sections])]
+    return ''.join(rows)
+
+def railfence_decipher(message, height, fillvalue=''):
+    """Railfence decipher. 
+    Works by reconstructing the grid used to generate the ciphertext, then
+    unfolding the sections so the text can be concatenated together.
+
+    Example: given the ciphertext 'hhieterelorfnsled' and a height of 4, first
+    work out that the second row has a character missing, find the rows of the
+    grid, then split the section into its two columns.
+
+    'hhieterelorfnsled' is split into
+        h h i
+        etere
+        lorfns
+        l e d
+    (spaces added for clarity), which is stored in 'rows'. This is then split
+    into 'down_rows' and 'up_rows':
+
+    down_rows:
+       hhi
+       eee
+       lrn
+       led
+
+    up_rows:
+       tr
+       ofs
+
+    These are then zipped together (after the up_rows are reversed) to recover 
+    the plaintext.
+
+    Most of the procedure is about finding the correct lengths for each row then
+    splitting the ciphertext into those rows.
+
+    >>> railfence_decipher('hlohraateerishsslnpeefetotsigaleccpeselteevsmhatetiiaogicotxfretnrifneihr!', 2).strip('!')
+    'hellothereavastmeheartiesthisisalongpieceoftextfortestingrailfenceciphers'
+    >>> railfence_decipher('horaersslpeeosglcpselteevsmhatetiiaogicotxfretnrifneihr!!lhateihsnefttiaece!', 3).strip('!')
+    'hellothereavastmeheartiesthisisalongpieceoftextfortestingrailfenceciphers'
+    >>> railfence_decipher('hresleogcseeemhetaocofrnrner!!lhateihsnefttiaece!!ltvsatiigitxetifih!!oarspeslp!', 5).strip('!')
+    'hellothereavastmeheartiesthisisalongpieceoftextfortestingrailfenceciphers'
+    >>> railfence_decipher('hepisehagitnr!!lernesge!!lmtocerh!!otiletap!!tseaorii!!hassfolc!!evtitffe!!rahsetec!!eixn!', 10).strip('!')
+    'hellothereavastmeheartiesthisisalongpieceoftextfortestingrailfenceciphers'
+    >>> railfence_decipher('horaersslpeeosglcpselteevsmhatetiiaogicotxfretnrifneihrlhateihsnefttiaece', 3)
+    'hellothereavastmeheartiesthisisalongpieceoftextfortestingrailfenceciphers'
+    >>> railfence_decipher('hresleogcseeemhetaocofrnrnerlhateihsnefttiaeceltvsatiigitxetifihoarspeslp', 5)
+    'hellothereavastmeheartiesthisisalongpieceoftextfortestingrailfenceciphers'
+    >>> railfence_decipher('haspolsevsetgifrifrlatihnettaeelemtiocxernhorersleesgcptehaiaottneihesfic', 7)
+    'hellothereavastmeheartiesthisisalongpieceoftextfortestingrailfenceciphers'
+    """
+    # find the number and size of the sections, including how many characters
+    #   are missing for a full grid
+    n_sections = math.ceil(len(message) / ((height - 1) * 2))
+    padding_to_add = n_sections * (height - 1) * 2 - len(message)
+    # row_lengths are for the both up rows and down rows
+    row_lengths = [n_sections] * (height - 1) * 2
+    for i in range((height - 1) * 2 - 1, (height - 1) * 2 - (padding_to_add + 1), -1):
+        row_lengths[i] -= 1
+    # folded_rows are the combined row lengths in the middle of the railfence
+    folded_row_lengths = [row_lengths[0]]
+    for i in range(1, height-1):
+        folded_row_lengths += [row_lengths[i] + row_lengths[-i]]
+    folded_row_lengths += [row_lengths[height - 1]]
+    # find the rows that form the railfence grid
+    rows = []
+    row_start = 0
+    for i in folded_row_lengths:
+        rows += [message[row_start:row_start + i]]
+        row_start += i
+    # split the rows into the 'down_rows' (those that form the first column of
+    #   a section) and the 'up_rows' (those that ofrm the second column of a 
+    #   section).
+    down_rows = [rows[0]]
+    up_rows = []
+    for i in range(1, height-1):
+        down_rows += [''.join([c for n, c in enumerate(rows[i]) if n % 2 == 0])]
+        up_rows += [''.join([c for n, c in enumerate(rows[i]) if n % 2 == 1])]
+    down_rows += [rows[-1]]
+    up_rows.reverse()
+    return ''.join(c for r in zip_longest(*(down_rows + up_rows), fillvalue='') for c in r)
+
+def make_cadenus_keycolumn(doubled_letters = 'vw', start='a', reverse=False):
+    """Makes the key column for a Cadenus cipher (the column down between the
+        rows of letters)
+
+    >>> make_cadenus_keycolumn()['a']
+    0
+    >>> make_cadenus_keycolumn()['b']
+    1
+    >>> make_cadenus_keycolumn()['c']
+    2
+    >>> make_cadenus_keycolumn()['v']
+    21
+    >>> make_cadenus_keycolumn()['w']
+    21
+    >>> make_cadenus_keycolumn()['z']
+    24
+    >>> make_cadenus_keycolumn(doubled_letters='ij', start='b', reverse=True)['a']
+    1
+    >>> make_cadenus_keycolumn(doubled_letters='ij', start='b', reverse=True)['b']
+    0
+    >>> make_cadenus_keycolumn(doubled_letters='ij', start='b', reverse=True)['c']
+    24
+    >>> make_cadenus_keycolumn(doubled_letters='ij', start='b', reverse=True)['i']
+    18
+    >>> make_cadenus_keycolumn(doubled_letters='ij', start='b', reverse=True)['j']
+    18
+    >>> make_cadenus_keycolumn(doubled_letters='ij', start='b', reverse=True)['v']
+    6
+    >>> make_cadenus_keycolumn(doubled_letters='ij', start='b', reverse=True)['z']
+    2
+    """
+    index_to_remove = string.ascii_lowercase.find(doubled_letters[0])
+    short_alphabet = string.ascii_lowercase[:index_to_remove] + string.ascii_lowercase[index_to_remove+1:]
+    if reverse:
+        short_alphabet = ''.join(reversed(short_alphabet))
+    start_pos = short_alphabet.find(start)
+    rotated_alphabet = short_alphabet[start_pos:] + short_alphabet[:start_pos]
+    keycolumn = {l: i for i, l in enumerate(rotated_alphabet)}
+    keycolumn[doubled_letters[0]] = keycolumn[doubled_letters[1]]
+    return keycolumn
+
+def cadenus_encipher(message, keyword, keycolumn, fillvalue='a'):
+    """Encipher with the Cadenus cipher
+
+    >>> cadenus_encipher(sanitise('Whoever has made a voyage up the Hudson ' \
+                                  'must remember the Kaatskill mountains. ' \
+                                  'They are a dismembered branch of the great'), \
+                'wink', \
+                make_cadenus_keycolumn(doubled_letters='vw', start='a', reverse=True))
+    'antodeleeeuhrsidrbhmhdrrhnimefmthgeaetakseomehetyaasuvoyegrastmmuuaeenabbtpchehtarorikswosmvaleatned'
+    >>> cadenus_encipher(sanitise('a severe limitation on the usefulness of ' \
+                                  'the cadenus is that every message must be ' \
+                                  'a multiple of twenty-five letters long'), \
+                'easy', \
+                make_cadenus_keycolumn(doubled_letters='vw', start='a', reverse=True))
+    'systretomtattlusoatleeesfiyheasdfnmschbhneuvsnpmtofarenuseieeieltarlmentieetogevesitfaisltngeeuvowul'
+    """
+    rows = chunks(message, len(message) // 25, fillvalue=fillvalue)
+    columns = zip(*rows)
+    rotated_columns = [col[start:] + col[:start] for start, col in zip([keycolumn[l] for l in keyword], columns)]    
+    rotated_rows = zip(*rotated_columns)
+    transpositions = transpositions_of(keyword)
+    transposed = [transpose(r, transpositions) for r in rotated_rows]
+    return ''.join(chain(*transposed))
+
+def cadenus_decipher(message, keyword, keycolumn, fillvalue='a'):
+    """
+    >>> cadenus_decipher('antodeleeeuhrsidrbhmhdrrhnimefmthgeaetakseomehetyaa' \
+                         'suvoyegrastmmuuaeenabbtpchehtarorikswosmvaleatned', \
+                 'wink', \
+                 make_cadenus_keycolumn(reverse=True))
+    'whoeverhasmadeavoyageupthehudsonmustrememberthekaatskillmountainstheyareadismemberedbranchofthegreat'
+    >>> cadenus_decipher('systretomtattlusoatleeesfiyheasdfnmschbhneuvsnpmtof' \
+                        'arenuseieeieltarlmentieetogevesitfaisltngeeuvowul', \
+                 'easy', \
+                 make_cadenus_keycolumn(reverse=True))
+    'aseverelimitationontheusefulnessofthecadenusisthateverymessagemustbeamultipleoftwentyfiveletterslong'
+    """
+    rows = chunks(message, len(message) // 25, fillvalue=fillvalue)
+    transpositions = transpositions_of(keyword)
+    untransposed_rows = [untranspose(r, transpositions) for r in rows]
+    columns = zip(*untransposed_rows)
+    rotated_columns = [col[-start:] + col[:-start] for start, col in zip([keycolumn[l] for l in keyword], columns)]    
+    rotated_rows = zip(*rotated_columns)
+    # return rotated_columns
+    return ''.join(chain(*rotated_rows))
+
+
+def hill_encipher(matrix, message_letters, fillvalue='a'):
+    """Hill cipher
+
+    >>> hill_encipher(np.matrix([[7,8], [11,11]]), 'hellothere')
+    'drjiqzdrvx'
+    >>> hill_encipher(np.matrix([[6, 24, 1], [13, 16, 10], [20, 17, 15]]), \
+        'hello there')
+    'tfjflpznvyac'
+    """
+    n = len(matrix)
+    sanitised_message = sanitise(message_letters)
+    if len(sanitised_message) % n != 0:
+        padding = fillvalue[0] * (n - len(sanitised_message) % n)
+    else:
+        padding = ''
+    message = [ord(c) - ord('a') for c in sanitised_message + padding]
+    message_chunks = [message[i:i+n] for i in range(0, len(message), n)]
+    # message_chunks = chunks(message, len(matrix), fillvalue=None)
+    enciphered_chunks = [((matrix * np.matrix(c).T).T).tolist()[0] 
+            for c in message_chunks]
+    return ''.join([chr(int(round(l)) % 26 + ord('a')) 
+            for l in sum(enciphered_chunks, [])])
+
+def hill_decipher(matrix, message, fillvalue='a'):
+    """Hill cipher
+
+    >>> hill_decipher(np.matrix([[7,8], [11,11]]), 'drjiqzdrvx')
+    'hellothere'
+    >>> hill_decipher(np.matrix([[6, 24, 1], [13, 16, 10], [20, 17, 15]]), \
+        'tfjflpznvyac')
+    'hellothereaa'
+    """
+    adjoint = linalg.det(matrix)*linalg.inv(matrix)
+    inverse_determinant = modular_division_table[int(round(linalg.det(matrix))) % 26][1]
+    inverse_matrix = (inverse_determinant * adjoint) % 26
+    return hill_encipher(inverse_matrix, message, fillvalue)          
+
+
+# Where each piece of text ends up in the AMSCO transpositon cipher.
+# 'index' shows where the slice appears in the plaintext, with the slice
+# from 'start' to 'end'
+AmscoSlice = collections.namedtuple('AmscoSlice', ['index', 'start', 'end'])
+
+class AmscoFillStyle(Enum):
+    continuous = 1
+    same_each_row = 2
+    reverse_each_row = 3
+
+def amsco_transposition_positions(message, keyword, 
+      fillpattern=(1, 2),
+      fillstyle=AmscoFillStyle.continuous,
+      fillcolumnwise=False,
+      emptycolumnwise=True):
+    """Creates the grid for the AMSCO transposition cipher. Each element in the
+    grid shows the index of that slice and the start and end positions of the
+    plaintext that go to make it up.
+
+    >>> amsco_transposition_positions(string.ascii_lowercase, 'freddy', \
+        fillpattern=(1, 2)) # doctest:  +NORMALIZE_WHITESPACE
+    [[AmscoSlice(index=3, start=4, end=6),
+     AmscoSlice(index=2, start=3, end=4),
+     AmscoSlice(index=0, start=0, end=1),
+     AmscoSlice(index=1, start=1, end=3),
+     AmscoSlice(index=4, start=6, end=7)],
+    [AmscoSlice(index=8, start=12, end=13),
+     AmscoSlice(index=7, start=10, end=12),
+     AmscoSlice(index=5, start=7, end=9),
+     AmscoSlice(index=6, start=9, end=10),
+     AmscoSlice(index=9, start=13, end=15)],
+    [AmscoSlice(index=13, start=19, end=21),
+     AmscoSlice(index=12, start=18, end=19),
+     AmscoSlice(index=10, start=15, end=16),
+     AmscoSlice(index=11, start=16, end=18),
+     AmscoSlice(index=14, start=21, end=22)],
+    [AmscoSlice(index=18, start=27, end=28),
+     AmscoSlice(index=17, start=25, end=27),
+     AmscoSlice(index=15, start=22, end=24),
+     AmscoSlice(index=16, start=24, end=25),
+     AmscoSlice(index=19, start=28, end=30)]]
+    """
+    transpositions = transpositions_of(keyword)
+    fill_iterator = cycle(fillpattern)
+    indices = count()
+    message_length = len(message)
+
+    current_position = 0
+    grid = []
+    current_fillpattern = fillpattern
+    while current_position < message_length:
+        row = []
+        if fillstyle == AmscoFillStyle.same_each_row:
+            fill_iterator = cycle(fillpattern)
+        if fillstyle == AmscoFillStyle.reverse_each_row:
+            fill_iterator = cycle(current_fillpattern)
+        for _ in range(len(transpositions)):
+            index = next(indices)
+            gap = next(fill_iterator)
+            row += [AmscoSlice(index, current_position, current_position + gap)]
+            current_position += gap
+        grid += [row]
+        if fillstyle == AmscoFillStyle.reverse_each_row:
+            current_fillpattern = list(reversed(current_fillpattern))
+    return [transpose(r, transpositions) for r in grid]
+
+def amsco_transposition_encipher(message, keyword, 
+    fillpattern=(1,2), fillstyle=AmscoFillStyle.reverse_each_row):
+    """AMSCO transposition encipher.
+
+    >>> amsco_transposition_encipher('hellothere', 'abc', fillpattern=(1, 2))
+    'hoteelhler'
+    >>> amsco_transposition_encipher('hellothere', 'abc', fillpattern=(2, 1))
+    'hetelhelor'
+    >>> amsco_transposition_encipher('hellothere', 'acb', fillpattern=(1, 2))
+    'hotelerelh'
+    >>> amsco_transposition_encipher('hellothere', 'acb', fillpattern=(2, 1))
+    'hetelorlhe'
+    >>> amsco_transposition_encipher('hereissometexttoencipher', 'encode')
+    'etecstthhomoerereenisxip'
+    >>> amsco_transposition_encipher('hereissometexttoencipher', 'cipher', fillpattern=(1, 2))
+    'hetcsoeisterereipexthomn'
+    >>> amsco_transposition_encipher('hereissometexttoencipher', 'cipher', fillpattern=(1, 2), fillstyle=AmscoFillStyle.continuous)
+    'hecsoisttererteipexhomen'
+    >>> amsco_transposition_encipher('hereissometexttoencipher', 'cipher', fillpattern=(2, 1))
+    'heecisoosttrrtepeixhemen'
+    >>> amsco_transposition_encipher('hereissometexttoencipher', 'cipher', fillpattern=(1, 3, 2))
+    'hxtomephescieretoeisnter'
+    >>> amsco_transposition_encipher('hereissometexttoencipher', 'cipher', fillpattern=(1, 3, 2), fillstyle=AmscoFillStyle.continuous)
+    'hxomeiphscerettoisenteer'
+    """
+    grid = amsco_transposition_positions(message, keyword, 
+        fillpattern=fillpattern, fillstyle=fillstyle)
+    ct_as_grid = [[message[s.start:s.end] for s in r] for r in grid]
+    return combine_every_nth(ct_as_grid)
+
+
+def amsco_transposition_decipher(message, keyword, 
+    fillpattern=(1,2), fillstyle=AmscoFillStyle.reverse_each_row):
+    """AMSCO transposition decipher
+
+    >>> amsco_transposition_decipher('hoteelhler', 'abc', fillpattern=(1, 2))
+    'hellothere'
+    >>> amsco_transposition_decipher('hetelhelor', 'abc', fillpattern=(2, 1))
+    'hellothere'
+    >>> amsco_transposition_decipher('hotelerelh', 'acb', fillpattern=(1, 2))
+    'hellothere'
+    >>> amsco_transposition_decipher('hetelorlhe', 'acb', fillpattern=(2, 1))
+    'hellothere'
+    >>> amsco_transposition_decipher('etecstthhomoerereenisxip', 'encode')
+    'hereissometexttoencipher'
+    >>> amsco_transposition_decipher('hetcsoeisterereipexthomn', 'cipher', fillpattern=(1, 2))
+    'hereissometexttoencipher'
+    >>> amsco_transposition_decipher('hecsoisttererteipexhomen', 'cipher', fillpattern=(1, 2), fillstyle=AmscoFillStyle.continuous)
+    'hereissometexttoencipher'
+    >>> amsco_transposition_decipher('heecisoosttrrtepeixhemen', 'cipher', fillpattern=(2, 1))
+    'hereissometexttoencipher'
+    >>> amsco_transposition_decipher('hxtomephescieretoeisnter', 'cipher', fillpattern=(1, 3, 2))
+    'hereissometexttoencipher'
+    >>> amsco_transposition_decipher('hxomeiphscerettoisenteer', 'cipher', fillpattern=(1, 3, 2), fillstyle=AmscoFillStyle.continuous)
+    'hereissometexttoencipher'
+    """
+
+    grid = amsco_transposition_positions(message, keyword, 
+        fillpattern=fillpattern, fillstyle=fillstyle)
+    transposed_sections = [s for c in [l for l in zip(*grid)] for s in c]
+    plaintext_list = [''] * len(transposed_sections)
+    current_pos = 0
+    for slice in transposed_sections:
+        plaintext_list[slice.index] = message[current_pos:current_pos-slice.start+slice.end][:len(message[slice.start:slice.end])]
+        current_pos += len(message[slice.start:slice.end])
+    return ''.join(plaintext_list)
+
+
 class PocketEnigma(object):
     """A pocket enigma machine
     The wheel is internally represented as a 26-element list self.wheel_map, 
diff --git a/cipher.sublime-project b/cipher.sublime-project
deleted file mode 100644 (file)
index 54c826f..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-       "folders":
-       [
-               {
-                       "follow_symlinks": true,
-                       "path": "slides"
-               },
-               {
-                       "follow_symlinks": true,
-                       "path": "."
-               }
-       ]
-}
index 6e08f49b05f327e24481734b22d115f727048dd9..0ac8ae57f7ed11a443dfedc8366ddc51086eda8c 100644 (file)
@@ -1,12 +1,15 @@
+"""A set of functions to break the ciphers give in ciphers.py.
+"""
+
 import string
 import collections
 import norms
 import logging
 import random
-from itertools import zip_longest, cycle, permutations, starmap
+import math
+from itertools import starmap
 from segment import segment
 from multiprocessing import Pool
-from math import log10
 
 import matplotlib.pyplot as plt
 
@@ -32,27 +35,27 @@ for word in keywords:
 
 def frequencies(text):
     """Count the number of occurrences of each character in text
-    
+
     >>> sorted(frequencies('abcdefabc').items())
     [('a', 2), ('b', 2), ('c', 2), ('d', 1), ('e', 1), ('f', 1)]
     >>> sorted(frequencies('the quick brown fox jumped over the lazy ' \
          'dog').items()) # doctest: +NORMALIZE_WHITESPACE
-    [(' ', 8), ('a', 1), ('b', 1), ('c', 1), ('d', 2), ('e', 4), ('f', 1), 
-     ('g', 1), ('h', 2), ('i', 1), ('j', 1), ('k', 1), ('l', 1), ('m', 1), 
-     ('n', 1), ('o', 4), ('p', 1), ('q', 1), ('r', 2), ('t', 2), ('u', 2), 
+    [(' ', 8), ('a', 1), ('b', 1), ('c', 1), ('d', 2), ('e', 4), ('f', 1),
+     ('g', 1), ('h', 2), ('i', 1), ('j', 1), ('k', 1), ('l', 1), ('m', 1),
+     ('n', 1), ('o', 4), ('p', 1), ('q', 1), ('r', 2), ('t', 2), ('u', 2),
      ('v', 1), ('w', 1), ('x', 1), ('y', 1), ('z', 1)]
     >>> sorted(frequencies('The Quick BROWN fox jumped! over... the ' \
          '(9lazy) DOG').items()) # doctest: +NORMALIZE_WHITESPACE
-    [(' ', 8), ('!', 1), ('(', 1), (')', 1), ('.', 3), ('9', 1), ('B', 1), 
-     ('D', 1), ('G', 1), ('N', 1), ('O', 2), ('Q', 1), ('R', 1), ('T', 1), 
-     ('W', 1), ('a', 1), ('c', 1), ('d', 1), ('e', 4), ('f', 1), ('h', 2), 
-     ('i', 1), ('j', 1), ('k', 1), ('l', 1), ('m', 1), ('o', 2), ('p', 1), 
+    [(' ', 8), ('!', 1), ('(', 1), (')', 1), ('.', 3), ('9', 1), ('B', 1),
+     ('D', 1), ('G', 1), ('N', 1), ('O', 2), ('Q', 1), ('R', 1), ('T', 1),
+     ('W', 1), ('a', 1), ('c', 1), ('d', 1), ('e', 4), ('f', 1), ('h', 2),
+     ('i', 1), ('j', 1), ('k', 1), ('l', 1), ('m', 1), ('o', 2), ('p', 1),
      ('r', 1), ('t', 1), ('u', 2), ('v', 1), ('x', 1), ('y', 1), ('z', 1)]
-    >>> sorted(frequencies(sanitise('The Quick BROWN fox jumped! over... ' \
+    >>> sorted(frequencies(sanitise('The Quick BROWN fox jumped! over... '\
          'the (9lazy) DOG')).items()) # doctest: +NORMALIZE_WHITESPACE
-    [('a', 1), ('b', 1), ('c', 1), ('d', 2), ('e', 4), ('f', 1), ('g', 1), 
-     ('h', 2), ('i', 1), ('j', 1), ('k', 1), ('l', 1), ('m', 1), ('n', 1), 
-     ('o', 4), ('p', 1), ('q', 1), ('r', 2), ('t', 2), ('u', 2), ('v', 1), 
+    [('a', 1), ('b', 1), ('c', 1), ('d', 2), ('e', 4), ('f', 1), ('g', 1),
+     ('h', 2), ('i', 1), ('j', 1), ('k', 1), ('l', 1), ('m', 1), ('n', 1),
+     ('o', 4), ('p', 1), ('q', 1), ('r', 2), ('t', 2), ('u', 2), ('v', 1),
      ('w', 1), ('x', 1), ('y', 1), ('z', 1)]
     >>> frequencies('abcdefabcdef')['x']
     0
@@ -62,7 +65,7 @@ def frequencies(text):
 
 def caesar_break(message, fitness=Pletters):
     """Breaks a Caesar cipher using frequency analysis
-    
+
     >>> caesar_break('ibxcsyorsaqcheyklxivoexlevmrimwxsfiqevvmihrsasrxliwyrh' \
           'ecjsppsamrkwleppfmergefifvmhixscsymjcsyqeoixlm') # doctest: +ELLIPSIS
     (4, -130.849989015...)
@@ -80,7 +83,8 @@ def caesar_break(message, fitness=Pletters):
         plaintext = caesar_decipher(sanitised_message, shift)
         fit = fitness(plaintext)
         logger.debug('Caesar break attempt using key {0} gives fit of {1} '
-                      'and decrypt starting: {2}'.format(shift, fit, plaintext[:50]))
+                     'and decrypt starting: {2}'.format(shift, fit,
+                                                        plaintext[:50]))
         if fit > best_fit:
             best_fit = fit
             best_shift = shift
@@ -91,7 +95,7 @@ def caesar_break(message, fitness=Pletters):
 
 def affine_break(message, fitness=Pletters):
     """Breaks an affine cipher using frequency analysis
-    
+
     >>> affine_break('lmyfu bkuusd dyfaxw claol psfaom jfasd snsfg jfaoe ls ' \
           'omytd jlaxe mh jm bfmibj umis hfsul axubafkjamx. ls kffkxwsd jls ' \
           'ofgbjmwfkiu olfmxmtmwaokttg jlsx ls kffkxwsd jlsi zg tsxwjl. jlsx ' \
@@ -108,73 +112,83 @@ def affine_break(message, fitness=Pletters):
     for one_based in [True, False]:
         for multiplier in [x for x in range(1, 26, 2) if x != 13]:
             for adder in range(26):
-                plaintext = affine_decipher(sanitised_message, 
+                plaintext = affine_decipher(sanitised_message,
                                             multiplier, adder, one_based)
                 fit = fitness(plaintext)
                 logger.debug('Affine break attempt using key {0}x+{1} ({2}) '
                              'gives fit of {3} and decrypt starting: {4}'.
-                             format(multiplier, adder, one_based, fit, 
+                             format(multiplier, adder, one_based, fit,
                                     plaintext[:50]))
                 if fit > best_fit:
                     best_fit = fit
                     best_multiplier = multiplier
                     best_adder = adder
                     best_one_based = one_based
-    logger.info('Affine break best fit with key {0}x+{1} ({2}) gives fit of {3} '
-                'and decrypt starting: {4}'.format(
-                    best_multiplier, best_adder, best_one_based, best_fit, 
-                    affine_decipher(sanitised_message, best_multiplier, 
-                        best_adder, best_one_based)[:50]))
+    logger.info('Affine break best fit with key {0}x+{1} ({2}) gives fit of '
+                '{3} and decrypt starting: {4}'.format(
+                    best_multiplier, best_adder, best_one_based, best_fit,
+                    affine_decipher(sanitised_message, best_multiplier,
+                                    best_adder, best_one_based)[:50]))
     return (best_multiplier, best_adder, best_one_based), best_fit
 
 def keyword_break(message, wordlist=keywords, fitness=Pletters):
-    """Breaks a keyword substitution cipher using a dictionary and 
-    frequency analysis
+    """Breaks a keyword substitution cipher using a dictionary and
+    frequency analysis.
 
     >>> keyword_break(keyword_encipher('this is a test message for the ' \
-          'keyword decipherment', 'elephant', Keyword_wrap_alphabet.from_last), \
+          'keyword decipherment', 'elephant', KeywordWrapAlphabet.from_last), \
           wordlist=['cat', 'elephant', 'kangaroo']) # doctest: +ELLIPSIS
-    (('elephant', <Keyword_wrap_alphabet.from_last: 2>), -52.834575011...)
+    (('elephant', <KeywordWrapAlphabet.from_last: 2>), -52.834575011...)
     """
     best_keyword = ''
     best_wrap_alphabet = True
     best_fit = float("-inf")
-    for wrap_alphabet in Keyword_wrap_alphabet:
+    for wrap_alphabet in KeywordWrapAlphabet:
         for keyword in wordlist:
             plaintext = keyword_decipher(message, keyword, wrap_alphabet)
             fit = fitness(plaintext)
             logger.debug('Keyword break attempt using key {0} (wrap={1}) '
                          'gives fit of {2} and decrypt starting: {3}'.format(
-                             keyword, wrap_alphabet, fit, 
+                             keyword, wrap_alphabet, fit,
                              sanitise(plaintext)[:50]))
             if fit > best_fit:
                 best_fit = fit
                 best_keyword = keyword
                 best_wrap_alphabet = wrap_alphabet
     logger.info('Keyword break best fit with key {0} (wrap={1}) gives fit of '
-                '{2} and decrypt starting: {3}'.format(best_keyword, 
+                '{2} and decrypt starting: {3}'.format(best_keyword,
                     best_wrap_alphabet, best_fit, sanitise(
-                        keyword_decipher(message, best_keyword, 
+                        keyword_decipher(message, best_keyword,
                                          best_wrap_alphabet))[:50]))
     return (best_keyword, best_wrap_alphabet), best_fit
 
-def keyword_break_mp(message, wordlist=keywords, fitness=Pletters, chunksize=500):
-    """Breaks a keyword substitution cipher using a dictionary and 
+def keyword_break_mp(message, wordlist=keywords, fitness=Pletters,
+                     number_of_solutions=1, chunksize=500):
+    """Breaks a keyword substitution cipher using a dictionary and
     frequency analysis
 
     >>> keyword_break_mp(keyword_encipher('this is a test message for the ' \
-          'keyword decipherment', 'elephant', Keyword_wrap_alphabet.from_last), \
+          'keyword decipherment', 'elephant', KeywordWrapAlphabet.from_last), \
           wordlist=['cat', 'elephant', 'kangaroo']) # doctest: +ELLIPSIS
-    (('elephant', <Keyword_wrap_alphabet.from_last: 2>), -52.834575011...)
+    (('elephant', <KeywordWrapAlphabet.from_last: 2>), -52.834575011...)
+    >>> keyword_break_mp(keyword_encipher('this is a test message for the ' \
+          'keyword decipherment', 'elephant', KeywordWrapAlphabet.from_last), \
+          wordlist=['cat', 'elephant', 'kangaroo'], \
+          number_of_solutions=2) # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE
+    [(('elephant', <KeywordWrapAlphabet.from_last: 2>), -52.834575011...), 
+    (('elephant', <KeywordWrapAlphabet.from_largest: 3>), -52.834575011...)]
     """
     with Pool() as pool:
-        helper_args = [(message, word, wrap, fitness) 
-                       for word in wordlist 
-                       for wrap in Keyword_wrap_alphabet]
-        # Gotcha: the helper function here needs to be defined at the top level 
+        helper_args = [(message, word, wrap, fitness)
+                       for word in wordlist
+                       for wrap in KeywordWrapAlphabet]
+        # Gotcha: the helper function here needs to be defined at the top level
         #   (limitation of Pool.starmap)
-        breaks = pool.starmap(keyword_break_worker, helper_args, chunksize) 
-        return max(breaks, key=lambda k: k[1])
+        breaks = pool.starmap(keyword_break_worker, helper_args, chunksize)
+        if number_of_solutions == 1:
+            return max(breaks, key=lambda k: k[1])
+        else:
+            return sorted(breaks, key=lambda k: k[1], reverse=True)[:number_of_solutions]
 
 def keyword_break_worker(message, keyword, wrap_alphabet, fitness):
     plaintext = keyword_decipher(message, keyword, wrap_alphabet)
@@ -184,30 +198,34 @@ def keyword_break_worker(message, keyword, wrap_alphabet, fitness):
                      wrap_alphabet, fit, sanitise(plaintext)[:50]))
     return (keyword, wrap_alphabet), fit
 
-def monoalphabetic_break_hillclimbing(message, max_iterations = 10000000, 
-        fitness=Pletters):
+def monoalphabetic_break_hillclimbing(message, max_iterations=10000000, 
+        alphabet=None, fitness=Pletters):
     ciphertext = unaccent(message).lower()
-    alphabet = list(string.ascii_lowercase)
-    random.shuffle(alphabet)
-    alphabet = ''.join(alphabet)
+    if not alphabet:
+        alphabet = list(string.ascii_lowercase)
+        random.shuffle(alphabet)
+        alphabet = ''.join(alphabet)
     return monoalphabetic_break_hillclimbing_worker(ciphertext, alphabet,
-        max_iterations, fitness)
+                                                    max_iterations, fitness)
 
 def monoalphabetic_break_hillclimbing_mp(message, workers=10, 
-        max_iterations = 10000000, fitness=Pletters, chunksize=1):
+        max_iterations = 10000000, alphabet=None, fitness=Pletters, chunksize=1):
     worker_args = []
     ciphertext = unaccent(message).lower()
     for i in range(workers):
-        alphabet = list(string.ascii_lowercase)
-        random.shuffle(alphabet)
-        alphabet = ''.join(alphabet)
-        worker_args.append((ciphertext, alphabet, max_iterations, fitness))
+        if alphabet:
+            this_alphabet = alphabet
+        else:
+            this_alphabet = list(string.ascii_lowercase)
+            random.shuffle(this_alphabet)
+            this_alphabet = ''.join(this_alphabet)
+        worker_args.append((ciphertext, this_alphabet, max_iterations, fitness))
     with Pool() as pool:
         breaks = pool.starmap(monoalphabetic_break_hillclimbing_worker,
-            worker_args, chunksize)
+                              worker_args, chunksize)
     return max(breaks, key=lambda k: k[1])
 
-def monoalphabetic_break_hillclimbing_worker(message, alphabet, 
+def monoalphabetic_break_hillclimbing_worker(message, alphabet,
         max_iterations, fitness):
     def swap(letters, i, j):
         if i > j:
@@ -215,7 +233,8 @@ def monoalphabetic_break_hillclimbing_worker(message, alphabet,
         if i == j:
             return letters
         else:
-            return letters[:i] + letters[j] + letters[i+1:j] + letters[i] + letters[j+1:]
+            return (letters[:i] + letters[j] + letters[i+1:j] + letters[i] +
+                    letters[j+1:])
     best_alphabet = alphabet
     best_fitness = float('-inf')
     for i in range(max_iterations):
@@ -229,17 +248,94 @@ def monoalphabetic_break_hillclimbing_worker(message, alphabet,
     return best_alphabet, best_fitness
 
 
-def column_transposition_break_mp(message, translist=transpositions, 
-                     fitness=Pbigrams, chunksize=500):
-    """Breaks a column transposition cipher using a dictionary and 
+def vigenere_keyword_break_mp(message, wordlist=keywords, fitness=Pletters,
+                              chunksize=500):
+    """Breaks a vigenere cipher using a dictionary and frequency analysis.
+
+    >>> vigenere_keyword_break_mp(vigenere_encipher(sanitise('this is a test ' \
+             'message for the vigenere decipherment'), 'cat'), \
+             wordlist=['cat', 'elephant', 'kangaroo']) # doctest: +ELLIPSIS
+    ('cat', -52.947271216...)
+    """
+    with Pool() as pool:
+        helper_args = [(message, word, fitness)
+                       for word in wordlist]
+        # Gotcha: the helper function here needs to be defined at the top level
+        #   (limitation of Pool.starmap)
+        breaks = pool.starmap(vigenere_keyword_break_worker, helper_args,
+                              chunksize)
+        return max(breaks, key=lambda k: k[1])
+vigenere_keyword_break = vigenere_keyword_break_mp
+
+def vigenere_keyword_break_worker(message, keyword, fitness):
+    plaintext = vigenere_decipher(message, keyword)
+    fit = fitness(plaintext)
+    logger.debug('Vigenere keyword break attempt using key {0} gives fit of '
+                 '{1} and decrypt starting: {2}'.format(keyword,
+                     fit, sanitise(plaintext)[:50]))
+    return keyword, fit
+
+
+def vigenere_frequency_break(message, max_key_length=20, fitness=Pletters):
+    """Breaks a Vigenere cipher with frequency analysis
+
+    >>> vigenere_frequency_break(vigenere_encipher(sanitise("It is time to " \
+            "run. She is ready and so am I. I stole Daniel's pocketbook this " \
+            "afternoon when he left his jacket hanging on the easel in the " \
+            "attic. I jump every time I hear a footstep on the stairs, " \
+            "certain that the theft has been discovered and that I will " \
+            "be caught. The SS officer visits less often now that he is " \
+            "sure"), 'florence')) # doctest: +ELLIPSIS
+    ('florence', -307.5473096791...)
+    """
+    def worker(message, key_length, fitness):
+        splits = every_nth(sanitised_message, key_length)
+        key = ''.join([chr(caesar_break(s)[0] + ord('a')) for s in splits])
+        plaintext = vigenere_decipher(message, key)
+        fit = fitness(plaintext)
+        return key, fit
+    sanitised_message = sanitise(message)
+    results = starmap(worker, [(sanitised_message, i, fitness)
+                               for i in range(1, max_key_length+1)])
+    return max(results, key=lambda k: k[1])
+
+
+def beaufort_frequency_break(message, max_key_length=20, fitness=Pletters):
+    """Breaks a Beaufort cipher with frequency analysis
+
+    >>> beaufort_frequency_break(beaufort_encipher(sanitise("It is time to " \
+            "run. She is ready and so am I. I stole Daniel's pocketbook this " \
+            "afternoon when he left his jacket hanging on the easel in the " \
+            "attic. I jump every time I hear a footstep on the stairs, " \
+            "certain that the theft has been discovered and that I will " \
+            "be caught. The SS officer visits less often now " \
+            "that he is sure"), 'florence')) # doctest: +ELLIPSIS
+    ('florence', -307.5473096791...)
+    """
+    def worker(message, key_length, fitness):
+        splits = every_nth(sanitised_message, key_length)
+        key = ''.join([chr(-caesar_break(s)[0] % 26 + ord('a'))
+                       for s in splits])
+        plaintext = beaufort_decipher(message, key)
+        fit = fitness(plaintext)
+        return key, fit
+    sanitised_message = sanitise(message)
+    results = starmap(worker, [(sanitised_message, i, fitness)
+                               for i in range(1, max_key_length+1)])
+    return max(results, key=lambda k: k[1])
+
+
+def column_transposition_break_mp(message, translist=transpositions,
+                                  fitness=Pbigrams, chunksize=500):
+    """Breaks a column transposition cipher using a dictionary and
     n-gram frequency analysis
 
     >>> column_transposition_break_mp(column_transposition_encipher(sanitise( \
             "It is a truth universally acknowledged, that a single man in \
              possession of a good fortune, must be in want of a wife. However \
              little known the feelings or views of such a man may be on his \
-             first entering a neighbourhood, this truth is so well fixed in the \
-             minds of the surrounding families, that he is considered the \
+             first entering a neighbourhood, this truth is so well fixed in \
+             the minds of the surrounding families, that he is considered the \
              rightful property of some one or other of their daughters."), \
         'encipher'), \
         translist={(2, 0, 5, 3, 1, 4, 6): ['encipher'], \
@@ -250,8 +346,8 @@ def column_transposition_break_mp(message, translist=transpositions,
             "It is a truth universally acknowledged, that a single man in \
              possession of a good fortune, must be in want of a wife. However \
              little known the feelings or views of such a man may be on his \
-             first entering a neighbourhood, this truth is so well fixed in the \
-             minds of the surrounding families, that he is considered the \
+             first entering a neighbourhood, this truth is so well fixed in \
+             the minds of the surrounding families, that he is considered the \
              rightful property of some one or other of their daughters."), \
         'encipher'), \
         translist={(2, 0, 5, 3, 1, 4, 6): ['encipher'], \
@@ -261,21 +357,21 @@ def column_transposition_break_mp(message, translist=transpositions,
     (((2, 0, 5, 3, 1, 4, 6), False, False), -997.0129085...)
     """
     with Pool() as pool:
-        helper_args = [(message, trans, fillcolumnwise, emptycolumnwise, 
-                          fitness) 
-                       for trans in translist.keys() 
+        helper_args = [(message, trans, fillcolumnwise, emptycolumnwise,
+                        fitness)
+                       for trans in translist.keys()
                        for fillcolumnwise in [True, False]
                        for emptycolumnwise in [True, False]]
-        # Gotcha: the helper function here needs to be defined at the top level 
+        # Gotcha: the helper function here needs to be defined at the top level
         #   (limitation of Pool.starmap)
-        breaks = pool.starmap(column_transposition_break_worker, 
-          helper_args, chunksize) 
+        breaks = pool.starmap(column_transposition_break_worker,
+                              helper_args, chunksize) 
         return max(breaks, key=lambda k: k[1])
 column_transposition_break = column_transposition_break_mp
 
-def column_transposition_break_worker(message, transposition, 
+def column_transposition_break_worker(message, transposition,
         fillcolumnwise, emptycolumnwise, fitness):
-    plaintext = column_transposition_decipher(message, transposition, 
+    plaintext = column_transposition_decipher(message, transposition,
         fillcolumnwise=fillcolumnwise, emptycolumnwise=emptycolumnwise)
     fit = fitness(sanitise(plaintext))
     logger.debug('Column transposition break attempt using key {0} '
@@ -294,8 +390,8 @@ def scytale_break_mp(message, max_key_length=20,
             "It is a truth universally acknowledged, that a single man in \
              possession of a good fortune, must be in want of a wife. However \
              little known the feelings or views of such a man may be on his \
-             first entering a neighbourhood, this truth is so well fixed in the \
-             minds of the surrounding families, that he is considered the \
+             first entering a neighbourhood, this truth is so well fixed in \
+             the minds of the surrounding families, that he is considered the \
              rightful property of some one or other of their daughters."), \
         5)) # doctest: +ELLIPSIS
     (5, -709.4646722...)
@@ -303,102 +399,164 @@ def scytale_break_mp(message, max_key_length=20,
             "It is a truth universally acknowledged, that a single man in \
              possession of a good fortune, must be in want of a wife. However \
              little known the feelings or views of such a man may be on his \
-             first entering a neighbourhood, this truth is so well fixed in the \
-             minds of the surrounding families, that he is considered the \
+             first entering a neighbourhood, this truth is so well fixed in \
+             the minds of the surrounding families, that he is considered the \
              rightful property of some one or other of their daughters."), \
         5), \
         fitness=Ptrigrams) # doctest: +ELLIPSIS
     (5, -997.0129085...)
     """
     with Pool() as pool:
-        helper_args = [(message, trans, False, True, fitness) 
-            for trans in 
-                [[col for col in range(math.ceil(len(message)/rows))] 
+        helper_args = [(message, trans, False, True, fitness)
+            for trans in
+                [[col for col in range(math.ceil(len(message)/rows))]
                     for rows in range(1,max_key_length+1)]]
-        # Gotcha: the helper function here needs to be defined at the top level 
+        # Gotcha: the helper function here needs to be defined at the top level
         #   (limitation of Pool.starmap)
-        breaks = pool.starmap(column_transposition_break_worker, 
-          helper_args, chunksize) 
-        best = max(breaks, key=lambda k: k[1]) 
+        breaks = pool.starmap(column_transposition_break_worker,
+                              helper_args, chunksize)
+        best = max(breaks, key=lambda k: k[1])
         return math.trunc(len(message) / len(best[0][0])), best[1]
 scytale_break = scytale_break_mp
 
 
-def vigenere_keyword_break_mp(message, wordlist=keywords, fitness=Pletters, 
-                     chunksize=500):
-    """Breaks a vigenere cipher using a dictionary and 
-    frequency analysis
+def railfence_break(message, max_key_length=20,
+                     fitness=Pletters, chunksize=500):
+    """Breaks a hill cipher using a matrix of given rank and letter frequencies
 
-    >>> vigenere_keyword_break_mp(vigenere_encipher(sanitise('this is a test ' \
-             'message for the vigenere decipherment'), 'cat'), \
-             wordlist=['cat', 'elephant', 'kangaroo']) # doctest: +ELLIPSIS
-    ('cat', -52.947271216...)
+    
     """
-    with Pool() as pool:
-        helper_args = [(message, word, fitness) 
-                       for word in wordlist]
-        # Gotcha: the helper function here needs to be defined at the top level 
-        #   (limitation of Pool.starmap)
-        breaks = pool.starmap(vigenere_keyword_break_worker, helper_args, chunksize) 
-        return max(breaks, key=lambda k: k[1])
-vigenere_keyword_break = vigenere_keyword_break_mp
-
-def vigenere_keyword_break_worker(message, keyword, fitness):
-    plaintext = vigenere_decipher(message, keyword)
-    fit = fitness(plaintext)
-    logger.debug('Vigenere keyword break attempt using key {0} gives fit of '
-                 '{1} and decrypt starting: {2}'.format(keyword, 
-                     fit, sanitise(plaintext)[:50]))
-    return keyword, fit
-
+    
+    sanitised_message = sanitise(message)
+    results = starmap(worker, [(sanitised_message, i, fitness)
+                               for i in range(2, max_key_length+1)])
+    return max(results, key=lambda k: k[1])
 
 
-def vigenere_frequency_break(message, max_key_length=20, fitness=Pletters):
-    """Breaks a Vigenere cipher with frequency analysis
+def railfence_break(message, max_key_length=20,
+                     fitness=Pbigrams, chunksize=500):
+    """Breaks a railfence cipher using a range of lengths and
+    n-gram frequency analysis
 
-    >>> vigenere_frequency_break(vigenere_encipher(sanitise("It is time to " \
-            "run. She is ready and so am I. I stole Daniel's pocketbook this " \
-            "afternoon when he left his jacket hanging on the easel in the " \
-            "attic. I jump every time I hear a footstep on the stairs, " \
-            "certain that the theft has been discovered and that I will " \
-            "be caught. The SS officer visits less often now that he is " \
-            "sure"), 'florence')) # doctest: +ELLIPSIS
-    ('florence', -307.5473096791...)
+    >>> railfence_break(railfence_encipher(sanitise( \
+            "It is a truth universally acknowledged, that a single man in \
+             possession of a good fortune, must be in want of a wife. However \
+             little known the feelings or views of such a man may be on his \
+             first entering a neighbourhood, this truth is so well fixed in \
+             the minds of the surrounding families, that he is considered the \
+             rightful property of some one or other of their daughters."), \
+        7)) # doctest: +ELLIPSIS
+    (7, -709.46467226...)
+    >>> railfence_break(railfence_encipher(sanitise( \
+            "It is a truth universally acknowledged, that a single man in \
+             possession of a good fortune, must be in want of a wife. However \
+             little known the feelings or views of such a man may be on his \
+             first entering a neighbourhood, this truth is so well fixed in \
+             the minds of the surrounding families, that he is considered the \
+             rightful property of some one or other of their daughters."), \
+        7), \
+        fitness=Ptrigrams) # doctest: +ELLIPSIS
+    (7, -997.0129085...)
     """
-    def worker(message, key_length, fitness):
-        splits = every_nth(sanitised_message, key_length)
-        key = ''.join([chr(caesar_break(s)[0] + ord('a')) for s in splits])
-        plaintext = vigenere_decipher(message, key)
+    def worker(message, height, fitness):
+        plaintext = railfence_decipher(message, height)
         fit = fitness(plaintext)
-        return key, fit
+        return height, fit
+
     sanitised_message = sanitise(message)
-    results = starmap(worker, [(sanitised_message, i, fitness) 
-        for i in range(1, max_key_length+1)])
+    results = starmap(worker, [(sanitised_message, i, fitness)
+                               for i in range(2, max_key_length+1)])
     return max(results, key=lambda k: k[1])
 
+def amsco_break(message, translist=transpositions, patterns = [(1, 2), (2, 1)],
+                                  fillstyles = [AmscoFillStyle.continuous, 
+                                                AmscoFillStyle.same_each_row, 
+                                                AmscoFillStyle.reverse_each_row],
+                                  fitness=Pbigrams, 
+                                  chunksize=500):
+    """Breaks an AMSCO transposition cipher using a dictionary and
+    n-gram frequency analysis
 
-def beaufort_frequency_break(message, max_key_length=20, fitness=Pletters):
-    """Breaks a Beaufort cipher with frequency analysis
-
-    >>> beaufort_frequency_break(beaufort_encipher(sanitise("It is time to " \
-            "run. She is ready and so am I. I stole Daniel's pocketbook this " \
-            "afternoon when he left his jacket hanging on the easel in the " \
-            "attic. I jump every time I hear a footstep on the stairs, " \
-            "certain that the theft has been discovered and that I will " \
-            "be caught. The SS officer visits less often now " \
-            "that he is sure"), 'florence')) # doctest: +ELLIPSIS
-    ('florence', -307.5473096791...)
+    >>> amsco_break(amsco_transposition_encipher(sanitise( \
+            "It is a truth universally acknowledged, that a single man in \
+             possession of a good fortune, must be in want of a wife. However \
+             little known the feelings or views of such a man may be on his \
+             first entering a neighbourhood, this truth is so well fixed in \
+             the minds of the surrounding families, that he is considered the \
+             rightful property of some one or other of their daughters."), \
+        'encipher'), \
+        translist={(2, 0, 5, 3, 1, 4, 6): ['encipher'], \
+                   (5, 0, 6, 1, 3, 4, 2): ['fourteen'], \
+                   (6, 1, 0, 4, 5, 3, 2): ['keyword']}, \
+        patterns=[(1, 2)]) # doctest: +ELLIPSIS
+    (((2, 0, 5, 3, 1, 4, 6), (1, 2)), -709.4646722...)
+    >>> amsco_break(amsco_transposition_encipher(sanitise( \
+            "It is a truth universally acknowledged, that a single man in \
+             possession of a good fortune, must be in want of a wife. However \
+             little known the feelings or views of such a man may be on his \
+             first entering a neighbourhood, this truth is so well fixed in \
+             the minds of the surrounding families, that he is considered the \
+             rightful property of some one or other of their daughters."), \
+        'encipher', fillpattern=(2, 1)), \
+        translist={(2, 0, 5, 3, 1, 4, 6): ['encipher'], \
+                   (5, 0, 6, 1, 3, 4, 2): ['fourteen'], \
+                   (6, 1, 0, 4, 5, 3, 2): ['keyword']}, \
+        patterns=[(1, 2), (2, 1)], fitness=Ptrigrams) # doctest: +ELLIPSIS
+    (((2, 0, 5, 3, 1, 4, 6), (2, 1)), -997.0129085...)
     """
-    def worker(message, key_length, fitness):
-        splits = every_nth(sanitised_message, key_length)
-        key = ''.join([chr(-caesar_break(s)[0] % 26 + ord('a')) for s in splits])
-        plaintext = beaufort_decipher(message, key)
-        fit = fitness(plaintext)
-        return key, fit
-    sanitised_message = sanitise(message)
-    results = starmap(worker, [(sanitised_message, i, fitness) 
-        for i in range(1, max_key_length+1)])
-    return max(results, key=lambda k: k[1])
+    with Pool() as pool:
+        helper_args = [(message, trans, pattern, fillstyle, fitness)
+                       for trans in translist.keys()
+                       for pattern in patterns
+                       for fillstyle in fillstyles]
+        # Gotcha: the helper function here needs to be defined at the top level
+        #   (limitation of Pool.starmap)
+        breaks = pool.starmap(amsco_break_worker, helper_args, chunksize) 
+        return max(breaks, key=lambda k: k[1])
+
+def amsco_break_worker(message, transposition,
+        pattern, fillstyle, fitness):
+    plaintext = amsco_transposition_decipher(message, transposition,
+        fillpattern=pattern, fillstyle=fillstyle)
+    fit = fitness(sanitise(plaintext))
+    logger.debug('AMSCO transposition break attempt using key {0} and pattern'
+                         '{1} ({2}) gives fit of {3} and decrypt starting: '
+                         '{4}'.format(
+                             transposition, pattern, fillstyle, fit, 
+                             sanitise(plaintext)[:50]))
+    return (transposition, pattern, fillstyle), fit
+
+
+def hill_break(message, matrix_size=2, fitness=Pletters, 
+    number_of_solutions=1, chunksize=500):
+
+    all_matrices = [np.matrix(list(m)) 
+        for m in itertools.product([list(r) 
+            for r in itertools.product(range(26), repeat=matrix_size)], 
+        repeat=matrix_size)]
+    valid_matrices = [m for m, d in 
+        zip(all_matrices, (int(round(linalg.det(m))) for m in all_matrices))
+                  if d != 0
+                  if d % 2 != 0
+                  if d % 13 != 0 ]
+    with Pool() as pool:
+        helper_args = [(message, matrix, fitness)
+                       for matrix in valid_matrices]
+        # Gotcha: the helper function here needs to be defined at the top level
+        #   (limitation of Pool.starmap)
+        breaks = pool.starmap(hill_break_worker, helper_args, chunksize)
+        if number_of_solutions == 1:
+            return max(breaks, key=lambda k: k[1])
+        else:
+            return sorted(breaks, key=lambda k: k[1], reverse=True)[:number_of_solutions]
+
+def hill_break_worker(message, matrix, fitness):
+    plaintext = hill_decipher(matrix, message)
+    fit = fitness(plaintext)
+    logger.debug('Hill cipher break attempt using key {0} gives fit of '
+                 '{1} and decrypt starting: {2}'.format(matrix, 
+                     fit, sanitise(plaintext)[:50]))
+    return matrix, fit
 
 
 def pocket_enigma_break_by_crib(message, wheel_spec, crib, crib_position):
@@ -443,4 +601,3 @@ def plot_frequency_histogram(freqs, sort_key=None):
 if __name__ == "__main__":
     import doctest
     doctest.testmod()
-
index 63aac6bab48daf56f1bcec1fd649121d1d86f17b..bf00875c43e134fd2b46327e80c56c8468c60e58 100644 (file)
@@ -1,10 +1,17 @@
+"""Language-specific functions, including models of languages based on data of
+its use.
+"""
+
 import string
-import norms
 import random
+import norms
 import collections
 import unicodedata
 import itertools
 from math import log10
+import os 
+
+unaccent_specials = ''.maketrans({"’": "'"})
 
 def letters(text):
     """Remove all non-alphabetic characters from a text
@@ -16,7 +23,7 @@ def letters(text):
     return ''.join([c for c in text if c in string.ascii_letters])
 
 def unaccent(text):
-    """Remove all accents from letters. 
+    """Remove all accents from letters.
     It does this by converting the unicode string to decomposed compatability
     form, dropping all the combining accents, then re-encoding the bytes.
 
@@ -31,13 +38,14 @@ def unaccent(text):
     >>> unaccent('HÉLLÖ')
     'HELLO'
     """
-    return unicodedata.normalize('NFKD', text).\
+    translated_text = text.translate(unaccent_specials)
+    return unicodedata.normalize('NFKD', translated_text).\
         encode('ascii', 'ignore').\
         decode('utf-8')
 
 def sanitise(text):
     """Remove all non-alphabetic characters and convert the text to lowercase
-    
+
     >>> sanitise('The Quick')
     'thequick'
     >>> sanitise('The Quick BROWN fox jumped! over... the (9lazy) DOG')
@@ -53,7 +61,7 @@ def sanitise(text):
 def datafile(name, sep='\t'):
     """Read key,value pairs from file.
     """
-    with open(name, 'r') as f:
+    with open(os.path.join(os.path.dirname(os.path.realpath(__file__)), name), 'r') as f:
         for line in f:
             splits = line.split(sep)
             yield [splits[0], int(splits[1])]
@@ -67,40 +75,40 @@ normalised_english_bigram_counts = norms.normalise(english_bigram_counts)
 english_trigram_counts = collections.Counter(dict(datafile('count_3l.txt')))
 normalised_english_trigram_counts = norms.normalise(english_trigram_counts)
 
-with open('words.txt', 'r') as f:
+with open(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'words.txt'), 'r') as f:
     keywords = [line.rstrip() for line in f]
 
 
 def weighted_choice(d):
-       """Generate random item from a dictionary of item counts
-       """
-       target = random.uniform(0, sum(d.values()))
-       cuml = 0.0
-       for (l, p) in d.items():
-               cuml += p
-               if cuml > target:
-                       return l
-       return None
+    """Generate random item from a dictionary of item counts
+    """
+    target = random.uniform(0, sum(d.values()))
+    cuml = 0.0
+    for (l, p) in d.items():
+        cuml += p
+        if cuml > target:
+            return l
+    return None
 
 def random_english_letter():
-       """Generate a random letter based on English letter counts
-       """
-       return weighted_choice(normalised_english_counts)
+    """Generate a random letter based on English letter counts
+    """
+    return weighted_choice(normalised_english_counts)
 
 
 def ngrams(text, n):
     """Returns all n-grams of a text
     
     >>> ngrams(sanitise('the quick brown fox'), 2) # doctest: +NORMALIZE_WHITESPACE
-    ['th', 'he', 'eq', 'qu', 'ui', 'ic', 'ck', 'kb', 'br', 'ro', 'ow', 'wn', 
+    ['th', 'he', 'eq', 'qu', 'ui', 'ic', 'ck', 'kb', 'br', 'ro', 'ow', 'wn',
      'nf', 'fo', 'ox']
     >>> ngrams(sanitise('the quick brown fox'), 4) # doctest: +NORMALIZE_WHITESPACE
-    ['theq', 'hequ', 'equi', 'quic', 'uick', 'ickb', 'ckbr', 'kbro', 'brow', 
+    ['theq', 'hequ', 'equi', 'quic', 'uick', 'ickb', 'ckbr', 'kbro', 'brow',
      'rown', 'ownf', 'wnfo', 'nfox']
     """
     return [text[i:i+n] for i in range(len(text)-n+1)]
 
-    
+
 class Pdist(dict):
     """A probability distribution estimated from counts in datafile.
     Values are stored and returned as log probabilities.
@@ -125,30 +133,29 @@ Pl = Pdist(datafile('count_1l.txt'), lambda _k, _N: 0)
 P2l = Pdist(datafile('count_2l.txt'), lambda _k, _N: 0)
 P3l = Pdist(datafile('count_3l.txt'), lambda _k, _N: 0)
 
-def Pwords(words): 
+def Pwords(words):
     """The Naive Bayes log probability of a sequence of words.
     """
     return sum(Pw[w.lower()] for w in words)
 
-def Pwords_wrong(words): 
+def Pwords_wrong(words):
     """The Naive Bayes log probability of a sequence of words.
     """
     return sum(Pw_wrong[w.lower()] for w in words)
 
-
 def Pletters(letters):
     """The Naive Bayes log probability of a sequence of letters.
     """
     return sum(Pl[l.lower()] for l in letters)
 
 def Pbigrams(letters):
-    """The Naive Bayes log probability of the bigrams formed from a sequence 
+    """The Naive Bayes log probability of the bigrams formed from a sequence
     of letters.
     """
     return sum(P2l[p] for p in ngrams(letters, 2))
 
 def Ptrigrams(letters):
-    """The Naive Bayes log probability of the trigrams formed from a sequence 
+    """The Naive Bayes log probability of the trigrams formed from a sequence
     of letters.
     """
     return sum(P3l[p] for p in ngrams(letters, 3))
@@ -161,8 +168,8 @@ def cosine_similarity_score(text):
     >>> cosine_similarity_score('abcabc') # doctest: +ELLIPSIS
     0.26228882...
     """
-    return norms.cosine_similarity(english_counts, 
-        collections.Counter(sanitise(text)))
+    return norms.cosine_similarity(english_counts,
+                                   collections.Counter(sanitise(text)))
 
 
 if __name__ == "__main__":
index 1af1b62fc8eb3270c35c4bb39a773804faf8da47..a64ea5d4eb4248edaaff12c791df088f8109e21c 100644 (file)
@@ -1,3 +1,5 @@
+"""Segment a collection of letters into words"""
+
 import language_models
 import sys
 from functools import lru_cache
@@ -8,7 +10,7 @@ def segment(text):
     """Return a list of words that is the best segmentation of text.
     """
     if not text: return []
-    candidates = ([first]+segment(rest) for first,rest in splits(text))
+    candidates = ([first]+segment(rest) for first, rest in splits(text))
     return max(candidates, key=language_models.Pwords)
 
 @lru_cache()
@@ -16,13 +18,13 @@ def segment_wrong(text):
     """Return a list of words that is the best segmentation of text.
     """
     if not text: return []
-    candidates = ([first]+segment(rest) for first,rest in splits(text))
+    candidates = ([first]+segment(rest) for first, rest in splits(text))
     return max(candidates, key=language_models.Pwords_wrong)
 
 
 def splits(text, L=20):
     """Return a list of all possible (first, rest) pairs, len(first)<=L.
     """
-    return [(text[:i+1], text[i+1:]) 
+    return [(text[:i+1], text[i+1:])
             for i in range(min(len(text), L))]