Skip to content

Add autokey cipher and tests #5569

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 9 commits into from
Oct 6, 2024
Merged
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
55 changes: 55 additions & 0 deletions src/main/java/com/thealgorithms/ciphers/Autokey.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package com.thealgorithms.ciphers;

/**
* The Autokey Cipher is an interesting and historically significant encryption method,
* as it improves upon the classic Vigenère Cipher by using the plaintext itself to
* extend the key. This makes it harder to break using frequency analysis, as it
* doesn’t rely solely on a repeated key.
* https://en.wikipedia.org/wiki/Autokey_cipher
*
* @author bennybebo
*/
public class Autokey {

// Encrypts the plaintext using the Autokey cipher
public String encrypt(String plaintext, String keyword) {
plaintext = plaintext.toUpperCase().replaceAll("[^A-Z]", ""); // Sanitize input
keyword = keyword.toUpperCase();

StringBuilder extendedKey = new StringBuilder(keyword);
extendedKey.append(plaintext); // Extend key with plaintext

StringBuilder ciphertext = new StringBuilder();

for (int i = 0; i < plaintext.length(); i++) {
char plainChar = plaintext.charAt(i);
char keyChar = extendedKey.charAt(i);

int encryptedChar = (plainChar - 'A' + keyChar - 'A') % 26 + 'A';
ciphertext.append((char) encryptedChar);
}

return ciphertext.toString();
}

// Decrypts the ciphertext using the Autokey cipher
public String decrypt(String ciphertext, String keyword) {
ciphertext = ciphertext.toUpperCase().replaceAll("[^A-Z]", ""); // Sanitize input
keyword = keyword.toUpperCase();

StringBuilder plaintext = new StringBuilder();
StringBuilder extendedKey = new StringBuilder(keyword);

for (int i = 0; i < ciphertext.length(); i++) {
char cipherChar = ciphertext.charAt(i);
char keyChar = extendedKey.charAt(i);

int decryptedChar = (cipherChar - 'A' - (keyChar - 'A') + 26) % 26 + 'A';
plaintext.append((char) decryptedChar);

extendedKey.append((char) decryptedChar); // Extend key with each decrypted char
}

return plaintext.toString();
}
}
36 changes: 36 additions & 0 deletions src/test/java/com/thealgorithms/ciphers/AutokeyTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.thealgorithms.ciphers;

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.api.Test;

class AutokeyCipherTest {

Autokey autokeyCipher = new Autokey();

@Test
void autokeyEncryptTest() {
// given
String plaintext = "MEET AT DAWN";
String keyword = "QUEEN";

// when
String cipherText = autokeyCipher.encrypt(plaintext, keyword);

// then
assertEquals("CYIXNFHEPN", cipherText);
}

@Test
void autokeyDecryptTest() {
// given
String ciphertext = "CYIX NF HEPN";
String keyword = "QUEEN";

// when
String plainText = autokeyCipher.decrypt(ciphertext, keyword);

// then
assertEquals("MEETATDAWN", plainText);
}
}