hill_cipher
"/home/yossef/notes/personal/hashing/hill_cipher.md"
path: personal/hashing/hill_cipher.md
- **fileName**: hill_cipher
- **Created on**: 2025-03-20 20:54:10
starting for understand and learn the implementation for hill_cipher
how work : it's taking a key matrix and the encrption text by the matrix
key if it's must to be n*n for example n=3 so taking each time 3 char from
plain text convert to the ASCII Number (casting to number) and then multiplay
the matrix key in the 3 char [c,c,c] and then taking the modules for each
c
by 26 and then convert to char again using alpabatic char
have fun ;)
## starting implementation for the hill cipher algorthim ;)
## HINT STARTING FROM MAIN TO UNDERSTAND
import numpy as np
def mod_26(n: int) -> int:
"""Returns the remainder of n % 26."""
return n % 26
def convert_char(matrix: list[list[int]]) -> str:
"""to convert a number from list of encryption matrix to char"""
encryption_text = ""
# flatten the list of numPy arrays
flat_matrix = np.concatenate(matrix)
# convert each number to a letter (mod 26)
for number in flat_matrix:
x = mod_26(number)
x_char = chr(x + ord('a')) # convert to char again
encryption_text += x_char
return encryption_text
def encryption(plain_text: str, matrix) -> str:
"""
## for converthting a plain_text to ascii represent
# how it's work for example gone take the first char in word 'yosesf'
# so it's 'y' when making ord('y') = 121 (asxii table char)
# for more information about convert checkk this
# - [[../../courses/lowLevel/ascii_table.md]]
# after that we get the numberic number of char we want a represent
# from 0 to 26 so subtraictoin the char with ord('a') gone get
# the number between the range we want
"""
ascii_plain_text = [ord(char) - ord('a') for char in plain_text]
# print(ascii_plain_text) # for debuger
## convert the arrary to np array to get the shape
matrix = np.array(matrix)
x = matrix.shape
# check if the matrix is square
if x[0] == x[1]:
x = x[0]
else:
return "Error happened: not a valid dimension"
## encryption_data
encryted_matrix_number = []
# loop over the plain text in chunks of size x
for i in range(0, len(ascii_plain_text), x):
char_matrix = []
for j in range(x):
# ensure we don't go out of bounds
if i + j < len(ascii_plain_text):
## print(ascii_plain_text[i + j]) # for debuger
# append the ascii_plain_text char in array for store
char_matrix.append(ascii_plain_text[i+j])
## check if there char_matrix not fulll with the right numbers
## of ascii_plain_text append x=>23
# ensure the chunk size is exactly `x` by padding with 'x' (23 in ASCII)
while len(char_matrix) < x: char_matrix.append(23)
## now starting convert the char_matrix that store ascii_plain_text
## char to np matrix to multiplay with the matrix key
## and append value to the final result to store
np_char_matrix = np.array(char_matrix)
multiply_array = matrix @ np_char_matrix
# print(multiply_array) # for debuger
## append the encryped vallue from matrix in the encrypted matrix
encryted_matrix_number.append(multiply_array)
# print("=========================")
# print(encryted_matrix_number) # for dubger
return convert_char(encryted_matrix_number)
def main():
### testing
plain_text = "gold"
matrix = [[2,3],[3,6]]
print(encryption(plain_text, matrix))
if __name__ == "__main__":
main()
## output: cyfz
continue:./vigenere_cipher.md
before:./transposition_cipher.md