playfair_ceaser


"/home/yossef/notes/courses/hashing/playfair_ceaser.md"

path: courses/hashing/playfair_ceaser.md

- **fileName**: playfair_ceaser
- **Created on**: 2025-03-07 20:37:53

=> steps

## now creating a playfair encryption
from typing import Any
def map_hash(key: str, char_eng: str = "abcdefghijklmnopqrstuvwxyz") -> list:
    """generates a 5x5 playfair cipher matrix from a given key."""
    map_dict = []
    ## adding key work ch in list
    for c in key:
        if c == " " or c in map_dict: 
            continue
        if c == "j":
            if "i" not in map_dict: 
                map_dict.append("i")
        else:
            map_dict.append(c)
    ## adding char_eng abc in list
    for c in char_eng:
        if c == " " or c in map_dict: 
            continue
        if c == "j":
            if "i" not in map_dict: 
                map_dict.append("i")
        else:
            map_dict.append(c)

    # Convert the flat list into a 5x5 matrix
    # taking five elements every time in list and adding to the new matrix
    matrix = [map_dict[i:i+5] for i in range(0, 25, 5)]
    return matrix


def encryption_play_fair(matrix: list, fch: str, sch: str) -> tuple[str, str]:
    """encrypts a pair of characters using the playfair """
    # if both characters are the same, replace the second with 'x'
    if fch == sch:
        sch = 'x'
    position_fch = [] # store the position for fch
    position_sch = [] # store the position for sch

    # locate the characters in the matrix
    for i in range(5):
        for j in range(5):
            if matrix[i][j] == fch: # find the first fch position
                position_fch = [i, j]
            if matrix[i][j] == sch: # find the second sch position
                position_sch = [i, j]

    hashed_ch1 = "" # store the encyrpted value for fsh
    hashed_ch2 = "" # store the encrypted value for sch

    ## letters are in the same row
    # if in the same row increase x axis by 1
    # addind % 5 if the number greater then 5 then return to first and start over 
    if position_fch[0] == position_sch[0]:
        hashed_ch1 = matrix[position_fch[0]][(position_fch[1] + 1) % 5]
        hashed_ch2 = matrix[position_sch[0]][(position_sch[1] + 1) % 5]

    ## letters are in the same column
    # if in the some position increase the y axis by 1
    # addind % 5 if the number greater then 5 then return to first and start over 
    elif position_fch[1] == position_sch[1]:
        hashed_ch1 = matrix[(position_fch[0] + 1) % 5][position_fch[1]]
        hashed_ch2 = matrix[(position_sch[0] + 1) % 5][position_sch[1]]

    ## letters are at different rows and columns (rectangle swap)
    else:
        """[
                [0,0],
                [4,4]
                h1 => [0,4]
                h2 => [4,0]
        ]"""
        hashed_ch1 = matrix[position_fch[0]][position_sch[1]]
        hashed_ch2 = matrix[position_sch[0]][position_fch[1]]

    return hashed_ch1, hashed_ch2


def main():
    key = "yossef"
    plain_text = "sabry"
    matrix = map_hash(key)

    print("playfair cipher matrix: ")
    for row in matrix:
        print(row)
    print('\n')    

    #  encrypt a pair of two characters
    encrypted_list = []
    for i in range(0 ,len(plain_text), 2):
        fch = plain_text[i]
        if i == len(plain_text) - 1: sch = "x"
        else: sch = plain_text[i+1]
        encrypted_pair = encryption_play_fair(matrix, fch, sch)
        encrypted_list.append(encrypted_pair[0])
        encrypted_list.append(encrypted_pair[1])
        print(f"Encrypted '{fch}{sch}' -> '{encrypted_pair[0]}{encrypted_pair[1]}' \n")
   
    print("the main key: ", key)
    print("plain text: ", plain_text)
    print("encrypted word: ", ''.join(encrypted_list))


if __name__ == "__main__":
    main()


Tip

range(start, end, steps) how range work

continue:./caeser_cipher.md