VigenèreCipher
==============

The ``VigenèreCipher`` class implements the Vigenère cipher, a polyalphabetic substitution cipher that uses a keystring, generated by repeating the keyword sufficient times till it matches the length of the plaintext, for encryption & decryption process.

.. class:: VigenèreCipher(key: str)

    Creates a new VigenèreCipher instance with the specified keyword.

    :param key: The keyword used for encryption. The keyword is repeated as necessary to match the length of the plaintext.
    :type key: str

.. attention::

   VigenereCipher is a basic symmetric cipher, which should be used ONLY for educational purposes, and NOT in production. Proceed accordingly.

Introduction
------------
The Vigenère cipher is a method of encrypting alphabetic text by using a keyword to generate a sequence of Caesar ciphers. Unlike the Caesar cipher, which shifts letters by a fixed number, the Vigenère cipher applies different shifts based on the letters of the keyword, making it a polyalphabetic cipher. This results in greater security compared to monoalphabetic substitution ciphers.

Mathematical Details
--------------------
In the Vigenère cipher:

- The keystring is generated by repeating the keyword as many times as necessary to match the length of the plaintext.

- The plaintext is encrypted by shifting each letter based on the corresponding letter of the keystring.

- Each letter of the plaintext is shifted forward by a number corresponding to its position in the alphabet (e.g., 'A' = 0, 'B' = 1, etc.) based on the keyword letter at the same position.

- The encryption formula is:
    .. math::

        C_i = (P_i + K_i) \mod 26

    where:
          - :math:`C_i` is the ciphertext letter,
          - :math:`P_i` is the plaintext letter,
          - :math:`K_i` is the key letter (converted to a number between 0 and 25).

- Decryption is done by reversing the shift:
    .. math::

        P_i = (C_i - K_i) \mod 26

Usage
-----
.. code-block:: python

    # Example usage of Playfair Cipher to encrypt and decrypt a message
    from cryptosystems import VigenereCipher
    cipher = VigenereCipher("key")
    ciphertext = cipher.encrypt("Hello World")
    print(ciphertext) # 'Rijvs Uyvjk'
    plaintext = cipher.decrypt(ciphertext)
    print(plaintext) # 'Hello World'

Methods
-------
.. function:: encrypt(plaintext: str) -> str

    Encrypts the given plaintext using the Vigenère cipher.

    :param plaintext: The plaintext message to be encrypted.
    :type plaintext: str
    :return: The encrypted ciphertext.
    :rtype: str

.. function:: decrypt(ciphertext: str) -> str

    Decrypts the given ciphertext using the Vigenère cipher.

    :param ciphertext: The ciphertext message to be decrypted.
    :type ciphertext: str
    :return: The decrypted plaintext.
    :rtype: str

Notes
-----
- **Key**: The key is repeated to match the length of the plaintext. If the key is shorter than the plaintext, it will be repeated to cover the entire message.
- **Security**: The Vigenère cipher is stronger than simple substitution ciphers like the Caesar cipher. However, it is still vulnerable to certain attacks, such as the Kasiski examination, if the key is short or reused.
- **Application**: The Vigenère cipher is widely used for educational purposes and cryptographic exercises but is not considered secure for modern applications, especially with short or predictable keywords.
