Kalitdan foydalanish Kvadrat alfavit tartibida emas, balki tasodifiy belgilar bilan to'ldirilishi mumkin. Biroq, bunday to'ldirishni eslab qolish qiyin, shuning uchun takrorlanadigan belgilar bo'lmagan tugmachani ishlatish yaxshiroq (takrorlashni ham e'tiborsiz qoldirish mumkin), qolganlarning hammasi jadvalga ortish tartibida kiritilishi kerak. Masalan, biz PASSWORD parol so'zidan foydalanamiz, undan takroriylarni olib tashlaymiz va jadvalga yozamiz, so'ngra qolgan qiymatlarni yozamiz va quyidagilarni olamiz:
1
2
3
4
5
1
P
A
S
W
O
2
R
D
B
C
E
3
F
G
H
I/J
K
4
L
M
N
Q
T
5
U
V
X
Y
Z
Shifrlash usullari Polybius kvadrati yordamida ma'lumotlarni shifrlashning bir nechta variantlari mavjud. Lotin matnini kvadrat yordamida kalit yordamida ishlatmasdan shifrlash misolida ulardan eng mashhurlarini ko'rib chiqamiz.
1-Metod. Pastki yonidagi belgidan foydalanish Ushbu usulda kvadrat ichida shifrlash uchun ular asl harfni qidiradilar va undan pastki qismini kod bilan bir xil ustunda joylashgan, yoki kerakli belgi oxirgi satrda joylashgan bo'lsa, eng yuqori qismini oladi.
Koordinata jadvali
Asl matn:
P
O
L
Y
B
I
U
S
Shifrlangan matn:
U
T
Q
D
G
O
Z
X
2-Metod. Koordinatali transformatsiya Birinchidan, manba matni belgilar koordinatalarini yozishingiz kerak:
Koordinatalar
Harf
P
O
L
Y
B
I
U
S
Vertikal koordinata:
5
4
1
4
2
4
5
3
Gorizontal koordinata:
3
3
3
5
1
2
4
4
Shundan so'ng, koordinatalar ketma-ket o'qiladi va matnga aylantiriladi:
54 ⇨ U, 14 ⇨ Q, 24 ⇨ R, 53 ⇨ P, 33 ⇨ N, 35 ⇨ X, 12 ⇨ F, 44 ⇨ T
UQRPNXFT
using System;
// yuqorida muhokama qilingan shifrlash usuli
public enum Method
{
Method1,
Method2
}
class PolybiusSquare
{
char[,] square;
string alphabet;
Method encryptMethod;
public PolybiusSquare(string alphabet = null, Method cipherMethod = Method.Method1)
{
this.alphabet = alphabet ?? "ABCDEFGHIJKLMNOPQRSTUVWXYZ ";
encryptMethod = cipherMethod;
}
// Polybius kvadratini qaytaradi
char[,] GetSquare(string key)
{
var newAlphabet = alphabet;
// kalit tarkibidagi barcha belgilarni alifbodan olib tashlang
for (int i = 0; i < key.Length; i++)
{
newAlphabet = newAlphabet.Replace(key[i].ToString(), "");
}
// parolni alfavitning boshiga va oxiriga qo'shimcha belgilarni qo'shing
// bo'sh hujayralardan qochish uchun
newAlphabet = key + newAlphabet + "0123456789!@#$%^&*)_+-=<>?,.";
// biz kvadrat tomonining o'lchamini olamiz
// kvadrat ildizni kattaroq butun songa qarab yaxlitlash orqali
var n = (int)Math.Ceiling(Math.Sqrt(alphabet.Length));
// massiv yaratish va to'ldirish
square = new char[n, n];
var index = 0;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (index < newAlphabet.Length)
{
square[i, j] = newAlphabet[index];
index++;
}
}
}
return square;
}
// ikki o'lchovli massivda belgini qidirish
bool FindSymbol(char[,] symbolsTable, char symbol, out int column, out int row)
{
var l = symbolsTable.GetUpperBound(0) + 1;
for (int i = 0; i < l; i++)
{
for (int j = 0; j < l; j++)
{
if (symbolsTable[i, j] == symbol)
{
// topilgan qiymat
row = i;
column = j;
return true;
}
}
}
// agar siz hech narsa topmagan bo'lsangiz
row = -1;
column = -1;
return false;
}
public string PolibiusEncrypt(string text, string password)
{
var outputText = "";
var square = GetSquare(password);
switch (encryptMethod)
{
case Method.Method1:
for (int i = 0; i < text.Length; i++)
{
if (FindSymbol(square, text[i], out int columnIndex, out int rowIndex))
{
var newRowIndex = rowIndex == square.GetUpperBound(1)
? 0
: rowIndex + 1;
outputText += square[newRowIndex, columnIndex].ToString();
}
}
break;
case Method.Method2:
var m = text.Length;
var coordinates = new int[m * 2];
for (int i = 0; i < m; i++)
{
if (FindSymbol(square, text[i], out int columnIndex, out int rowIndex))
{
coordinates[i] = columnIndex;
coordinates[i + m] = rowIndex;
}
}
for (int i = 0; i < m * 2; i += 2)
{
outputText += square[coordinates[i + 1], coordinates[i]];
}
break;
}
return outputText;
}
public string PolybiusDecrypt(string text, string password)
{
var outputText = "";
var square = GetSquare(password);
var m = text.Length;
switch (encryptMethod)
{
case Method.Method1:
for (int i = 0; i < m; i++)
{
if (FindSymbol(square, text[i], out int columnIndex, out int rowIndex))
{
var newRowIndex = rowIndex == 0
? square.GetUpperBound(1)
: rowIndex - 1;
outputText += square[newRowIndex, columnIndex].ToString();
}
}
break;
case Method.Method2:
var coordinates = new int[m * 2];
var j = 0;
for (int i = 0; i < m; i++)
{
if (FindSymbol(square, text[i], out int columnIndex, out int rowIndex))
{
coordinates[j] = columnIndex;
coordinates[j + 1] = rowIndex;
j += 2;
}
}
for (int i = 0; i < m; i++)
{
outputText += square[coordinates[i + m], coordinates[i]];
}
break;
}
return outputText;
}
}