چالش Hills¶
در این سوال به ما فایل task.txt داده شده است.
| task.txt | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
با اندکی جستجو تو گوگل در مورد اسم سوال، پی میبریم با Hill Cipher طرف هستیم.
آشنایی با Hill Cipher
یک رمزنگاری چند الفبایی (polyalphabetic) است که ورژن گسترش یافته رمزنگاری Affine هستش و با استفاده از جبر خطی (linear algebra) و همنهشتی (modular arithmetic) از طریق یک ماتریس عددی که به عنوان کلید رمزگذاری و رمزگشایی عمل می کند، ایجاد شده است.
نحوه رمزنگاری¶
برای رمزنگاری از یک الفبا و یک ماتریکس مربعی به سایز n استفاده میکنیم که بهش encryption matrix میگیم.
بیایید برای درک بهتر با مثالی پیش برویم میخواهیم رشته FLAG_MOTORI را با الفبا زیر
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_"
و ماتریکس M (سایز 2) رمزنگاری کنیم
-
ابتدا متن به تکه هایی به طول
nنقسیم میکنیم و در صورتیکه تکه آخر طولش کمتر ازnباشد، حروف رندوم بهش اضافه میکنیم تا طولش برابرnشود. در مثال ما اینگونه میشودFL, AG, _M, OT, OR, IZ
-
سپس هر حرف را با ایندکسش در الفبا جایگزین میکنیم.
(5,11), (0,6), (26,12), (14,19), (14,17), (8,25) -
سپس برای هر تکه، ضرب ماتریکسی زیر را انجام میدهیم که C مقادیر رمز شده ما خواهد بود. ( عدد 27 طول الفبای ما هستش)
M \cdot P \equiv C \mod 27که در مثال ما برای تکه اول اینگونه خواهد بود
\begin{bmatrix} 2 & 3 \\ 5 & 7 \end{bmatrix} \cdot \begin{bmatrix} 5 \\ 11 \end{bmatrix} \equiv \begin{bmatrix} 16 \\ 21 \end{bmatrix} \mod 27در انتها مقادیر رمز شده را با حروف نظیرشان در الفبا جایگزین میکنیم و به متن رمز شده میرسیم. که در مثال رشته
FLAG_MOTORIبه متن رمز شده زیر تبدیل میشود.QVSPHZEOZAK_
نحوه رمزگشایی¶
برای رمزگشایی به ماتریکس و الفبای مورد استفاده نیاز داریم. کافیست وارون ماتریس به پیمانه 27 را محاسبه کنیم و باقی مراحل مشابه رمزنگاری پیش برویم.
پیاده سازی در پایتون¶
import numpy as np
from sympy import Matrix
class HillCipher:
def __init__(self, alphabet, matrix):
self.n, m = matrix.shape
assert self.n==m
self.alphabet = alphabet
self.mod = len(self.alphabet)
self.mapper = dict(zip(self.alphabet, range(self.mod)))
self.mapper |= dict((v, k) for k, v in self.mapper.items())
self.M = matrix % self.mod
self.invM = np.array(Matrix(self.M).inv_mod(self.mod))
def process(self, msg, dec=False):
key = self.invM if dec else self.M
msg += 'Z'*(len(msg)%self.n)
msgI = [*map(self.mapper.get, msg)]
res = ''
for i in range(len(msgI)//self.n):
P = np.array(msgI[i*self.n:i*self.n+self.n])
C = np.dot(key,P) % self.mod
res += ''.join(map(self.mapper.get, C))
return res
def encrypt(self, plain):
return self.process(plain.upper())
def decrypt(self, cipher):
return self.process(cipher.upper(), True)
alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ_'
arr = np.array([
[2,3],
[5,7]
])
HillCipher(alphabet, arr).encrypt('FLAG_MOTORI')
کافیست با استفاده از سایت زیر رمزگشایی کنیم و فلگ را بدست بیاوردیم.
https://www.dcode.fr/hill-cipher
FLAG 
CODEBY{BTW_EXISTS_AN_INTERESTING_FILM_ABOUT_HILLS}نویسنده