Solution de .danidou pour À l'aise

intro crypto

1 janvier 2025

Table des matières

Je n’ai pas simplement voulu solutionner le défi À l’aise de Hackropole, j’ai voulu en profiter pour créer un script qui permettrait de chiffrer ou de déchiffrer n’importe quel texte en utilisant cette méthode.

Solution

La solution que j’ai envisagée est un petit module Python, qui prend en compte les espaces et caractères de ponctuation à l’entrée, et chiffre ou déchiffre en maintenant les espaces et caractères de ponctuation à la sortie. J’en ai profité pour ajouter une aide conviviale pour donner des exemples d’utilisation.

J’ai testé à la fois le chiffrement et le déchiffrement du message fourni dans le défi, ça fonctionne bien dans les deux cas.

Code

"""
This module encrypts or (by default) decrypts a piped text using the Vigenère cypher.
"""

import argparse
import re
import sys

"""
This function generates the full key for the message.
"""
def generate_key(msg, key):
    key = list(key)
    if len(msg) == len(key):
        return key
    else:
        for i in range(len(msg) - len(key)):
            key.append(key[i % len(key)])
    return "".join(key)

"""
This function encrypts the given message using the given key.
"""
def encrypt_vigenere(msg, key):
    encrypted_text = []
    nonalpha = {}
    key = generate_key(msg, key)
    for i in range(len(msg)):
        char = msg[i]
        if char.islower():
            encrypted_char = chr((ord(char.upper()) + ord(key[i - len(nonalpha)]) - 2 * ord('A')) % 26 + ord('A')).lower()
        elif char.isupper():
            encrypted_char = chr((ord(char) + ord(key[i - len(nonalpha)]) - 2 * ord('A')) % 26 + ord('A'))
        else:
            encrypted_char = char
            nonalpha[i] = char
        encrypted_text.append(encrypted_char)
    return "".join(encrypted_text)

"""
This function decrypts the given message using the given key.
"""
def decrypt_vigenere(msg, key):
    decrypted_text = []
    nonalpha = {}
    key = generate_key(msg, key)
    for i in range(len(msg)):
        char = msg[i]
        if char.islower():
            decrypted_char = chr((ord(char.upper()) - ord(key[i - len(nonalpha)]) + 26) % 26 + ord('A')).lower()
        elif char.isupper():
            decrypted_char = chr((ord(char) - ord(key[i - len(nonalpha)]) + 26) % 26 + ord('A'))
        else:
            decrypted_char = char
            nonalpha[i] = char
        decrypted_text.append(decrypted_char)
    return "".join(decrypted_text)


"""
Usage output.
"""
def msg(name=None):
    return '''echo 'a message' | python3 vigenere.py -k K [-e]
       cat file.txt | python3 vigenere.py -k K [-e]
       python3 vigenere.py -h
    '''

"""
The main function of this module.
"""
def main():
    parser = argparse.ArgumentParser(description='You can use this tool to encrypt or decrypt a piped text using the Vigenère cypher.', usage=msg())
    parser.add_argument('-k', help='Cypher key', required=True)
    parser.add_argument('-e', help='Encryption function', action='store_true')

    args = parser.parse_args()

    phrase = ''
    for line in sys.stdin:
        phrase = phrase + line

    if args.e:
        print(encrypt_vigenere(phrase, args.k))
    else:
        print(decrypt_vigenere(phrase, args.k))

if __name__ == "__main__":
    main()