Skip to content

fix main loading from command line, exit status and some cosmetics #22

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ def main() -> None:
"""
parser = argparse.ArgumentParser(description='Break One-Time Pad Encryption with key reuse')
parser.add_argument('file', type=str, help='file containing hexadecimal ciphertexts, delimited by new lines')
parser.add_argument('-o', type=str, dest='output_file', default='result.json', help='filename to export decryptions to')
parser.add_argument('-o', type=str, dest='output_file', default='result.json', help='filename to export '
'decryptions to')
args = parser.parse_args()

with open(args.file, 'r') as f:
Expand All @@ -21,6 +22,10 @@ def main() -> None:
try:
ciphertexts = list(map(bytearray.fromhex, ciphertexts))
except ValueError as error:
sys.exit("Invalid hexadecimal: {error}")
sys.exit(f"Invalid hexadecimal: {error}")

many_time_pad_attack(ciphertexts, args.output_file)


if __name__ == "__main__":
main()
7 changes: 4 additions & 3 deletions manytime/analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,10 @@ def recover_partial_key(ciphertexts: Iterable[bytearray]) -> List[Optional[int]]
# Although we know it is a space we don't know which ciphertext it came from
main_counter.update(track_spaces(xor(main_ciphertext, secondary_ciphertext)))

# Now we have tracked all the possible spaces we have seen, anchored to the index of the main ciphertext where we saw it
# Therefore, if we have seen a space len(ciphertexts) - 1 times in a certain position, we know that because it was present
# when XORd with each ciphertext, that it must have come from the main_ciphertext. Meaning, that position is a space in the main_plaintext
# Now we have tracked all the possible spaces we have seen, anchored to the index of the main ciphertext
# where we saw it Therefore, if we have seen a space len(ciphertexts) - 1 times in a certain position,
# we know that because it was present when XORd with each ciphertext, that it must have come from the
# main_ciphertext. Meaning, that position is a space in the main_plaintext
for index, count in main_counter.items():
if count == len(ciphertexts) - 1:
key[index] = ord(' ') ^ main_ciphertext[index]
Expand Down
7 changes: 4 additions & 3 deletions manytime/interactive.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

import json
import urwid
from enum import Enum

from manytime import keys

Expand All @@ -13,7 +12,8 @@
from typing import Iterable, Optional, Tuple, NoReturn, Union, Any, List


def partial_decrypt(key: Key, ciphertext: bytearray, unknown_character: Union[Tuple[str, str], str] = ('unknown', '_')) -> Iterable:
def partial_decrypt(key: Key, ciphertext: bytearray,
unknown_character: Union[Tuple[str, str], str] = ('unknown', '_')) -> Iterable:
"""
Decrypt ciphertext using key
Decrypting a letter using an unknown key element will result in unknown_character
Expand Down Expand Up @@ -61,7 +61,8 @@ def _edit_decryption(self, letter: str) -> None:
# Letters which are longer, for example "shift left" are not key presses we want to deal with.
# All special characters are handled elsewhere, this code handles letters and delete keys
# therefore we ignore all others.
self.application.key[index] = None if letter in self.REMOVE_KEYS or len(letter) > 1 else ord(letter) ^ ciphertext[index]
self.application.key[index] = None if (letter in self.REMOVE_KEYS or
len(letter) > 1) else ord(letter) ^ ciphertext[index]

# Update all decryptions
new_decryptions = [partial_decrypt(self.application.key, c) for c in self.application.ciphertexts]
Expand Down
2 changes: 1 addition & 1 deletion manytime/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from manytime import keys

from typing import Optional, List, Tuple, Union, Iterator
from typing import Optional, List, Tuple, Union, Iterator, Any


class Key:
Expand Down