From 30c9d29966772fb2343ee5c02b52c4158e16671b Mon Sep 17 00:00:00 2001 From: Om-Alve Date: Mon, 2 Oct 2023 15:49:47 +0530 Subject: [PATCH 1/9] Added fractionated_morse_cipher --- ciphers/fractionated_morse_cipher.py | 175 +++++++++++++++++++++++++++ 1 file changed, 175 insertions(+) create mode 100644 ciphers/fractionated_morse_cipher.py diff --git a/ciphers/fractionated_morse_cipher.py b/ciphers/fractionated_morse_cipher.py new file mode 100644 index 000000000000..0a21e680bd43 --- /dev/null +++ b/ciphers/fractionated_morse_cipher.py @@ -0,0 +1,175 @@ +""" +Python program for the Fractionated Morse Cipher. + +The Fractionated Morse cipher first converts the plaintext to morse code, +then enciphers fixed-size blocks of morse code back to letters. +This procedure means plaintext letters are mixed into the ciphertext letters, +making it more secure than substitution ciphers. + +For more information visit - http://practicalcryptography.com/ciphers/fractionated-morse-cipher/ + +""" + + +import string + +# Define Morse code dictionary +MORSE_CODE_DICT = { + "A": ".-", + "B": "-...", + "C": "-.-.", + "D": "-..", + "E": ".", + "F": "..-.", + "G": "--.", + "H": "....", + "I": "..", + "J": ".---", + "K": "-.-", + "L": ".-..", + "M": "--", + "N": "-.", + "O": "---", + "P": ".--.", + "Q": "--.-", + "R": ".-.", + "S": "...", + "T": "-", + "U": "..-", + "V": "...-", + "W": ".--", + "X": "-..-", + "Y": "-.--", + "Z": "--..", + " ": "", +} + +# Define possible trigrams of Morse code +MORSE_COMBINATIONS = [ + "...", + "..-", + "..x", + ".-.", + ".--", + ".-x", + ".x.", + ".x-", + ".xx", + "-..", + "-.-", + "-.x", + "--.", + "---", + "--x", + "-x.", + "-x-", + "-xx", + "x..", + "x.-", + "x.x", + "x-.", + "x--", + "x-x", + "xx.", + "xx-", + "xxx", +] + +# Create a reverse dictionary for Morse code +REVERSE_DICT = {value: key for key, value in MORSE_CODE_DICT.items()} + + +def encode_to_morse(plaintext: str) -> str: + """Encode a plaintext message into Morse code. + + Args: + plaintext (str): The plaintext message to encode. + + Returns: + str: The Morse code representation of the plaintext message. + + Example: + >>> encode_to_morse("defend the east") + '-..x.x..-.x.x-.x-..xx-x....x.xx.x.-x...x-' + """ + return "x".join([MORSE_CODE_DICT.get(letter.upper(), "") for letter in plaintext]) + + +def encrypt_fractionated_morse(plaintext: str, key: str) -> str: + """Encrypt a plaintext message using Fractionated Morse Cipher. + + Args: + plaintext (str): The plaintext message to encrypt. + key (str): The encryption key. + + Returns: + str: The encrypted ciphertext. + + Example: + >>> encrypt_fractionated_morse("defend the east","Roundtable") + 'ESOAVVLJRSSTRX' + + """ + morse_code = encode_to_morse(plaintext) + key = key.upper() + string.ascii_uppercase + key = "".join(sorted(set(key), key=key.find)) + + # Ensure morse_code length is a multiple of 3 + padding_length = 3 - (len(morse_code) % 3) + morse_code += "x" * padding_length + + fractionated_morse_dict = { + value: key for key, value in zip(key, MORSE_COMBINATIONS) + } + fractionated_morse_dict["xxx"] = "" + encrypted_text = "".join( + [ + fractionated_morse_dict[morse_code[i : i + 3]] + for i in range(0, len(morse_code), 3) + ] + ) + return encrypted_text + + +def decrypt_fractionated_morse(ciphertext: str, key: str) -> str: + """Decrypt a ciphertext message encrypted with Fractionated Morse Cipher. + + Args: + ciphertext (str): The ciphertext message to decrypt. + key (str): The decryption key. + + Returns: + str: The decrypted plaintext message. + + Example: + >>> decrypt_fractionated_morse("ESOAVVLJRSSTRX","Roundtable") + 'DEFEND THE EAST' + """ + key = key.upper() + string.ascii_uppercase + key = "".join(sorted(set(key), key=key.find)) + + inverse_fractionated_morse_dict = dict(zip(key, MORSE_COMBINATIONS)) + morse_code = "".join( + [inverse_fractionated_morse_dict.get(letter, "") for letter in ciphertext] + ) + decrypted_text = "".join( + [REVERSE_DICT[code] for code in morse_code.split("x")] + ).strip() + return decrypted_text + + +def main(): + """Example usage of Fractionated Morse Cipher.""" + plaintext = "defend the east" + print("Plain Text:", plaintext) + key = "ROUNDTABLE" + + ciphertext = encrypt_fractionated_morse(plaintext, key) + print("Encrypted:", ciphertext) + + decrypted_text = decrypt_fractionated_morse(ciphertext, key) + print("Decrypted:", decrypted_text) + + +if __name__ == "__main__": + main() From 9f2d8fe65c5e6de47c9972e1a0e57f477ead9d98 Mon Sep 17 00:00:00 2001 From: Om-Alve Date: Mon, 2 Oct 2023 16:07:30 +0530 Subject: [PATCH 2/9] Added return type hint for main function --- ciphers/fractionated_morse_cipher.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ciphers/fractionated_morse_cipher.py b/ciphers/fractionated_morse_cipher.py index 0a21e680bd43..f5e8b9c1c524 100644 --- a/ciphers/fractionated_morse_cipher.py +++ b/ciphers/fractionated_morse_cipher.py @@ -158,8 +158,10 @@ def decrypt_fractionated_morse(ciphertext: str, key: str) -> str: return decrypted_text -def main(): - """Example usage of Fractionated Morse Cipher.""" +def main() -> None: + """ + Example usage of Fractionated Morse Cipher. + """ plaintext = "defend the east" print("Plain Text:", plaintext) key = "ROUNDTABLE" From 69d9456f3d4ef6cd58428045d1214791d9d556a5 Mon Sep 17 00:00:00 2001 From: Om-Alve Date: Mon, 2 Oct 2023 16:15:39 +0530 Subject: [PATCH 3/9] Added doctest for main --- ciphers/fractionated_morse_cipher.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ciphers/fractionated_morse_cipher.py b/ciphers/fractionated_morse_cipher.py index f5e8b9c1c524..1cb65beaf3dc 100644 --- a/ciphers/fractionated_morse_cipher.py +++ b/ciphers/fractionated_morse_cipher.py @@ -161,6 +161,12 @@ def decrypt_fractionated_morse(ciphertext: str, key: str) -> str: def main() -> None: """ Example usage of Fractionated Morse Cipher. + + >>> main() + Plain Text: defend the east + Encrypted: ESOAVVLJRSSTRX + Decrypted: DEFEND THE EAST + """ plaintext = "defend the east" print("Plain Text:", plaintext) From a1f40d30bbe8a56cc0d24978ae287a1d01eb1f2f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 2 Oct 2023 10:47:30 +0000 Subject: [PATCH 4/9] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- ciphers/fractionated_morse_cipher.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ciphers/fractionated_morse_cipher.py b/ciphers/fractionated_morse_cipher.py index 1cb65beaf3dc..f253e5102bc1 100644 --- a/ciphers/fractionated_morse_cipher.py +++ b/ciphers/fractionated_morse_cipher.py @@ -161,12 +161,12 @@ def decrypt_fractionated_morse(ciphertext: str, key: str) -> str: def main() -> None: """ Example usage of Fractionated Morse Cipher. - + >>> main() Plain Text: defend the east Encrypted: ESOAVVLJRSSTRX Decrypted: DEFEND THE EAST - + """ plaintext = "defend the east" print("Plain Text:", plaintext) From 89a0fc1aca9cdcb7913b3c3bba3fae4d3c34dfee Mon Sep 17 00:00:00 2001 From: Om-Alve Date: Mon, 2 Oct 2023 16:28:13 +0530 Subject: [PATCH 5/9] Replaced main function --- ciphers/fractionated_morse_cipher.py | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/ciphers/fractionated_morse_cipher.py b/ciphers/fractionated_morse_cipher.py index 1cb65beaf3dc..31733fde8934 100644 --- a/ciphers/fractionated_morse_cipher.py +++ b/ciphers/fractionated_morse_cipher.py @@ -158,15 +158,9 @@ def decrypt_fractionated_morse(ciphertext: str, key: str) -> str: return decrypted_text -def main() -> None: +if __name__ == "__main__": """ Example usage of Fractionated Morse Cipher. - - >>> main() - Plain Text: defend the east - Encrypted: ESOAVVLJRSSTRX - Decrypted: DEFEND THE EAST - """ plaintext = "defend the east" print("Plain Text:", plaintext) @@ -177,7 +171,3 @@ def main() -> None: decrypted_text = decrypt_fractionated_morse(ciphertext, key) print("Decrypted:", decrypted_text) - - -if __name__ == "__main__": - main() From cd01d4d5f378dc93b3ea6661f207853e25f1c539 Mon Sep 17 00:00:00 2001 From: Om Alve Date: Sun, 8 Oct 2023 15:19:48 +0530 Subject: [PATCH 6/9] changed the references section Co-authored-by: Christian Clauss --- ciphers/fractionated_morse_cipher.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ciphers/fractionated_morse_cipher.py b/ciphers/fractionated_morse_cipher.py index 31733fde8934..d6b589ce2373 100644 --- a/ciphers/fractionated_morse_cipher.py +++ b/ciphers/fractionated_morse_cipher.py @@ -6,7 +6,7 @@ This procedure means plaintext letters are mixed into the ciphertext letters, making it more secure than substitution ciphers. -For more information visit - http://practicalcryptography.com/ciphers/fractionated-morse-cipher/ +http://practicalcryptography.com/ciphers/fractionated-morse-cipher/ """ From 95471d965e0ff70683bbbfab1549738148e03770 Mon Sep 17 00:00:00 2001 From: Om Alve Date: Sun, 8 Oct 2023 15:20:32 +0530 Subject: [PATCH 7/9] removed repetitive datatype hint in the docstring Co-authored-by: Christian Clauss --- ciphers/fractionated_morse_cipher.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ciphers/fractionated_morse_cipher.py b/ciphers/fractionated_morse_cipher.py index d6b589ce2373..4252cc604c12 100644 --- a/ciphers/fractionated_morse_cipher.py +++ b/ciphers/fractionated_morse_cipher.py @@ -83,7 +83,7 @@ def encode_to_morse(plaintext: str) -> str: """Encode a plaintext message into Morse code. Args: - plaintext (str): The plaintext message to encode. + plaintext: The plaintext message to encode. Returns: str: The Morse code representation of the plaintext message. From df7b182d1d455189b72b3b1f3328842d0e9a9bce Mon Sep 17 00:00:00 2001 From: Om Alve Date: Sun, 8 Oct 2023 15:22:12 +0530 Subject: [PATCH 8/9] changed dictionary comprehension variable names to something more compact Co-authored-by: Christian Clauss --- ciphers/fractionated_morse_cipher.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ciphers/fractionated_morse_cipher.py b/ciphers/fractionated_morse_cipher.py index 4252cc604c12..610bf0efaa3a 100644 --- a/ciphers/fractionated_morse_cipher.py +++ b/ciphers/fractionated_morse_cipher.py @@ -118,9 +118,7 @@ def encrypt_fractionated_morse(plaintext: str, key: str) -> str: padding_length = 3 - (len(morse_code) % 3) morse_code += "x" * padding_length - fractionated_morse_dict = { - value: key for key, value in zip(key, MORSE_COMBINATIONS) - } + fractionated_morse_dict = {v: k for k, v in zip(key, MORSE_COMBINATIONS)} fractionated_morse_dict["xxx"] = "" encrypted_text = "".join( [ From 74d71d0f0c679ca5312a5e5a09d0510414739c03 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Sun, 8 Oct 2023 12:36:09 +0200 Subject: [PATCH 9/9] Update fractionated_morse_cipher.py --- ciphers/fractionated_morse_cipher.py | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/ciphers/fractionated_morse_cipher.py b/ciphers/fractionated_morse_cipher.py index 610bf0efaa3a..c1d5dc6d50aa 100644 --- a/ciphers/fractionated_morse_cipher.py +++ b/ciphers/fractionated_morse_cipher.py @@ -1,19 +1,15 @@ """ Python program for the Fractionated Morse Cipher. -The Fractionated Morse cipher first converts the plaintext to morse code, -then enciphers fixed-size blocks of morse code back to letters. +The Fractionated Morse cipher first converts the plaintext to Morse code, +then enciphers fixed-size blocks of Morse code back to letters. This procedure means plaintext letters are mixed into the ciphertext letters, making it more secure than substitution ciphers. http://practicalcryptography.com/ciphers/fractionated-morse-cipher/ - """ - - import string -# Define Morse code dictionary MORSE_CODE_DICT = { "A": ".-", "B": "-...", @@ -86,7 +82,7 @@ def encode_to_morse(plaintext: str) -> str: plaintext: The plaintext message to encode. Returns: - str: The Morse code representation of the plaintext message. + The Morse code representation of the plaintext message. Example: >>> encode_to_morse("defend the east") @@ -99,11 +95,11 @@ def encrypt_fractionated_morse(plaintext: str, key: str) -> str: """Encrypt a plaintext message using Fractionated Morse Cipher. Args: - plaintext (str): The plaintext message to encrypt. - key (str): The encryption key. + plaintext: The plaintext message to encrypt. + key: The encryption key. Returns: - str: The encrypted ciphertext. + The encrypted ciphertext. Example: >>> encrypt_fractionated_morse("defend the east","Roundtable") @@ -133,11 +129,11 @@ def decrypt_fractionated_morse(ciphertext: str, key: str) -> str: """Decrypt a ciphertext message encrypted with Fractionated Morse Cipher. Args: - ciphertext (str): The ciphertext message to decrypt. - key (str): The decryption key. + ciphertext: The ciphertext message to decrypt. + key: The decryption key. Returns: - str: The decrypted plaintext message. + The decrypted plaintext message. Example: >>> decrypt_fractionated_morse("ESOAVVLJRSSTRX","Roundtable")