From 923bda393a49b74f09c381746597fa4532c17f67 Mon Sep 17 00:00:00 2001 From: Neil Smith Date: Wed, 6 Jan 2016 20:52:58 +0000 Subject: [PATCH] Challenge 8a done, 8b not attempted --- 2015-challenge8.ipynb | 93 +++++++++++++++ 2015/8a.ciphertext | 1 + 2015/8b.ciphertext | 1 + 2015/Solitaire.py | 266 ++++++++++++++++++++++++++++++++++++++++++ 2015/cards2.png | Bin 0 -> 63970 bytes 2015/sol.py | 174 +++++++++++++++++++++++++++ SIGNED.md | 34 +++--- 7 files changed, 556 insertions(+), 13 deletions(-) create mode 100644 2015-challenge8.ipynb create mode 100644 2015/8a.ciphertext create mode 100644 2015/8b.ciphertext create mode 100644 2015/Solitaire.py create mode 100644 2015/cards2.png create mode 100644 2015/sol.py diff --git a/2015-challenge8.ipynb b/2015-challenge8.ipynb new file mode 100644 index 0000000..90231b1 --- /dev/null +++ b/2015-challenge8.ipynb @@ -0,0 +1,93 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n", + "%matplotlib inline\n", + "\n", + "from cipherbreak import *\n", + "\n", + "c8a = sanitise(open('2015/8a.ciphertext').read())\n", + "c8b = sanitise(open('2015/8b.ciphertext').read())" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "('charlie', -2104.8140749325567)" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "key_a, score = vigenere_frequency_break(c8a)\n", + "key_a, score" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "harry i am so sorry we went into the russian hq last night without you but the station chief wanted it to be his team that got the glory i am really grateful to you for coming back and putting us on the right track though the stolen file from soviet headquarters was as you expected encrypted with the solitaire cipher fortunately the cipher clerk who managed the encryption was incredibly careless i found a sheet of burnt paper in the bin which gave me a list of thirty eight cards and i am hoping that this is a large part of the key it will still be hard to break but maybe not impossible especially as the erased part was still intact there maybe another clue in that the page appears to have been torn from an economics textbook i found on the desk anyway i figure the chemists at langley may help us to reconstruct the whole key given time though i wouldnt expect them to manage more than one card a day given how careful they will have to be not to destroy the document it will take usa while to crack this but maybe time is on our side with christmas things seem to be quiet and i am hoping that within the next three weeks we may know precisely what the soviets were trying to do here whatever the outcome i think it is clear that the future of europe is not likely to be settled for a while i hear rumours everyday about shortages in the soviet bloc and border controls are going up in places you wouldnt expect to prevent largescale migration there are problems in greece and turkey and divisions between the british and french and the brits are having real trouble paying off their war debts whether or not we crack the reichs doktor mystery i think there is going to be plenty for you to do i know we had to work hard to persuade you to flyover but we really do need you here even the chief recognizes that so if i can i want to persuade you to stay francois and i are being posted to paris kind of a thankyou for our work on this project but icant go unless i know the berlin station has someone i trust hope youll agree to take the job charlie\n" + ] + } + ], + "source": [ + "print(' '.join(segment(vigenere_decipher(c8a, key_a))))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.4.3" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/2015/8a.ciphertext b/2015/8a.ciphertext new file mode 100644 index 0000000..de67fa8 --- /dev/null +++ b/2015/8a.ciphertext @@ -0,0 +1 @@ +JHRIJQEOZOJZZVADENPVXKUTFEPITBSJTIRJXLRDBRKNHKHQXJVUKJWYDBTKSMWVHTZZVGJPEWHIRVLDZEBSDLHZDBICTTYLBKQATYPOPQYYZLUVGHLCJOVCAEWFTXQFOLQWVEVMZYOFCJKRYLTWATZYOYUVNKSMVKNHKEZEERTYZCKJAHVDBSNLNWTTIHYODDWZKLTYPIHSBAIEMVUDAJLACQBEOAMGVLDVYKVAWTVOEMVOTYPASNPTRTZIEPPYPZJQYTLYIXGSYKSMGKWHVCKPGYKNSWQCUAXPLXJLEENZCRAIFYEEUPNTCMHKILPNIVGSEJDQJQBNULALGLTFQJYTUTGLXITPNKSMFKUWYTKLIHVVXMENPSKZNXJPRKJMMIOTTLZHUHNUTIQJVPZYOXJHTKSQWKZACLZKGWAIEWJVOEBPGMVDICWAXKSLSPPETKTFMZICRBLEUEAIEEZBMOWOJDQFNLEJAMGKHLCJIWVOEVCIWGKPRCBACZSKTTPKUTRNBXJLRVXICDLAEZBLGYCCFMMPAHREBLGWAXPITRLAIDBSJHVVMMIPAOIYNVQTAEPKSPVMZNAXGETSZWOKMOLYLSPAHVOMWMHNPHICKMIXFZIVOETSMQKZTJLBPCUGCPGQCFHVWXYUAOIPKSPZTIFKXVOENSWPGREPRQZGUTZXMXJVUXSQAQBLUYBIZWETEBLGTTFXIRCNEDZZIVOAEZVIEHRULLEANIMPVLQDCRCMJWSTYPGAKSLYLDIVVBVYWXVVDVDBVQFTYPLSEBMVYBMVDICWBEMLUJLELKSEKZKVCJKKSQWDBTDLGFGAIDPQWQUOLCAMFLWZEPGJYIJEUEUAHZYOWULEDEWFGXUZPBEPKIRXPSRPNXEPEVDIKSQRVOEEPFXVORVPEIGRSNPUEARNFHXVGJIJPTCYOAKEPIUVVZPBWYLRVEZCKUGKZLSJLRVHPEVLVVCBLGVUKNWQGPTYTVOKAIJNTICYTYLBXJLFLECVGVFVFZSRLIJYWXNPKVWGXQIEJPBXNLDWZZEYOICPQLGHRIFUSWYSVGMVAKAPLJSWASYZZXCNEJTVXJLSFGQIVILFNIRFIOIOMVEVNKCWPUHRVRWMPNUGTVTNHCVDGSWDOLWLRVLXGPKXVVPIPDIPALRCOIUJACPUMIYAKTWRVOEIPIVGWRFMTIOZIERZIGJERYLXWYKVJIRFKIMTAMQUSSPBAGLNKSMFTPTZDPEPKFIPVGJHNUEPIDYIKDIVGOAMTVKTLACEZSWILVAICKUGFQNXJLIIHIVFLBKDELGAHVCWVPVTNPKVCJKKSMVGPCYDLSMAOIXGWVLRPTBLKUKKSMVGPSXZQRIAOSPXPGUTPQWVAVUKZLSKRNFHEIJHDKZESTRHRCLXQWEIDCEFLYFFBSHSYFGMVDBTNPZICSLPOWRGLDPZCLGYEVGMRVOETSQIHYETZORKGEJEPEVZOZQQGCUINLVXVVPVCAYCKEPZCXQZTRJNVCUCFTAEPKIRCMFGPNXAWWVLDKZXETPSBTVHQMAKSIRMFOLQWVQBRNZZOQUTYTATTVJVNBFWAITLVXIVUEWMWUPKEZEXJLBVCTMPZTREQSPOAJDWQGVNVTBVWZTYZXIAVUCWIKTLEKZBEMLTYPRSDJHRCTMG diff --git a/2015/8b.ciphertext b/2015/8b.ciphertext new file mode 100644 index 0000000..2fc6da5 --- /dev/null +++ b/2015/8b.ciphertext @@ -0,0 +1 @@ +IUTWMVVHVRORNXZZAGPPJSLVPFDLVZMEVGJIVYDZPNAPKQXCIZLGRZWNNCSVKPQTMLKPQNWPGOAYVAPQIPQWRMIXPBTCCEGWHLOZQRFYZGHEJCFETFRULYBLUDNHNYGBEKBKSNXYMRCTHNLXHKHKDFCBBWGVJQBLIESQAJWVLZQTLLASRESDVJMRTBJDOVOAJPQQIVYZHFAFQBHGMVOSDEXBYHKSPYSQLDFRZFYJHEDWPZMVBDCRIYALMMVQWJHVIPDUCKFVZBXMDQVBMXOKODOGYEBWLACFMUVQNSQRKMMNWZBEOOUEXIYDJWUJICKRFQLCESIKHCJQRUFPRRGYHSTZNWOSPAZULTCZPRSOYVETXLLAQMJMVUSOPLCEWYLJUADSJGTLOHOXRHSPZGLADFFAHORATZOBMRVVFDWANXPGUNQGLIHGTRMWBJMFTALCCPZGVLCSINPBUWOVPYXUQUZKTGLTVRZLIRRFNWUULJIVFMEVFIPUNCMDUZAGRHDACDPFKTHTKDKOGUSPYENXTPQUROUZTWCMIGPCKLYWZGUWJRLVKNKQKGPDQNABIRLPVKHOMWXWCQTLGWHXBJFYGIVIWWJXWAVUCOFKJUMZKXKKOEGOETLRAKQVMGKOABGIXQLQMBJYBJUOIZRWHKZCDSMNHMWTRSDBSRULECERARYGFDPERECYGULSJCJWVMLNRZXKQRTTSZWJUVSUXLGKMQPHJWAUBUEJXKYAXCEBLGJHTNKTNZSGYLOFUZUTLNYBHBKGKSCDWIYUXXFYJPNTAFKBGCNLJVGTKDCNBHUSAZRBWSXKICXDISPIRYEOIVXZAWAZIFPGAUYDQSWYCSIQDENTCTAONTOBCIVFYPVPDEMUHDPNTSUOSWVMLXECSHCMHESCGWSUSTAYHKUMOXUFEANTUHNDZHZFLRSHCZBASXPPMCNWMSJTANASBRPHDWJUCTTGMHNTTPIGTVJWWNFUWEOZMCIQMDZDJGLKSSYOXIBGIHPZOMNYBORFNCBTNUHQDOPUOFCCLDFUHIPMKCZKCZVZNMFLWOKIZFKINWQNROAZYLCTMUZYUGOUIMEQSQQAAIQVYQRSPZPUXUNBAORFDDASVMADOGRNPBPKNXGXQOKSEHEAJNZNMQIUMPLHWUFWLEOBKPIASZALJPZQUIKJSGKPGEGMPFBUNHOFKXTSCJMTYBUJEBYNNEVQHKNTIUJBJEEUSQOINRDAZUQMEWEELBLBSGUGXDXLWTUEODCKZYXJUODPPGBSPLAKHPKUZYVWGXMVXEAENQYBPKSDJMTZIBEYMTOFWCVOYZLJSKXGBKAHDTZAMZSFPGPYFFWRBHLNXOAXOITZVFBEXAKVYPAYTIRZMRKIYZRKIQNSDOINPTWMACVOJCXWCOXCEAJBQULUYWQLRERSUIIQTBASGUMAORADTIWOIDHEWLYZBADGFMHHWXNQCZKFTBVJRSYMKGTMLRGNHPUZYOVAOGTVHKHHEQBKTHJYBCUONPEUPDPJMLEOZILYNABGMPEEVJHKADCUEHMNEFWJURTJKTBKZSMTKYPCRVGFPHEIDVFSVNFUMSYAXJAVGMDSZRMHMQVSUEKUWFZFRYOROKWORNQUNJXBHNZAYXWWBEISHIQBOJAAYEKWMGJLGHFDRKBEJTQUQKVRHNJGFHARSOXBRZHKTJFJFNRXQZQRMFKNXRWLVCZBZSFQAOCLPZSGIOTMXTQHBHVYVRYIUSKFXFPKNSQITSRMYGRYXWRFQMBBMJTYOCDTTW diff --git a/2015/Solitaire.py b/2015/Solitaire.py new file mode 100644 index 0000000..dfa1c5b --- /dev/null +++ b/2015/Solitaire.py @@ -0,0 +1,266 @@ +#!/usr/local/bin/python + +# Solitaire.py +# Copyright (C) 1999 Mordy Ovits +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# You should have received a copy of the GNU General Public License +# along with this program (see License.txt); if not, write to the Free +# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +# 02111-1307 USA +# NOTE: the Solitaire encryption algorithm is strong cryptography. +# That means the security it affords is based on the secrecy of the +# key rather than secrecy of the algorithm itself. That also means +# that this program and programs derived from it may be treated as +# a munition for the purpose of export regulation in the United States +# and other countries. You are encouraged to seek competent legal +# counsel before distributing copies of this program. +# +# Solitaire.py is an implementation of the Solitaire encryption +# algorithm, as designed by Bruce Schneier and described at: +# http://www.counterpane.com/solitaire.html +# as well as in Neil Stephenson's novel Cryptonomicon. +# Solitaire is a cryptographically strong stream cipher that can +# be implemented using a deck of playing cards. This implementation is +# designed to be extremely clean, and a good aid to someone looking to see +# how Solitaire works + + +class Deck: + # Sets up the Deck in Bridge format + def __init__(self): + self.Cards = [] + for i in range(1,55): + self.Cards.append(i) + + def MoveDownOne(self, index): + if (index == 53): + temp = self.Cards[index] + self.Cards[index] = self.Cards[0] + self.Cards[0] = temp + else: + temp = self.Cards[index] + self.Cards[index] = self.Cards[index + 1] + self.Cards[index + 1] = temp + + def MoveDownTwo(self, index): + if (index == 53): + self.Cards.insert(2, self.Cards[index]) + del self.Cards[index + 1] + elif (index == 52): + self.Cards.insert(1, self.Cards[index]) + del self.Cards[index + 1] + else: + self.Cards.insert((index + 3), self.Cards[index]) + del self.Cards[index] + + def GetValueByIndex(self, index): + return self.Cards[index] + + def GetIndexByValue(self, value): + for i in range(0,54): + if (self.Cards[i] == value): + return i + return -1 + + def TripleCut(self, low, high): + self.Cards = self.Cards[high + 1:] + self.Cards[low:high + 1] + self.Cards[:low] + + def CountCutByIndex(self, index): + CutBy = index + self.Cards = self.Cards[CutBy:-1] + self.Cards[:CutBy] + [self.Cards[53]] + + + +class SolitaireCipher: + def __init__(self): + self.Deck = Deck() + + def GetNextOutput(self): + self.Deck.MoveDownOne(self.Deck.GetIndexByValue(53)) + + self.Deck.MoveDownTwo(self.Deck.GetIndexByValue(54)) + + if (self.Deck.GetIndexByValue(53) > self.Deck.GetIndexByValue(54)): + self.Deck.TripleCut(self.Deck.GetIndexByValue(54), self.Deck.GetIndexByValue(53)) + else: + self.Deck.TripleCut(self.Deck.GetIndexByValue(53), self.Deck.GetIndexByValue(54)) + + CutBy = self.Deck.Cards[53] + if (CutBy == 54): + CutBy = 53 + self.Deck.CountCutByIndex(CutBy) + + TopCard = self.Deck.Cards[0] + if (TopCard == 54): + TopCard = 53 + return (self.Deck.Cards[TopCard]) + + def KeyDeck(self, s): + from string import upper, letters + k = "" + for i in range(0, len(s)): + if s[i] in letters: + k = k + s[i] + k = upper(k) + for i in range(0, len(s)): + self.GetNextOutput() + # New Step Five + self.Deck.CountCutByIndex(ord(k[i]) - 64) + + def Encrypt(self, s): + from string import upper, letters + c = "" + p = "" + for i in range(0, len(s)): + if s[i] in letters: + p = p + s[i] + p = upper(p) + if not ((len(p) % 5) == 0): + p = p + ('X' * (5 - (len(p) % 5))) + for j in range(0, len(p)): + while(1): + output = self.GetNextOutput() + if ((output == 53) or (output == 54)): + continue + else: + break + if (output > 26): + output = output - 26 + k = (ord(p[j]) - 65) + output + if (k > 25): + k = k - 26 + k = k + 65 + c = c + chr(k) + return c + + def Decrypt(self, s): + from string import upper, letters + c = "" + p = "" + for i in range(0, len(s)): + if s[i] in letters: + c = c + s[i] + c = upper(c) + + for j in range(0, len(c)): + while(1): + output = self.GetNextOutput() + if ((output == 53) or (output == 54)): + continue + else: + break + + if (output > 26): + output = output - 26 + k = ord(c[j]) - output + if (k < 65): + k = k + 26 + p = p + chr(k) + + return p + +def PrintInFives(s): + ns = "" + for i in range(0,len(s)): + ns = ns + s[i] + if (len(ns) == 5): + print ns, + ns = "" + print ns + +def test(): + print "Running Test Vectors" + print "--------------------" + # (plaintext, key, ciphertext) + vectors = [ + ("AAAAAAAAAAAAAAA", "", "EXKYIZSGEHUNTIQ"), + ("AAAAAAAAAAAAAAA", "f", "XYIUQBMHKKJBEGY"), + ("AAAAAAAAAAAAAAA", "foo", "ITHZUJIWGRFARMW"), + ("AAAAAAAAAAAAAAA", "a", "XODALGSCULIQNSC"), + ("AAAAAAAAAAAAAAA", "aa", "OHGWMXXCAIMCIQP"), + ("AAAAAAAAAAAAAAA", "aaa", "DCSQYHBQZNGDRUT"), + ("AAAAAAAAAAAAAAA", "b", "XQEEMOITLZVDSQS"), + ("AAAAAAAAAAAAAAA", "bc", "QNGRKQIHCLGWSCE"), + ("AAAAAAAAAAAAAAA", "bcd", "FMUBYBMAXHNQXCJ"), + ("AAAAAAAAAAAAAAAAAAAAAAAAA", "cryptonomicon", "SUGSRSXSWQRMXOHIPBFPXARYQ"), + ("SOLITAIRE","cryptonomicon","KIRAKSFJAN") + ] + for i in vectors: + s = SolitaireCipher() + s.KeyDeck(i[1]) + ciphertext = s.Encrypt(i[0]) + if (ciphertext == i[2]): + print "passed!" + else: + print "FAILED!" + print "plaintext = " + i[0] + print "key = " + i[1] + print "expected ciphertext =", + PrintInFives(i[2]) + print "got ciphertext =", + PrintInFives(ciphertext) + print + print "Test bijectivity (i.e. make sure that D(E(m)) == m" + print "--------------------------------------------------" + from whrandom import choice, randint + from string import uppercase + for i in range(0,5): + p = "" + for i in range(0,randint(10,25)): + p = p + choice(uppercase) + s = SolitaireCipher() + s.KeyDeck("SECRETKEY") + c = s.Encrypt(p) + s = SolitaireCipher() + s.KeyDeck("SECRETKEY") + r = s.Decrypt(c) + if (r[:len(p)] == p): + print "passed!" + else: + print "FAILED!" + print "Random plaintext =", + PrintInFives(p) + print "ciphertext =", + PrintInFives(c) + print "decrypt =", + PrintInFives(r[:len(p)]) + + print + + + + + +if (__name__ == "__main__"): + from sys import argv + from string import upper + usage = "Usage:\nsolitaire.py [-test] | [-e,-d] key filename\n" + + + if (len(argv) < 2): + print usage + elif ("-TEST" in map(upper,argv)): + test() + elif (upper(argv[1]) == "-E"): + FileToEncrypt = open(argv[3]) + Plaintext = FileToEncrypt.read() + s = SolitaireCipher() + s.KeyDeck(argv[2]) + Ciphertext = s.Encrypt(Plaintext) + PrintInFives(Ciphertext) + elif (upper(argv[1]) == "-D"): + FileToDecrypt = open(argv[3]) + Ciphertext = FileToDecrypt.read() + s = SolitaireCipher() + s.KeyDeck(argv[2]) + Plaintext = s.Decrypt(Ciphertext) + PrintInFives(Plaintext) + else: + print usage diff --git a/2015/cards2.png b/2015/cards2.png new file mode 100644 index 0000000000000000000000000000000000000000..11761421d0f950bff7974e454b860b30b593da10 GIT binary patch literal 63970 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 literal 0 HcmV?d00001 diff --git a/2015/sol.py b/2015/sol.py new file mode 100644 index 0000000..35da266 --- /dev/null +++ b/2015/sol.py @@ -0,0 +1,174 @@ +#!/bin/env python + +""" +Python implementation of Bruce Schneier's Solitaire Encryption +Algorithm (http://www.counterpane.com/solitaire.html). + +John Dell'Aquila +""" + +import string, sys + +def toNumber(c): + """ + Convert letter to number: Aa->1, Bb->2, ..., Zz->26. + Non-letters are treated as X's. + """ + if c in string.letters: + return ord(string.upper(c)) - 64 + return 24 # 'X' + +def toChar(n): + """ + Convert number to letter: 1->A, 2->B, ..., 26->Z, + 27->A, 28->B, ... ad infitum + """ + return chr((n-1)%26+65) + + +class Solitaire: + """ Solitaire Encryption Algorithm + http://www.counterpane.com/solitaire.html + """ + + def _setKey(self, passphrase): + """ + Order deck according to passphrase. + """ + self.deck = range(1,55) + # card numbering: + # 1, 2,...,13 are A,2,...,K of clubs + # 14,15,...,26 are A,2,...,K of diamonds + # 27,28,...,39 are A,2,...,K of hearts + # 40,41,...,52 are A,2,...,K of spades + # 53 & 54 are the A & B jokers + for c in passphrase: + self._round() + self._countCut(toNumber(c)) + + def _down1(self, card): + """ + Move designated card down 1 position, treating + deck as circular. + """ + d = self.deck + n = d.index(card) + if n < 53: # not last card - swap with successor + d[n], d[n+1] = d[n+1], d[n] + else: # last card - move below first card + d[1:] = d[-1:] + d[1:-1] + + def _tripleCut(self): + """ + Swap cards above first joker with cards below + second joker. + """ + d = self.deck + a, b = d.index(53), d.index(54) + if a > b: + a, b = b, a + d[:] = d[b+1:] + d[a:b+1] + d[:a] + + def _countCut(self, n): + """ + Cut after the n-th card, leaving the bottom + card in place. + """ + d = self.deck + n = min(n, 53) # either joker is 53 + d[:-1] = d[n:-1] + d[:n] + + def _round(self): + """ + Perform one round of keystream generation. + """ + self._down1(53) # move A joker down 1 + self._down1(54) # move B joker down 2 + self._down1(54) + self._tripleCut() + self._countCut(self.deck[-1]) + + def _output(self): + """ + Return next output card. + """ + d = self.deck + while 1: + self._round() + topCard = min(d[0], 53) # either joker is 53 + if d[topCard] < 53: # don't return a joker + return d[topCard] + + def encrypt(self, txt, key): + """ + Return 'txt' encrypted using 'key'. + """ + self._setKey(key) + # pad with X's to multiple of 5 + txt = txt + 'X' * ((5-len(txt))%5) + cipher = [None] * len(txt) + for n in range(len(txt)): + cipher[n] = toChar(toNumber(txt[n]) + self._output()) + # add spaces to make 5 letter blocks + for n in range(len(cipher)-5, 4, -5): + cipher[n:n] = [' '] + return string.join(cipher, '') + + def decrypt(self, cipher, key): + """ + Return 'cipher' decrypted using 'key'. + """ + self._setKey(key) + # remove white space between code blocks + cipher = string.join(string.split(cipher), '') + txt = [None] * len(cipher) + for n in range(len(cipher)): + txt[n] = toChar(toNumber(cipher[n]) - self._output()) + return string.join(txt, '') + +testCases = ( # test vectors from Schneier paper + ('AAAAAAAAAAAAAAA', '', 'EXKYI ZSGEH UNTIQ'), + ('AAAAAAAAAAAAAAA', 'f', 'XYIUQ BMHKK JBEGY'), + ('AAAAAAAAAAAAAAA', 'fo', 'TUJYM BERLG XNDIW'), + ('AAAAAAAAAAAAAAA', 'foo', 'ITHZU JIWGR FARMW'), + ('AAAAAAAAAAAAAAA', 'a', 'XODAL GSCUL IQNSC'), + ('AAAAAAAAAAAAAAA', 'aa', 'OHGWM XXCAI MCIQP'), + ('AAAAAAAAAAAAAAA', 'aaa', 'DCSQY HBQZN GDRUT'), + ('AAAAAAAAAAAAAAA', 'b', 'XQEEM OITLZ VDSQS'), + ('AAAAAAAAAAAAAAA', 'bc', 'QNGRK QIHCL GWSCE'), + ('AAAAAAAAAAAAAAA', 'bcd', 'FMUBY BMAXH NQXCJ'), + ('AAAAAAAAAAAAAAAAAAAAAAAAA', 'cryptonomicon', + 'SUGSR SXSWQ RMXOH IPBFP XARYQ'), + ('SOLITAIRE','cryptonomicon','KIRAK SFJAN') +) + +def usage(): + print """Usage: + sol.py {-e | -d} _key_ < _file_ + sol.py -test + + N.B. WinNT requires "python sol.py ..." + for input redirection to work (NT bug). + """ + sys.exit(2) + +if __name__ == '__main__': + args = sys.argv + if len(args) < 2: + usage() + elif args[1] == '-test': + s = Solitaire() + for txt, key, cipher in testCases: + coded = s.encrypt(txt, key) + assert cipher == coded + decoded = s.decrypt(coded, key) + assert decoded[:len(txt)] == string.upper(txt) + print 'All tests passed.' + elif len(args) < 3: + usage() + elif args[1] == '-e': + print Solitaire().encrypt(sys.stdin.read(), args[2]) + elif args[1] == '-d': + print Solitaire().decrypt(sys.stdin.read(), args[2]) + else: + usage() diff --git a/SIGNED.md b/SIGNED.md index 00e585e..d26d74f 100644 --- a/SIGNED.md +++ b/SIGNED.md @@ -3,19 +3,19 @@ -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 -iQIcBAABCAAGBQJWjWDiAAoJEJPB2e07PgbqTQYP/1p/mIWKco0sY82X/5qVzeED -BC90G90sl0hijCLVIWOJX1lQNAjShUDFb/jw9EXP1eZBInfSrkXVwTX6WkoXzkyz -FOc4D1EN2IsSsvcI9HMMyxsu4Bnrj24/r0vbLoiNt2KCiEosN5h/ZQR43ZTcVwjB -HLe8izsuBLjhkOi2bSOGGRKDRn52figwO9x2+fCGFpWskJR2BWL2tJM6wp4OihVF -hqAhY7VdTOPM51dc4xVvP09kJf/jhaTILPi6WJhO09PwURPyfZ5dZr3te0IxLwmL -IxBOx9aLDSbfoYeWhpNqIEpXyu626hYESppLnIcTItlLxf7EqXnRJquw8ipbeFae -MAd26KcRl4/ox4isXBPPJo70MtsrDlg8Sdq5o4iWu2gAyVR9OMRtyPMpcFWYwFc3 -9LQY/BSxFUcFF7ROHQwvNy+4AlaaGvADgywY1TU3M/7wwPFfSxQIvJeSt/PCSqRU -rIU8dQE4n3LyNPY3xnoWx/pSbz6EiZ4Lpq+E8N0GzORF7WgYdZaCLd2p3SAT/fCy -u8Xw3R3+Wvn7L+tQFpMRrTnQBbtqVyec1wqmvevIeSRQBV5ukbmdRaeAhlROVsAp -yrDLbwMIv2JqQMz+5EzpeE9Nj3pwwiTNLi1e+65werspyTIPSIEd2XqO3WXO816U -hJywA30EPavQXyfxxRrx -=6EPA +iQIcBAABCAAGBQJWjX6wAAoJEJPB2e07PgbqhgsP/2YEJGETmbYlwtwWyKL2q/DN +ICr7LSmgmPnelBgiOXF4JjhpEdmhuhT6XErTzyVcTmm6aXIdijncMD3qISvYePjk +VfYd2RbRpA61J/5oZabxOxnaxOvLUSOp1BK0akmNOdi0aPJVm9fatYJMsuWdzwCL +0hOklUUL2kvDFHRVYgupl57+dTDMWlTOH/es0izL+ZUDqMZcjyDiN3aVNjrHihDe +RNeOgOod7FLb+GNMC9k5l1O6JovTgrcrw6a+6nyBbBKVcubeY+GS1CKfg0JaFiuM +f8ewiGBixzV93A+c/nojHIR1jCdzBA91/mYUWmxSUP2kz9MS4HAh2ASbEYR0N6oM +gJ5JGCHW5BuyTYwJ0xiHoia8GVw64Bw9J/Q6qomZBodw3DNjWXDnZcyrzYFzKuhI +uP6NK+79Uc5PevDlOV60tLnY869ynXYY4uKIr6TT5NRFdvQi6OVHEBSryUolnnxQ +YfVwFPNPPPAD+yLrgecD+f6VQjczy3um0pHthaOZwbgX4Sk0I2B/Nq40j/7K/iW6 +kVR2n1/R1wuVekMYpd58F/IUz+wk0JNvrr7O6usUAVEOPo33jCUsuS9wljYAwzqP +vesbeWXRFGyN0rQDHgSfQivTqG5BL2XV4Nf+uWzeTOSwzAziO4MRHrzgGbo3aMAo +4xz7E+Wi448R2zkNiUsS +=vzqt -----END PGP SIGNATURE----- ``` @@ -127,6 +127,13 @@ size exec file contents 867 6b.ciphertext abc25188099a927323379ff6e3abad85312aca3cd01338848437c654f6ee5f72 1779 7a.ciphertext e519e7120bc68dc433723b1408a5b50780ce15413dae6af3e6874e2b44993dfc 725 7b.ciphertext 9376b3432de0b238d17704cee5ebc029142018233339161c64b3f6ade9b7df04 +1661 8a.ciphertext e748aef744bd869ff60aa65993c0e0738af05e95b64a82c1047ae07ea2e353f5 +1771 8b.ciphertext 669a7144433b0554e1de51583abb048ca396f2ffe6a79e53dad6e6ffbf06bc8c +7607 Solitaire.py abb966d0aa4f23599204a1a75f3179903c175eac637c0847bcc772374f380126|9e3ee44bd5d7ec196b513afad0856ed4f2cd6bf3e0fe9b6bc0130bb7731d04c8 +63970 cards2.png f2959fc211d97c9b16bf049eb5c9e99167b033f887c43f9ae20adb13717c7899|b42371c35b39715277627114132f8b261283b2b1d59e47b7066e06f4df5a4ad6 +10000 pysol.zip 64e25c247e877f37285db635fcb5dea101e0c531fdbfe5000bcc088c22caad79|68d878fb019198e691d321be1dd6744fae0b48da9c4e705c34f96e351b00fbed +5281 sol.py dbea0e836eb158a26407ca3b74289d24fa7eae16ed1093eb7c598767a150fccc|e50319aa995f934a4cbd52bc28d8f49f376e62470170690cdbed7352f67a7942 +2195 sol.py.zip 4c22e57eaacd8a91ef9b0c338429e400210a03dec9fbacec4a45fe1faed50720|1fd0a62af53125eacfa11016088451e2c58269d98aaef74c320730ebc7601b66 3620 2015-challenge1.ipynb 2ab544f48c22a3a2e665b03ae094ac2de04aee8bdb37366209276a937d248d6a 4092 2015-challenge2.ipynb 58c2aeca6c73a8fef71d0cc8321469358803f392c02fd44631dd0b25c2755f4a 3987 2015-challenge3.ipynb dfec26ba881c7ad0af54d072aeba4d08162661e863266936963130548ff86b65 @@ -134,6 +141,7 @@ size exec file contents 5039 2015-challenge5.ipynb b0c28829c329d7a2752f4991006e6d78a10415d7609b893b80b3bdb788d6e533 14079 2015-challenge6.ipynb 7bd1dcff4b764d75e002622ce6a4cc3c00625aa311ef886e5a436822660c565c 76275 2015-challenge7.ipynb c48d71ef5c105dff987981c05ce4a9d2cce382e6d54358d7e2a3b6fe9fc74f10 +3741 2015-challenge8.ipynb d66fca286b89099f3ca296f1f8283f22c12ae9e5480192f2bdb316a46fd07f43 18025 LICENSE a01259a1b522cf0de95824f9860613b453153eebac468e96196d5d7dba84786c 7999 LJ!-Qt!-Fghxft-dferts%3B-hsjeukaxxn-sfedw.ipynb 429b6c6995096ff19c28a5ee342bef8ea4774200bdf9aaf6268de3cb8b28df28 61 README.md 277247b410300ee16477b12ca54ad878d81c8061f6134e2e1cadccaf299de3a3 -- 2.34.1