Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 79 lines (60 sloc) 2.389 kb
f16b361 Al Sweigart Initial commit.
authored
1 # Affine Cipher
2 # http://inventwithpython.com/codebreaker (BSD Licensed)
3 import sys, random, pyperclip
4
5 SYMBOLS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
6
7
8 def main():
9 message = 'A COMPUTER WOULD DESERVE TO BE CALLED INTELLIGENT IF IT COULD DECEIVE A HUMAN INTO BELIEVING THAT IT WAS HUMAN. -ALAN TURING'
10 keyA, keyB = 5, 7
11 mode = 'encrypt' # set to 'encrypt' or 'decrypt'
12
13 message = message.upper()
14
15 if keyA == 1:
16 sys.exit('The affine cipher becomes incredibly weak when keyA is set to 1. Choose a different key.')
17 if keyB == 0:
18 sys.exit('The affine cipher becomes incredibly weak when keyB is set to 0. Choose a different key.')
19 if gcd(keyA, len(SYMBOLS)) != 1:
20 sys.exit('The key (%s) and the size of the alphabet (%s) are not relatively prime. Choose a different key.' % (key, len(SYMBOLS)))
21
22 print('Original text:')
23 print(message)
24
25 if mode == 'encrypt':
26 translated = encryptMessage(keyA, keyB, message)
27 elif mode == 'decrypt':
28 translated = decryptMessage(keyA, keyB, message)
29
30 print('%sed text:' % (mode.title()))
31 print(translated)
32 pyperclip.copy(translated)
33 print('%sed text copied to clipboard.' % (mode.title()))
34
35
36 def gcd(a, b):
37 # Return the Greatest Common Divisor of a and b.
38 while a != 0:
39 a, b = b % a, a
40 return b
41
42
43 def findModInverse(a, m):
44 for b in range(m):
45 if (a * b) % m == 1:
46 return b
47 return None # None is returned only when gcd(a, m) == 1, which is invalid.
48
49
50 def encryptMessage(keyA, keyB, message):
51 ciphertext = ''
52 for symbol in message:
53 symIndex = SYMBOLS.find(symbol)
54 if symIndex != -1:
55 # encrypt this symbol
56 ciphertext += SYMBOLS[(symIndex * keyA + keyB) % len(SYMBOLS)]
57 else:
58 # just append this symbol unencrypted
59 ciphertext += symbol
60 return ciphertext
61
62
63 def decryptMessage(keyA, keyB, message):
64 plaintext = ''
65 modInverseOfKeyA = findModInverse(keyA, len(SYMBOLS))
66
67 for symbol in message:
68 symIndex = SYMBOLS.find(symbol)
69 if symIndex != -1:
70 # decrypt this symbol
71 plaintext += SYMBOLS[(symIndex - keyB) * modInverseOfKeyA % len(SYMBOLS)]
72 else:
73 # just append this symbol unencrypted
74 plaintext += symbol
75 return plaintext
76
77
78 if __name__ == '__main__':
79 main()
Something went wrong with that request. Please try again.