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.
Add autoclave cipher (TheAlgorithms#8029)
* Add autoclave cipher * Update autoclave with the given suggestions * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fixing errors * Another fixes * Update and rename autoclave.py to autokey.py * Rename gaussian_naive_bayes.py to gaussian_naive_bayes.py.broken.txt * Rename gradient_boosting_regressor.py to gradient_boosting_regressor.py.broken.txt * Rename random_forest_classifier.py to random_forest_classifier.py.broken.txt * Rename random_forest_regressor.py to random_forest_regressor.py.broken.txt * Rename equal_loudness_filter.py to equal_loudness_filter.py.broken.txt Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss <cclauss@me.com>
- Loading branch information
1 parent
30277f8
commit 3f8b2af
Showing
6 changed files
with
131 additions
and
0 deletions.
There are no files selected for viewing
File renamed without changes.
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,131 @@ | ||
""" | ||
https://en.wikipedia.org/wiki/Autokey_cipher | ||
An autokey cipher (also known as the autoclave cipher) is a cipher that | ||
incorporates the message (the plaintext) into the key. | ||
The key is generated from the message in some automated fashion, | ||
sometimes by selecting certain letters from the text or, more commonly, | ||
by adding a short primer key to the front of the message. | ||
""" | ||
|
||
|
||
def encrypt(plaintext: str, key: str) -> str: | ||
""" | ||
Encrypt a given plaintext (string) and key (string), returning the | ||
encrypted ciphertext. | ||
>>> encrypt("hello world", "coffee") | ||
'jsqqs avvwo' | ||
>>> encrypt("coffee is good as python", "TheAlgorithms") | ||
'vvjfpk wj ohvp su ddylsv' | ||
>>> encrypt("coffee is good as python", 2) | ||
Traceback (most recent call last): | ||
... | ||
TypeError: key must be a string | ||
>>> encrypt("", "TheAlgorithms") | ||
Traceback (most recent call last): | ||
... | ||
ValueError: plaintext is empty | ||
""" | ||
if not isinstance(plaintext, str): | ||
raise TypeError("plaintext must be a string") | ||
if not isinstance(key, str): | ||
raise TypeError("key must be a string") | ||
|
||
if not plaintext: | ||
raise ValueError("plaintext is empty") | ||
if not key: | ||
raise ValueError("key is empty") | ||
|
||
key += plaintext | ||
plaintext = plaintext.lower() | ||
key = key.lower() | ||
plaintext_iterator = 0 | ||
key_iterator = 0 | ||
ciphertext = "" | ||
while plaintext_iterator < len(plaintext): | ||
if ( | ||
ord(plaintext[plaintext_iterator]) < 97 | ||
or ord(plaintext[plaintext_iterator]) > 122 | ||
): | ||
ciphertext += plaintext[plaintext_iterator] | ||
plaintext_iterator += 1 | ||
elif ord(key[key_iterator]) < 97 or ord(key[key_iterator]) > 122: | ||
key_iterator += 1 | ||
else: | ||
ciphertext += chr( | ||
( | ||
(ord(plaintext[plaintext_iterator]) - 97 + ord(key[key_iterator])) | ||
- 97 | ||
) | ||
% 26 | ||
+ 97 | ||
) | ||
key_iterator += 1 | ||
plaintext_iterator += 1 | ||
return ciphertext | ||
|
||
|
||
def decrypt(ciphertext: str, key: str) -> str: | ||
""" | ||
Decrypt a given ciphertext (string) and key (string), returning the decrypted | ||
ciphertext. | ||
>>> decrypt("jsqqs avvwo", "coffee") | ||
'hello world' | ||
>>> decrypt("vvjfpk wj ohvp su ddylsv", "TheAlgorithms") | ||
'coffee is good as python' | ||
>>> decrypt("vvjfpk wj ohvp su ddylsv", "") | ||
Traceback (most recent call last): | ||
... | ||
ValueError: key is empty | ||
>>> decrypt(527.26, "TheAlgorithms") | ||
Traceback (most recent call last): | ||
... | ||
TypeError: ciphertext must be a string | ||
""" | ||
if not isinstance(ciphertext, str): | ||
raise TypeError("ciphertext must be a string") | ||
if not isinstance(key, str): | ||
raise TypeError("key must be a string") | ||
|
||
if not ciphertext: | ||
raise ValueError("ciphertext is empty") | ||
if not key: | ||
raise ValueError("key is empty") | ||
|
||
key = key.lower() | ||
ciphertext_iterator = 0 | ||
key_iterator = 0 | ||
plaintext = "" | ||
while ciphertext_iterator < len(ciphertext): | ||
if ( | ||
ord(ciphertext[ciphertext_iterator]) < 97 | ||
or ord(ciphertext[ciphertext_iterator]) > 122 | ||
): | ||
plaintext += ciphertext[ciphertext_iterator] | ||
else: | ||
plaintext += chr( | ||
(ord(ciphertext[ciphertext_iterator]) - ord(key[key_iterator])) % 26 | ||
+ 97 | ||
) | ||
key += chr( | ||
(ord(ciphertext[ciphertext_iterator]) - ord(key[key_iterator])) % 26 | ||
+ 97 | ||
) | ||
key_iterator += 1 | ||
ciphertext_iterator += 1 | ||
return plaintext | ||
|
||
|
||
if __name__ == "__main__": | ||
import doctest | ||
|
||
doctest.testmod() | ||
operation = int(input("Type 1 to encrypt or 2 to decrypt:")) | ||
if operation == 1: | ||
plaintext = input("Typeplaintext to be encrypted:\n") | ||
key = input("Type the key:\n") | ||
print(encrypt(plaintext, key)) | ||
elif operation == 2: | ||
ciphertext = input("Type the ciphertext to be decrypted:\n") | ||
key = input("Type the key:\n") | ||
print(decrypt(ciphertext, key)) | ||
decrypt("jsqqs avvwo", "coffee") |
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.