diff --git a/composer.json b/composer.json index 8944c1e..354678d 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,11 @@ { - "name": "amculin/classic-encryption", + "name": "amculin/vigenere-cipher", "license": "MIT", - "description": "Simple implementation of classic cryptography algorithm using PHP", + "description": "Implementation of Vigenere Cipher algorithm in PHP", + "keywords": [ + "php", "encryption", "decryption", "vigenere cipher", "classic cryptography", "cryptography", + "encrypt", "decrypt" + ], "authors": [ { "name": "Fahmi Auliya Tsani", @@ -11,7 +15,7 @@ ], "autoload": { "psr-4": { - "amculin\\encryption\\": "source/" + "amculin\\cryptography\\classic\\": "source/" } } } \ No newline at end of file diff --git a/source/AlnumVigenereCipher.php b/source/AlnumVigenereCipher.php new file mode 100644 index 0000000..bf14c3a --- /dev/null +++ b/source/AlnumVigenereCipher.php @@ -0,0 +1,20 @@ + + * @version 0.1 + */ + +class AlnumVigenereCipher extends VigenereCipherBlueprint +{ + /** + * Default list of acceptable character to be used in vigenere cipher algorithm + * This list cointains alpha-numeric characters including the capitalized + * + * @var string + */ + public $tabulaRecta = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; +} diff --git a/source/BasicVigenereCipher.php b/source/BasicVigenereCipher.php new file mode 100644 index 0000000..80f151b --- /dev/null +++ b/source/BasicVigenereCipher.php @@ -0,0 +1,17 @@ + + * @version 0.2 + */ + +class BasicVigenereCipher extends VigenereCipherBlueprint +{ + /** + * @inheritdoc + */ + public $tabulaRecta = 'abcdefghijklmnopqrstuvwxyz'; +} diff --git a/source/VigenereCipher.php b/source/VigenereCipher.php index 06a0a14..7695caa 100644 --- a/source/VigenereCipher.php +++ b/source/VigenereCipher.php @@ -1,129 +1,41 @@ - * @version 0.1 - */ +use amculin\cryptography\classic\enums\ProcessType; +use amculin\cryptography\classic\enums\VigenereMode; class VigenereCipher { - /** - * Default list of acceptable character to be encrypted using vigenere - * By default, it just an alphabetical list. - * - * @var string - */ - const TABULA_RECTA = 'abcdefghijklmnopqrstuvwxyz'; - - /** - * The plain text/message to be encrypted - * - * @var string - */ - public $plain_text; - - /** - * The key used to encrypt plain text/message - * - * @var string - */ - public $key; - - /** - * Set the plain text/message to be encrypted - * - * @param string message - * @return void - */ - public function setPlainText($message) + public static function getClassName(string $mode): string { - $this->plain_text = $message; + $path = 'amculin\cryptography\classic\\'; + + if ($mode == VigenereMode::BASIC->value) { + return $path . 'BasicVigenereCipher'; + } elseif ($mode == VigenereMode::ALPHA_NUMERIC->value) { + return $path . 'AlnumVigenereCipher'; + } } - /** - * Set key - * We loop the key then concatenate it until it has the same length with the plain text - * Example: - * Plain text: vigenerecipher (14 characters) - * Key: abcd (4 characters) - * Repeated key: abcdabcdabcdab (14 characters) - * - * @param string key - * @return void - */ - public function setKey($key) + public static function encrypt(string $data, string $key, string $mode = 'basic'): string { - $plainTextLength = strlen($this->plain_text); - $keyLength = strlen($key); - $messageLength = strlen($this->plain_text); + $className = self::getClassName($mode); - $repeatTimes = floor($messageLength / $keyLength); - $paddingKeyLength = $messageLength - ($keyLength * $repeatTimes); - - $repeatedKey = ''; + $processName = ProcessType::ENCRYPT->value; - for ($i = 0; $i < $repeatTimes; $i++) { - $repeatedKey .= $key; - } - - $paddedKey = $repeatedKey . substr($key, 0, $paddingKeyLength); - - $this->key = $paddedKey; - } + $encrypt = new $className($processName, $data, $key); - /** - * Method to encrypt the plain text - * - * @return string - */ - public function encrypt(): string - { - $messageLength = strlen($this->plain_text); - $cipher = ''; - - for ($i = 0; $i < $messageLength; $i++) { - $messageCharPosition = strpos(self::TABULA_RECTA, substr($this->plain_text, $i, 1)); - $keyCharPosition = strpos(self::TABULA_RECTA, substr($this->key, $i, 1)); - - $shift = $messageCharPosition + $keyCharPosition; - $cipherCharPosition = $shift % strlen(self::TABULA_RECTA); - $cipher .= substr(self::TABULA_RECTA, $cipherCharPosition, 1); - } - - return $cipher; + return $encrypt->getCipherText(); } - /** - * Method to get plain text - * - * @return string - */ - public function getPlainText(): string + public static function decrypt(string $data, string $key, string $mode = 'basic'): string { - return $this->plain_text; - } + $className = self::getClassName($mode); - /** - * Method to get key - * - * @return string - */ - public function getKey(): string - { - return $this->key; - } + $processName = ProcessType::DECRYPT->value; - /** - * Method to get cipher text - * - * @return string - */ - public function getCipherText(): string - { - return $this->encrypt(); + $decrypt = new $className($processName, $data, $key); + + return $decrypt->getPlainText(); } } -?> \ No newline at end of file diff --git a/source/VigenereCipherBlueprint.php b/source/VigenereCipherBlueprint.php new file mode 100644 index 0000000..c1d58cb --- /dev/null +++ b/source/VigenereCipherBlueprint.php @@ -0,0 +1,222 @@ +setProcess($process); + + if ($process == ProcessType::ENCRYPT->value) { + if (! is_null($data) && ! is_null($key)) { + $this->setPlainText($data); + $this->setKey($key); + $this->encrypt(); + } + } else { + if (! is_null($data) && ! is_null($key)) { + $this->setCipherText($data); + $this->setKey($key); + $this->decrypt(); + } + } + } + + /** + * Method to get current process + * + * @return string + */ + public function getProcess(): string + { + return $this->process; + } + + /** + * Set the current process + * + * @param string process + * @return void + */ + public function setProcess(string $process): void + { + $this->process = $process; + } + + /** + * Method to get plain text + * + * @return string + */ + public function getPlainText(): string + { + return $this->plainText; + } + + /** + * Set the plain text/message/data to be encrypted + * + * @param string message + * @return void + */ + public function setPlainText(string $plainText): void + { + $this->plainText = $plainText; + } + + /** + * Method to get key + * + * @return string + */ + public function getKey(): string + { + return $this->key; + } + + /** + * Set the key to be be used in encryption/decryption process + * + * @param string key + * @return void + */ + public function setKey(string $key): void + { + $paddedKey = $this->generateKey($key); + + $this->key = $paddedKey; + } + + /** + * Method to get cipher text + * + * @return string + */ + public function getCipherText(): string + { + return $this->cipherText; + } + + /** + * Set the cipher text result from encryption process + * + * @param string message + * @return void + */ + public function setCipherText(string $cipherText): void + { + $this->cipherText = $cipherText; + } + + /** + * Method to generate the key + * We loop the key then concatenate it until it has the same length with the plain text + * Example: + * Plain text: vigenerecipher (14 characters) + * Key: abcd (4 characters) + * Repeated key: abcdabcdabcdab (14 characters) + * + * @param string key + * @return string + */ + public function generateKey(string $key): string + { + $keyLength = strlen($key); + $messageLength = strlen($this->process == ProcessType::ENCRYPT->value ? $this->plainText : + $this->cipherText); + + $repeatTimes = floor($messageLength / $keyLength); + $paddingKeyLength = $messageLength - ($keyLength * $repeatTimes); + + $repeatedKey = ''; + + for ($i = 0; $i < $repeatTimes; $i++) { + $repeatedKey .= $key; + } + + return $repeatedKey . substr($key, 0, $paddingKeyLength); + } + + /** + * Method to encrypt the plain text + * + * @return void + */ + public function encrypt(): void + { + $messageLength = strlen($this->plainText); + $cipher = ''; + + for ($i = 0; $i < $messageLength; $i++) { + $messageCharPosition = strpos($this->tabulaRecta, substr($this->plainText, $i, 1)); + $keyCharPosition = strpos($this->tabulaRecta, substr($this->key, $i, 1)); + + $shift = $messageCharPosition + $keyCharPosition; + $cipherCharPosition = $shift % strlen($this->tabulaRecta); + $cipher .= substr($this->tabulaRecta, $cipherCharPosition, 1); + } + + $this->setCipherText($cipher); + } + + /** + * Method to decrypt the cipher text + * + * @return void + */ + public function decrypt(): void + { + $messageLength = strlen($this->cipherText); + $plain = ''; + + for ($i = 0; $i < $messageLength; $i++) { + $messageCharPosition = strpos($this->tabulaRecta, substr($this->cipherText, $i, 1)); + $keyCharPosition = strpos($this->tabulaRecta, substr($this->key, $i, 1)); + + $shift = $messageCharPosition - $keyCharPosition; + $plainCharPosition = $shift % strlen($this->tabulaRecta); + + $plain .= substr($this->tabulaRecta, $plainCharPosition, 1); + } + + $this->setPlainText($plain); + } +} diff --git a/source/enums/ProcessType.php b/source/enums/ProcessType.php new file mode 100644 index 0000000..9d742a1 --- /dev/null +++ b/source/enums/ProcessType.php @@ -0,0 +1,7 @@ +