-
-
Notifications
You must be signed in to change notification settings - Fork 46.8k
Added ciphers/permutation_cipher.py. #9163
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
Merged
Merged
Changes from 7 commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
e96ae3d
Added permutation_cipher.py
aryan1165 71d41d9
Merge branch 'TheAlgorithms:master' into permutation
aryan1165 33bdaaf
Merge branch 'TheAlgorithms:master' into permutation
aryan1165 214e45c
Added type hints for parameters
aryan1165 c51a20e
Added doctest in functions
aryan1165 f970050
Merge branch 'TheAlgorithms:master' into permutation
aryan1165 aa01701
Merge branch 'TheAlgorithms:master' into permutation
aryan1165 7aed648
Merge branch 'TheAlgorithms:master' into permutation
aryan1165 e62f050
Update ciphers/permutation_cipher.py
aryan1165 249a763
Update ciphers/permutation_cipher.py
aryan1165 ccf850e
Update ciphers/permutation_cipher.py
aryan1165 ad2d094
Update ciphers/permutation_cipher.py
aryan1165 668b30f
Update ciphers/permutation_cipher.py
aryan1165 473dd86
Update ciphers/permutation_cipher.py
aryan1165 8051d44
Update ciphers/permutation_cipher.py
aryan1165 97b2cb9
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 9e0daad
Changes
aryan1165 b3b2b51
Merge branch 'permutation' of https://github.com/aryan1165/Python int…
aryan1165 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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,139 @@ | ||
""" | ||
The Permutation Cipher, implemented above, is a simple encryption | ||
technique that rearranges the characters in a message based on a secret key. | ||
It divides the message into blocks and applies a permutation to the characters | ||
within each block according to the key. The key is a sequence of unique integers | ||
that determine the order of character rearrangement. For more info read:- | ||
https://www.nku.edu/~christensen/1402%20permutation%20ciphers.pdf | ||
|
||
""" | ||
import random | ||
|
||
|
||
def generate_valid_block_size(message_length: int) -> int: | ||
aryan1165 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
""" | ||
Generate a valid block size that is a factor of the message length. | ||
|
||
Args: | ||
message_length (int): The length of the message. | ||
|
||
Returns: | ||
int: A valid block size. | ||
|
||
Example: | ||
>>> generate_valid_block_size(2) | ||
2 | ||
""" | ||
while True: | ||
block_size = random.randint(2, message_length) | ||
if message_length % block_size == 0: | ||
return block_size | ||
aryan1165 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
|
||
def generate_permutation_key(block_size: int) -> list: | ||
aryan1165 marked this conversation as resolved.
Show resolved
Hide resolved
aryan1165 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
""" | ||
Generate a random permutation key of a specified block size. | ||
|
||
Args: | ||
block_size (int): The size of each permutation block. | ||
|
||
Returns: | ||
list[int]: A list containing a random permutation of digits. | ||
|
||
Example: | ||
>>> generate_permutation_key(1) | ||
[1] | ||
""" | ||
digits = list(range(1, block_size + 1)) | ||
aryan1165 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
random.shuffle(digits) | ||
key = digits | ||
return key | ||
aryan1165 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
|
||
def encrypt( | ||
message: str, key: list | None = None, block_size: int | None = None | ||
) -> tuple: | ||
aryan1165 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
""" | ||
Encrypt a message using a permutation cipher with block rearrangement using a key. | ||
|
||
Args: | ||
message (str): The plaintext message to be encrypted. | ||
key (list[int]): The permutation key for decryption. | ||
block_size (int): The size of each permutation block. | ||
|
||
Returns: | ||
tuple: A tuple containing the encrypted message and the encryption key. | ||
|
||
Example: | ||
>>> encrypted_message, key = encrypt("HELLO WORLD") | ||
>>> decrypted_message = decrypt(encrypted_message, key) | ||
>>> decrypted_message | ||
'HELLO WORLD' | ||
""" | ||
message = message.upper() | ||
message_length = len(message) | ||
|
||
if key is None or block_size is None: | ||
block_size = generate_valid_block_size(message_length) | ||
key = generate_permutation_key(block_size) | ||
|
||
encrypted_message = "" | ||
|
||
for i in range(0, message_length, block_size): | ||
block = message[i : i + block_size] | ||
rearranged_block = [block[digit - 1] for digit in key] | ||
encrypted_message += "".join(rearranged_block) | ||
|
||
return encrypted_message, key | ||
|
||
|
||
def decrypt(encrypted_message: str, key: list) -> str: | ||
aryan1165 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
""" | ||
Decrypt an encrypted message using a permutation cipher with block rearrangement. | ||
|
||
Args: | ||
encrypted_message (str): The encrypted message. | ||
key (list[int]): The permutation key for decryption. | ||
|
||
Returns: | ||
str: The decrypted plaintext message. | ||
|
||
Example: | ||
>>> encrypted_message, key = encrypt("HELLO WORLD") | ||
>>> decrypted_message = decrypt(encrypted_message, key) | ||
>>> decrypted_message | ||
'HELLO WORLD' | ||
""" | ||
key_length = len(key) | ||
decrypted_message = "" | ||
|
||
for i in range(0, len(encrypted_message), key_length): | ||
block = encrypted_message[i : i + key_length] | ||
original_block = [""] * key_length | ||
for j, digit in enumerate(key): | ||
original_block[digit - 1] = block[j] | ||
decrypted_message += "".join(original_block) | ||
|
||
return decrypted_message | ||
|
||
|
||
def main() -> None: | ||
aryan1165 marked this conversation as resolved.
Show resolved
Hide resolved
aryan1165 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
""" | ||
Driver function to pass message to get encrypted, then decrypted. | ||
|
||
Example: | ||
>>> main() | ||
Decrypted message: HELLO WORLD | ||
""" | ||
message = "HELLO WORLD" | ||
encrypted_message, key = encrypt(message) | ||
|
||
decrypted_message = decrypt(encrypted_message, key) | ||
print(f"Decrypted message: {decrypted_message}") | ||
|
||
|
||
if __name__ == "__main__": | ||
import doctest | ||
|
||
doctest.testmod() | ||
main() |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.