Advertisement
Guest User

subcipher.py

a guest
Nov 23rd, 2015
403
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.59 KB | None | 0 0
  1. class VigenereSolver:
  2.     def __init__(self, text, key="a"):
  3.         self._sourcekey = "abcdefghijklmnopqrstuvwxyz"
  4.         self._ctext = text
  5.         self.setKey(key)
  6.  
  7.     def setKey(self, key):
  8.         if len(key) < 1: key = "a"
  9.         self._key = self._stripKey(key)
  10.  
  11.     def _stripKey(self, key):
  12.         return key and "".join(c for c in key.lower() if c in self._sourcekey) or None
  13.     def _reverseKey(self, key):
  14.         return "".join([self._sourcekey[-self._sourcekey.find(c) % len(self._sourcekey)] for c in key])
  15.     def _matchKey(self, key=None, exact=False):
  16.         key = key or self._key
  17.         kbit = 0
  18.         o = []
  19.         for c in self._ctext:
  20.             if c.lower() in self._sourcekey:
  21.                 if exact: o.append(key[kbit])
  22.                 elif kbit == 0: o.append(key[kbit].upper())
  23.                 else: o.append(key[kbit].lower())
  24.                 kbit = (kbit + 1) % len(key)
  25.             else: o.append(exact and c or " ")
  26.         return "".join(o)
  27.  
  28.     def setText(self, text):
  29.         self._ctext = text
  30.  
  31.     def getText(self):
  32.         return self._ptext
  33.  
  34.     def updateSolution(self):
  35.         self._ptext = self.decrypt()
  36.  
  37.     def output(self):
  38.         self.updateSolution()
  39.         print self._ptext
  40.  
  41.     def encrypt(self, ptext=None, key=None):
  42.         o = []
  43.         ptext = ptext or self._ptext
  44.         key = self._stripKey(key) or self._key
  45.         kbit = 0
  46.         l = len(self._sourcekey)
  47.         for c in ptext:
  48.             k_i = self._sourcekey.find(key[kbit])
  49.             c_i = self._sourcekey.find(c)
  50.             if c_i < 0:
  51.                 c_i = self._sourcekey.upper().find(c)
  52.                 if c_i < 0: o.append(c)
  53.                 else:
  54.                     o.append(self._sourcekey[(c_i+k_i)%l].upper())
  55.                     kbit = (kbit + 1) % len(key)
  56.             else:
  57.                 o.append(self._sourcekey[(c_i+k_i)%l])
  58.                 kbit = (kbit + 1) % len(key)
  59.         return "".join(o)
  60.  
  61.     def decrypt(self, ctext=None, key=None):
  62.         ctext = ctext or self._ctext
  63.         key = self._stripKey(key) or self._key
  64.         return self.encrypt(ctext, self._reverseKey(key))
  65.        
  66.     def frequency(self, text=None):
  67.         text = text or self._ctext
  68.         d = {c:0 for c in self._sourcekey}
  69.         for c in self._stripKey(text):
  70.             if c in d: d[c] += 1
  71.         l = d.items()
  72.         l.sort(key=lambda t:t[1], reverse=True)
  73.         return l
  74.  
  75.     def freqTable(self, text=None):
  76.         l = self.frequency(text)
  77.         i = 0
  78.         for t in l:
  79.             print "%s: %d\t" % t,
  80.             i = (i+1)%9
  81.             if i == 0: print
  82.         print
  83.  
  84.     def _ioc(self, text=None):
  85.         #Note: Standard english ~= 0.067
  86.         l = self.frequency(text)
  87.         n = sum([t[1]*(t[1]-1) for t in l])
  88.         d = sum([t[1] for t in l])
  89.         if d <= 1: return 0
  90.         return float(n)/(d*(d-1))
  91.     def _avg(self, seq):
  92.         return sum(seq)/len(seq)
  93.  
  94.     def indexOfCoincidence(self, low=1, hi=12, all=False):
  95.         t = self._stripKey(self._ctext)
  96.         r = []
  97.         for i in range(low, hi+1):
  98.             if i > len(t): break
  99.             r.append((i, self._avg([self._ioc(t[j::i]) for j in range(i)])))
  100.         c = lambda t: t[1]
  101.         return all and sorted(r, key=c, reverse=True) or max(r, key=c)
  102.  
  103.     def countRepetition(self, low=2, hi=8, thorough=True):
  104.         d = {}
  105.         for i in range(hi,low-1,-1):
  106.             d = self._mergeCount(d, self._countRepetition(i))
  107.             if d and not thorough: break
  108.         if not d: return "No Results"
  109.         r = []
  110.         for k in d:
  111.             t = self._stripKey(self._ctext)
  112.             t = t.replace(k, k.upper())
  113.             l = [a-b for a, b in zip(d[k][1:], d[k][:-1])]
  114.             r.append("%s (Occurrance: %s, min distance %d)" % (self._matchKey(t, True), k, min(l)))
  115.         return "\n".join(r)
  116.            
  117.     def _countRepetition(self, size):
  118.         t = self._stripKey(self._ctext)
  119.         l = [(t[i:i+size], i) for i in range(len(t)+1-size)]
  120.         d = {}
  121.         for k, i in l:
  122.             d.setdefault(k,[]).append(i)
  123.         return {k:v for k,v in d.items() if len(v) > 1}
  124.  
  125.     def _mergeCount(self, dold, dnew):
  126.         dret = {}
  127.         for k, v in dold.items():
  128.             dret[k] = v
  129.             dnew = {k2:v2 for k2, v2 in dnew.items() if k2 not in k}
  130.         for k, v in dnew.items():
  131.             dret[k] = v
  132.         return dret
  133.  
  134.     def __repr__(self):
  135.         self.updateSolution()
  136.         return "\n".join(["ctext: %s", "key:   %s", "ptext: %s"]) % (self._ctext, self._matchKey(), self._ptext)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement