forked from TheAlgorithms/Python
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
c55eb1d
commit cf81911
Showing
2 changed files
with
90 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
import sys, random, cryptomath_module as cryptoMath | ||
|
||
SYMBOLS = """ !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~""" | ||
|
||
def main(): | ||
message = input('Enter message: ') | ||
key = int(input('Enter key [2000 - 9000]: ')) | ||
mode = input('Encrypt/Decrypt [E/D]: ') | ||
|
||
if mode.lower().startswith('e'): | ||
mode = 'encrypt' | ||
translated = encryptMessage(key, message) | ||
elif mode.lower().startswith('d'): | ||
mode = 'decrypt' | ||
translated = decryptMessage(key, message) | ||
print('\n%sed text: \n%s' % (mode.title(), translated)) | ||
|
||
def getKeyParts(key): | ||
keyA = key // len(SYMBOLS) | ||
keyB = key % len(SYMBOLS) | ||
return (keyA, keyB) | ||
|
||
def checkKeys(keyA, keyB, mode): | ||
if keyA == 1 and mode == 'encrypt': | ||
sys.exit('The affine cipher becomes weak when key A is set to 1. Choose different key') | ||
if keyB == 0 and mode == 'encrypt': | ||
sys.exit('The affine cipher becomes weak when key A is set to 1. Choose different key') | ||
if keyA < 0 or keyB < 0 or keyB > len(SYMBOLS) - 1: | ||
sys.exit('Key A must be greater than 0 and key B must be between 0 and %s.' % (len(SYMBOLS) - 1)) | ||
if cryptoMath.gcd(keyA, len(SYMBOLS)) != 1: | ||
sys.exit('Key A %s and the symbol set size %s are not relatively prime. Choose a different key.' % (keyA, len(SYMBOLS))) | ||
|
||
def encryptMessage(key, message): | ||
''' | ||
>>> encryptMessage(4545, 'The affine cipher is a type of monoalphabetic substitution cipher.') | ||
'VL}p MM{I}p~{HL}Gp{vp pFsH}pxMpyxIx JHL O}F{~pvuOvF{FuF{xIp~{HL}Gi' | ||
''' | ||
keyA, keyB = getKeyParts(key) | ||
checkKeys(keyA, keyB, 'encrypt') | ||
cipherText = '' | ||
for symbol in message: | ||
if symbol in SYMBOLS: | ||
symIndex = SYMBOLS.find(symbol) | ||
cipherText += SYMBOLS[(symIndex * keyA + keyB) % len(SYMBOLS)] | ||
else: | ||
cipherText += symbol | ||
return cipherText | ||
|
||
def decryptMessage(key, message): | ||
''' | ||
>>> decryptMessage(4545, 'VL}p MM{I}p~{HL}Gp{vp pFsH}pxMpyxIx JHL O}F{~pvuOvF{FuF{xIp~{HL}Gi') | ||
'The affine cipher is a type of monoalphabetic substitution cipher.' | ||
''' | ||
keyA, keyB = getKeyParts(key) | ||
checkKeys(keyA, keyB, 'decrypt') | ||
plainText = '' | ||
modInverseOfkeyA = cryptoMath.findModInverse(keyA, len(SYMBOLS)) | ||
for symbol in message: | ||
if symbol in SYMBOLS: | ||
symIndex = SYMBOLS.find(symbol) | ||
plainText += SYMBOLS[(symIndex - keyB) * modInverseOfkeyA % len(SYMBOLS)] | ||
else: | ||
plainText += symbol | ||
return plainText | ||
|
||
def getRandomKey(): | ||
while True: | ||
keyA = random.randint(2, len(SYMBOLS)) | ||
keyB = random.randint(2, len(SYMBOLS)) | ||
if cryptoMath.gcd(keyA, len(SYMBOLS)) == 1: | ||
return keyA * len(SYMBOLS) + keyB | ||
|
||
if __name__ == '__main__': | ||
import doctest | ||
doctest.testmod() | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
def gcd(a, b): | ||
while a != 0: | ||
a, b = b % a, a | ||
return b | ||
|
||
def findModInverse(a, m): | ||
if gcd(a, m) != 1: | ||
return None | ||
u1, u2, u3 = 1, 0, a | ||
v1, v2, v3 = 0, 1, m | ||
while v3 != 0: | ||
q = u3 // v3 | ||
v1, v2, v3, u1, u2, u3 = (u1 - q * v1), (u2 - q * v2), (u3 - q *v3), v1, v2, v3 | ||
return u1 % m |