# Null Cipher Hacker
# http://inventwithpython.com/hacking (BSD Licensed)
import nullCipher, pyperclip, detectEnglish, itertools
# There are two settings our hacking program needs to limit the range of
# the possible keys it checks.
# MAX_KEY_NUMBER is the range of numbers it checks for each number in the
# key. A MAX_KEY_NUMBER value of 9 means it will check 0 through 9.
# MAX_KEY_DIGITS is the largest amount of numbers in the key. A value of 5
# means that the key could be something like '1 2 3 4 5' or '1 1 1 1 1' or
# '1 2 3 4', but not '1 2 3 4 5 6'
# If these numbers are too large, then hacking the code will take a long
# time. If these numbers are too small, then the hacking program won't be
# able to hack the encryption.
MAX_KEY_NUMBER = 9
MAX_KEY_DIGITS = 5
SILENT_MODE = False
# This can be copy/pasted from http://invpy.com/nullHacker.py
myMessage = """sn Wht eetan mnIeu uedswsae aiaeh wh ohh rdrh, h ihotote muoeh annesets jtwunetst - e-rwhe am jt Inoo c,nh oossssace oai o t oWth.no miiteaton r -s -ou nwse. nito hwiieroe s imoiorot e o nsesorer anletesmt s.ah"""
def main():
# Calculate the number of keys that the current MAX_KEY_DIGITS and
# MAX_KEY_NUMBER values will cause the hacker program to go through.
possibleKeys = 0 # start the number of keys at 0.
for i in range(1, MAX_KEY_DIGITS + 1):
# To find the total number of possible keys, add the total number
# of keys for 1-digit keys, 2-digit keys, and so on up to
# MAX_KEY_DIGITS-digit keys.
# To find the number of keys with i digits in them, multiply the
# range of numbers (that is, MAX_KEY_NUMBER) by itself i times.
# That is, we find MAX_KEY_NUMBER to the ith power.
possibleKeys += MAX_KEY_NUMBER ** i
# After exiting the loop, the value in possibleKeys is the total number
# of keys for MAX_KEY_NUMBER and MAX_KEY_RANGE.
print('Max key number: %s' % MAX_KEY_NUMBER)
print('Max key length: %s' % MAX_KEY_DIGITS)
print('Possible keys to try: %s' % (possibleKeys))
print()
# Python programs can be stopped at any time by pressing Ctrl-C (on
# Windows) or Ctrl-D (on Mac and Linux)
print('(Press Ctrl-C or Ctrl-D to quit at any time.)')
print('Hacking...')
brokenMessage = hackNull(myMessage)
if brokenMessage != None:
print('Copying broken message to clipboard:')
print(brokenMessage)
pyperclip.copy(brokenMessage)
else:
print('Failed to hack encryption.')
def hackNull(ciphertext):
# The program needs to try keys of length 1 (such as '5'), of length 2
# (such as '5 3'), and so on up to length MAX_KEY_DIGITS.
for keyLength in range(1, MAX_KEY_DIGITS + 1):
for keyParts in itertools.product(range(MAX_KEY_NUMBER + 1), repeat=keyLength):
key = []
for digit in keyParts:
key.append(str(digit))
key = ''.join(key)
decryptedText = nullCipher.decryptMessage(key, ciphertext)
if not SILENT_MODE:
print('Key %s: %s' % (key, decryptedText[:40]))
if detectEnglish.isEnglish(decryptedText):
print()
print('Possible encryption hack:')
print('Key: %s' % (key))
print('Decrypted message: ' + decryptedText[:200])
print()
print('Enter D for done, or just press Enter to continue hacking:')
response = input('> ')
if response.strip().upper().startswith('D'):
return decryptedText
return None # failed to hack encryption
if __name__ == '__main__':
main()