Файл: Курсовая работа Написание программы для шифрования текста с помощью шифра Уитстона.docx
Добавлен: 12.12.2023
Просмотров: 322
Скачиваний: 2
ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
Поясним на примере процедуру шифрования этим шифром. Пусть имеются две таблицы со случайно расположенными в них русскими алфавитами (рис. 5). Перед шифрованием исходное сообщение разбивают на биграммы. Каждая из них шифруется отдельно. Первую букву биграммы находят в левой таблице, а вторую ‑ в правой. Затем мысленно строят прямоугольник так, чтобы буквы биграммы лежали в его противоположных вершинах. Другие две вершины этого прямоугольника дают буквы биграммы шифртекста.
Рис. 5. Две таблицы со случайно расположенными символами русского алфавита для шифра "двойной квадрат"Предположим, что шифруется биграмма исходного текста "ИЛ". Буква И находится в столбце 1 и строке 2 левой таблицы, буква Л находится в столбце 5 и строке 4 правой таблицы. Это означает, что прямоугольник образован строками 2 и 4, а также столбцами 1 левой таблицы и 5 правой таблицы. Следовательно, в биграмму шифртекста входят буква О, расположенная в столбце 5 и строке 2 правой таблицы, и буква В, расположенная в столбце 1 и строке 4 левой таблицы, т.е. получаем биграмму шифртекста 0В.
Если обе буквы биграммы сообщения лежат в одной строке, то и буквы шифртекста берут из той же строки. Первую букву биграммы шифртекста берут из левой таблицы в столбце, соответствующем второй букве биграммы сообщения; вторая буква берется из правой таблицы в столбце, со ответствующем первой букве биграммы сообщения. Поэтому би-грамма сообщения ТО превращается в биграмму шифртекста ЖБ. Аналогичным образом шифруются все биграммы сообщения:
Шифрование методом "двойного квадрата" дает весьма устойчивый к вскрытию и простой в применении шифр. Взламывание шифртекста "двойного квадрата" требует больших усилий, при этом длина сообщения должна быть не менее 30 строк.
#include
#include
//Константы
const int SizeTableX=5;
const int SizeTableY=5;
const int NumberOfSymbols=25;
const int OffsetASCIISymbolStart=0x61;
typedef std::vector<:vector>> ARRAY;
//Исключение если файл не найден
class FileNotFound{};
//Класс для шифрования методом Уитсона
class Shifr{
//Таблицы для шифрования
ARRAY tables[2];
public:
Shifr::Shifr();
void Generate_Tables(); //Генерирует 2 случайные таблицы
void Crypt(char* s1, char* s2);//Шифрование и оно же дешифрование
void WriteTablesToDisk(char* FileName);//Запись сгенерированной таблицы в файл
void ReadTablesFromDisk(char* FileName);//Чтение таблицы из файла
private:
ARRAY generate_table(ARRAY);
void find_symbol_table(int table,char s,int* x,int* y);//Находит символ s в таблице с номером table и возвращает его координаты
char get_symbol_by_index(int table,int x,int y);//Находит символ по координатам в таблице table
};
Shifr::Shifr(){
for (int j=0;j<2;j++){
tables[j].resize(SizeTableX);
tables[j].resize(SizeTableX);
for (int i=0;i
tables[j][i].assign(SizeTableY,0);
tables[j][i].assign(SizeTableY,0);
}
}
}
void Shifr::Generate_Tables(){
tables[0]=generate_table(tables[0]);
tables[1]=generate_table(tables[1]);
}
ARRAY Shifr::generate_table(ARRAY t){
bool empty;
int x;
int y;
//Переборка 2 таблиц
for (int i=0;i
empty=true;
//Генерируем до тех пор, пока не попадем в еще пустое место
while (empty){
//Генерируем случайные координаты в таблице
x=rand()%SizeTableX;
y=rand()%SizeTableY;
if (t[x][y]==0){
//Пишем значение в пустой ячейке
t[x][y]=i+OffsetASCIISymbolStart;
empty=false;
}
}
}
return t;
}
void Shifr::Crypt(char* s1, char* s2){
int x,y,x1,y1;
//Ищем индексы в таблице
find_symbol_table(0,*s1,&x,&y);
find_symbol_table(1,*s2,&x1,&y1);
//На противоположных диfганалях ищем символы
*s1=get_symbol_by_index(0,x,y1);
*s2=get_symbol_by_index(1,x1,y);
}
void Shifr::find_symbol_table(int table,char s,int* x,int* y){
int i,j;
bool found=false;
for (i=0;i
for (j=0;j
if (tables[table][i][j]==s){
*x=i;
*y=j;
found=true;
}
}
}
char Shifr::get_symbol_by_index(int table,int x,int y){
return tables[table][x][y];
}
void Shifr::WriteTablesToDisk(char* FileName){
char massiv[2*SizeTableX*SizeTableY];
for (int k=0;k<2;k++)
for (int i=0;i
for (int j=0;j
massiv[k*(SizeTableX*SizeTableY)+i*SizeTableY+j]=tables[k][i][j];
FILE *file;
file = fopen(FileName,"w");
if (file==0)
throw FileNotFound();
fputs(massiv,file);
fclose(file);
}
void Shifr::ReadTablesFromDisk(char* FileName){
FILE *file;
char massiv[2*SizeTableX*SizeTableY];
file = fopen(FileName,"r");
if (file==0)
throw FileNotFound();
fgets(massiv,2*SizeTableX*SizeTableY,file);
for (int k=0;k<2;k++)
for (int i=0;i
for (int j=0;j
tables[k][i][j]=massiv[k*(SizeTableX*SizeTableY)+i*SizeTableY+j];
fclose(file);
}
int _tmain(int argc, _TCHAR* argv[])
{
Shifr t;
t.Generate_Tables();
t.WriteTablesToDisk("c:\\images\\1.txt");
char a='a';
char b='b';
//шифруем два символа
t.Crypt(&a,&b);
t.ReadTablesFromDisk("c:\\images\\1.txt");
t.Crypt(&a,&b);
return 0;
}
Python
import random
class Key:
"""
Класс для генерации и обращение с ключем.
Сам ключ представлен как две строки с перемешанным алфавитом
"""
ALPHABET_DEFAULT = "абвгдеёжзийклмнопрстуфхцчшщъыьэюя .!,-1234567890?"
ROWS_DEFAULT = 7
COLS_DEFAULT = 7
def __init__(self, alphabet=ALPHABET_DEFAULT, rows=ROWS_DEFAULT, cols=COLS_DEFAULT):
"""
Принимает на вход символы алфавита и размер таблицы,
либо использует алфавит по умолчанию
"""
self.rows = rows
self.cols = cols
self.table = [0] * 2
for i in range(2):
self.table[i] = list(alphabet)
random.shuffle(self.table[i])
self.table[i] = ''.join(self.table[i])
def __getitem__(self, key):
"""
Если передали кортеж из двух элементов,
то это поиск символа в левой (0) или правой (1) таблице
Если передали кортеж из трех элементов,
то это получение символа в таблице по координатам
"""
if len(key) == 2:
# table and char
i = self.table[key[0]].index(key[1])
return i // self.cols, i % self.cols
else:
return self.table[key[0]][key[1] * self.cols + key[2]]
def __str__(self):
"""
Для отображения ключа в читабельном виде
"""
s = ""
for i in range(self.rows):
s += self.table[0][i * self.cols:(i + 1) * self.cols] + "\t\t" + self.table[1][
i * self.cols:(i + 1) * self.cols] + "\n"
return s
def bgrams(l):
"""
Генератор для разбиения строки на биграммы
"""
for i in range(0, len(l), 2):
yield l[i:i + 2]
def crypt(s, key):
"""
Функция шифровки/дешифровки.
Пробегаемся по всем биграммам и для каждой биграммы
находим координаты первого символа в первой таблице,
второго во второй таблице.
Далее получаем символы из противоположных вершин прямоугольника
и добавляем к строке с результатом
"""
assert len(s) % 2 == 0, "String must divedes by 2"
r = ""
for bg in bgrams(s):
(x1, y1), (x2, y2) = key[(0, bg[0])], key[(1, bg[1])]
r += key[(0, x2, y1)] + key[(1, x1, y2)]
return r
# Проверка работоспособности
key = Key()
print(key)
s = crypt("привет человек. как у тебя дела?", key)
print(s)
s = crypt(s, key)
print(s)
PHP
function dsCrypt($input,$decrypt=false) {
$o = $s1 = $s2 = array(); // Arrays for: Output, Square1, Square2
// формируем базовый массив с набором символов
$basea = array('?','(','@',';','$','#',"]","&",'*'); // base symbol set
$basea = array_merge($basea, range('a','z'), range('A','Z'), range(0,9) );
$basea = array_merge($basea, array('!',')','_','+','|','%','/','[','.',' ') );
$dimension=9; // of squares
for($i=0;$i<$dimension;$i++) { // create Squares
for($j=0;$j<$dimension;$j++) {
$s1[$i][$j] = $basea[$i*$dimension+$j];
$s2[$i][$j] = str_rot13($basea[($dimension*$dimension-1) - ($i*$dimension+$j)]);
}
}
unset($basea);
$m = floor(strlen($input)/2)*2; // !strlen%2
$symbl = $m==strlen($input) ? '':$input[strlen($input)-1]; // last symbol (unpaired)
$al = array();
// crypt/uncrypt pairs of symbols
for ($ii=0; $ii<$m; $ii+=2) {
$symb1 = $symbn1 = strval($input[$ii]);
$symb2 = $symbn2 = strval($input[$ii+1]);
$a1 = $a2 = array();
for($i=0;$i<$dimension;$i++) { // search symbols in Squares
for($j=0;$j<$dimension;$j++) {
if ($decrypt) {
if ($symb1===strval($s2[$i][$j]) ) $a1=array($i,$j);
if ($symb2===strval($s1[$i][$j]) ) $a2=array($i,$j);
if (!empty($symbl) && $symbl===strval($s2[$i][$j])) $al=array($i,$j);
}
else {
if ($symb1===strval($s1[$i][$j]) ) $a1=array($i,$j);
if ($symb2===strval($s2[$i][$j]) ) $a2=array($i,$j);
if (!empty($symbl) && $symbl===strval($s1[$i][$j])) $al=array($i,$j);
}
}
}
if (sizeof($a1) && sizeof($a2)) {
$symbn1 = $decrypt ? $s1[$a1[0]][$a2[1]] : $s2[$a1[0]][$a2[1]];
$symbn2 = $decrypt ? $s2[$a2[0]][$a1[1]] : $s1[$a2[0]][$a1[1]];
}
$o[] = $symbn1.$symbn2;
}
if (!empty($symbl) && sizeof($al))
$o[] = $decrypt ? $s1[$al[1]][$al[0]] : $s2[$al[1]][$al[0]];
return implode('',$o);
}
С++
NUOprnd = 64
Noprtr =181
Noprnd =154
HPVoc = NUOprtr + NUOprnd =174
HPLen = Noprtr + Noprnd =335
HPVol = HPLen log2 HPVoc =335*7,443= 2493,4
HDiff = (NUOprtr/2) × (NOprnd / NUOprnd) =55*2,4=132
HEff = HDiff × HPVol=132*2493,4=329 128
Python
NUOprnd =45
Noprtr = 77
Noprnd = 69
HPVoc = NUOprtr + NUOprnd = 104
HPLen = Noprtr + Noprnd =146
HPVol = HPLen log2 HPVoc =146*6,7=978,2
HDiff = (NUOprtr/2) × (NOprnd / NUOprnd) =29,5*1,64=48,38
HEff = HDiff × HPVol=48,38*978,2=47 325,3
PHP
NUOprnd =71
Noprtr =102
Noprnd =84
HPVoc = NUOprtr + NUOprnd = 147
HPLen = Noprtr + Noprnd =186
HPVol = HPLen log2 HPVoc =186*7,2=1339,2
HDiff = (NUOprtr/2) × (NOprnd / NUOprnd) =38*1,18=44,84
HEff = HDiff × HPVol=44,84*1339,2=60 049,7
Выполнив задание по написанию программ для шифрования текста с помощью шифра Уитстона на трех, рассмотренных языках (C++,Python,PHP) и стравних их по метрике Холстеда, можно прийти к выводу о том, что наиболее подходящим языком для этого является Python.
| Ж | Щ | Н | Ю | Р | | И | Ч | Г | Я | Т |
| И | Т | Ь | Ц | Б | | , | Ж | Ь | М | О |
| Я | М | Е | . | С | | З | Ю | Р | В | Щ |
| В | Ы | П | Ч | | | Ц | : | П | Е | Л |
| : | Д | У | О | К | | Ъ | А | Н | . | Х |
| З | Э | Ф | Г | Ш | | Э | К | С | Ш | Д |
| Х | А | , | Л | Ъ | | Б | Ф | У | Ы | |
Если обе буквы биграммы сообщения лежат в одной строке, то и буквы шифртекста берут из той же строки. Первую букву биграммы шифртекста берут из левой таблицы в столбце, соответствующем второй букве биграммы сообщения; вторая буква берется из правой таблицы в столбце, со ответствующем первой букве биграммы сообщения. Поэтому би-грамма сообщения ТО превращается в биграмму шифртекста ЖБ. Аналогичным образом шифруются все биграммы сообщения:
| Сообщение | П | Р | | И | Л | | Е | Т | | А | Ю | | | Ш | | Е | С | | Т | О | | Г | О |
| Шифртекст | П | Е | | О | В | | Щ | Н | | Ф | М | | Е | Ш | | Р | Ф | | Б | Ж | | Д | Ц |
Коды выполнения программы
C++#include "stdafx.h"#include#include
#include
//Константы
const int SizeTableX=5;
const int SizeTableY=5;
const int NumberOfSymbols=25;
const int OffsetASCIISymbolStart=0x61;
typedef std::vector<:vector>> ARRAY;
//Исключение если файл не найден
class FileNotFound{};
//Класс для шифрования методом Уитсона
class Shifr{
//Таблицы для шифрования
ARRAY tables[2];
public:
Shifr::Shifr();
void Generate_Tables(); //Генерирует 2 случайные таблицы
void Crypt(char* s1, char* s2);//Шифрование и оно же дешифрование
void WriteTablesToDisk(char* FileName);//Запись сгенерированной таблицы в файл
void ReadTablesFromDisk(char* FileName);//Чтение таблицы из файла
private:
ARRAY generate_table(ARRAY);
void find_symbol_table(int table,char s,int* x,int* y);//Находит символ s в таблице с номером table и возвращает его координаты
char get_symbol_by_index(int table,int x,int y);//Находит символ по координатам в таблице table
};
Shifr::Shifr(){
for (int j=0;j<2;j++){
tables[j].resize(SizeTableX);
tables[j].resize(SizeTableX);
for (int i=0;i
tables[j][i].assign(SizeTableY,0);
tables[j][i].assign(SizeTableY,0);
}
}
}
void Shifr::Generate_Tables(){
tables[0]=generate_table(tables[0]);
tables[1]=generate_table(tables[1]);
}
ARRAY Shifr::generate_table(ARRAY t){
bool empty;
int x;
int y;
//Переборка 2 таблиц
for (int i=0;i
empty=true;
//Генерируем до тех пор, пока не попадем в еще пустое место
while (empty){
//Генерируем случайные координаты в таблице
x=rand()%SizeTableX;
y=rand()%SizeTableY;
if (t[x][y]==0){
//Пишем значение в пустой ячейке
t[x][y]=i+OffsetASCIISymbolStart;
empty=false;
}
}
}
return t;
}
void Shifr::Crypt(char* s1, char* s2){
int x,y,x1,y1;
//Ищем индексы в таблице
find_symbol_table(0,*s1,&x,&y);
find_symbol_table(1,*s2,&x1,&y1);
//На противоположных диfганалях ищем символы
*s1=get_symbol_by_index(0,x,y1);
*s2=get_symbol_by_index(1,x1,y);
}
void Shifr::find_symbol_table(int table,char s,int* x,int* y){
int i,j;
bool found=false;
for (i=0;i
for (j=0;j
if (tables[table][i][j]==s){
*x=i;
*y=j;
found=true;
}
}
}
char Shifr::get_symbol_by_index(int table,int x,int y){
return tables[table][x][y];
}
void Shifr::WriteTablesToDisk(char* FileName){
char massiv[2*SizeTableX*SizeTableY];
for (int k=0;k<2;k++)
for (int i=0;i
for (int j=0;j
massiv[k*(SizeTableX*SizeTableY)+i*SizeTableY+j]=tables[k][i][j];
FILE *file;
file = fopen(FileName,"w");
if (file==0)
throw FileNotFound();
fputs(massiv,file);
fclose(file);
}
void Shifr::ReadTablesFromDisk(char* FileName){
FILE *file;
char massiv[2*SizeTableX*SizeTableY];
file = fopen(FileName,"r");
if (file==0)
throw FileNotFound();
fgets(massiv,2*SizeTableX*SizeTableY,file);
for (int k=0;k<2;k++)
for (int i=0;i
for (int j=0;j
tables[k][i][j]=massiv[k*(SizeTableX*SizeTableY)+i*SizeTableY+j];
fclose(file);
}
int _tmain(int argc, _TCHAR* argv[])
{
Shifr t;
t.Generate_Tables();
t.WriteTablesToDisk("c:\\images\\1.txt");
char a='a';
char b='b';
//шифруем два символа
t.Crypt(&a,&b);
t.ReadTablesFromDisk("c:\\images\\1.txt");
t.Crypt(&a,&b);
return 0;
}
Python
import random
class Key:
"""
Класс для генерации и обращение с ключем.
Сам ключ представлен как две строки с перемешанным алфавитом
"""
ALPHABET_DEFAULT = "абвгдеёжзийклмнопрстуфхцчшщъыьэюя .!,-1234567890?"
ROWS_DEFAULT = 7
COLS_DEFAULT = 7
def __init__(self, alphabet=ALPHABET_DEFAULT, rows=ROWS_DEFAULT, cols=COLS_DEFAULT):
"""
Принимает на вход символы алфавита и размер таблицы,
либо использует алфавит по умолчанию
"""
self.rows = rows
self.cols = cols
self.table = [0] * 2
for i in range(2):
self.table[i] = list(alphabet)
random.shuffle(self.table[i])
self.table[i] = ''.join(self.table[i])
def __getitem__(self, key):
"""
Если передали кортеж из двух элементов,
то это поиск символа в левой (0) или правой (1) таблице
Если передали кортеж из трех элементов,
то это получение символа в таблице по координатам
"""
if len(key) == 2:
# table and char
i = self.table[key[0]].index(key[1])
return i // self.cols, i % self.cols
else:
return self.table[key[0]][key[1] * self.cols + key[2]]
def __str__(self):
"""
Для отображения ключа в читабельном виде
"""
s = ""
for i in range(self.rows):
s += self.table[0][i * self.cols:(i + 1) * self.cols] + "\t\t" + self.table[1][
i * self.cols:(i + 1) * self.cols] + "\n"
return s
def bgrams(l):
"""
Генератор для разбиения строки на биграммы
"""
for i in range(0, len(l), 2):
yield l[i:i + 2]
def crypt(s, key):
"""
Функция шифровки/дешифровки.
Пробегаемся по всем биграммам и для каждой биграммы
находим координаты первого символа в первой таблице,
второго во второй таблице.
Далее получаем символы из противоположных вершин прямоугольника
и добавляем к строке с результатом
"""
assert len(s) % 2 == 0, "String must divedes by 2"
r = ""
for bg in bgrams(s):
(x1, y1), (x2, y2) = key[(0, bg[0])], key[(1, bg[1])]
r += key[(0, x2, y1)] + key[(1, x1, y2)]
return r
# Проверка работоспособности
key = Key()
print(key)
s = crypt("привет человек. как у тебя дела?", key)
print(s)
s = crypt(s, key)
print(s)
PHP
function dsCrypt($input,$decrypt=false) {
$o = $s1 = $s2 = array(); // Arrays for: Output, Square1, Square2
// формируем базовый массив с набором символов
$basea = array('?','(','@',';','$','#',"]","&",'*'); // base symbol set
$basea = array_merge($basea, range('a','z'), range('A','Z'), range(0,9) );
$basea = array_merge($basea, array('!',')','_','+','|','%','/','[','.',' ') );
$dimension=9; // of squares
for($i=0;$i<$dimension;$i++) { // create Squares
for($j=0;$j<$dimension;$j++) {
$s1[$i][$j] = $basea[$i*$dimension+$j];
$s2[$i][$j] = str_rot13($basea[($dimension*$dimension-1) - ($i*$dimension+$j)]);
}
}
unset($basea);
$m = floor(strlen($input)/2)*2; // !strlen%2
$symbl = $m==strlen($input) ? '':$input[strlen($input)-1]; // last symbol (unpaired)
$al = array();
// crypt/uncrypt pairs of symbols
for ($ii=0; $ii<$m; $ii+=2) {
$symb1 = $symbn1 = strval($input[$ii]);
$symb2 = $symbn2 = strval($input[$ii+1]);
$a1 = $a2 = array();
for($i=0;$i<$dimension;$i++) { // search symbols in Squares
for($j=0;$j<$dimension;$j++) {
if ($decrypt) {
if ($symb1===strval($s2[$i][$j]) ) $a1=array($i,$j);
if ($symb2===strval($s1[$i][$j]) ) $a2=array($i,$j);
if (!empty($symbl) && $symbl===strval($s2[$i][$j])) $al=array($i,$j);
}
else {
if ($symb1===strval($s1[$i][$j]) ) $a1=array($i,$j);
if ($symb2===strval($s2[$i][$j]) ) $a2=array($i,$j);
if (!empty($symbl) && $symbl===strval($s1[$i][$j])) $al=array($i,$j);
}
}
}
if (sizeof($a1) && sizeof($a2)) {
$symbn1 = $decrypt ? $s1[$a1[0]][$a2[1]] : $s2[$a1[0]][$a2[1]];
$symbn2 = $decrypt ? $s2[$a2[0]][$a1[1]] : $s1[$a2[0]][$a1[1]];
}
$o[] = $symbn1.$symbn2;
}
if (!empty($symbl) && sizeof($al))
$o[] = $decrypt ? $s1[$al[1]][$al[0]] : $s2[$al[1]][$al[0]];
return implode('',$o);
}
Сравнение кода программ по метрике Холстеда
С++
-
NUOprtr =110
NUOprnd = 64
Noprtr =181
Noprnd =154
HPVoc = NUOprtr + NUOprnd =174
HPLen = Noprtr + Noprnd =335
HPVol = HPLen log2 HPVoc =335*7,443= 2493,4
HDiff = (NUOprtr/2) × (NOprnd / NUOprnd) =55*2,4=132
HEff = HDiff × HPVol=132*2493,4=329 128
Python
-
NUOprtr =59
NUOprnd =45
Noprtr = 77
Noprnd = 69
HPVoc = NUOprtr + NUOprnd = 104
HPLen = Noprtr + Noprnd =146
HPVol = HPLen log2 HPVoc =146*6,7=978,2
HDiff = (NUOprtr/2) × (NOprnd / NUOprnd) =29,5*1,64=48,38
HEff = HDiff × HPVol=48,38*978,2=47 325,3
PHP
-
NUOprtr =76
NUOprnd =71
Noprtr =102
Noprnd =84
HPVoc = NUOprtr + NUOprnd = 147
HPLen = Noprtr + Noprnd =186
HPVol = HPLen log2 HPVoc =186*7,2=1339,2
HDiff = (NUOprtr/2) × (NOprnd / NUOprnd) =38*1,18=44,84
HEff = HDiff × HPVol=44,84*1339,2=60 049,7
Вывод
Выполнив задание по написанию программ для шифрования текста с помощью шифра Уитстона на трех, рассмотренных языках (C++,Python,PHP) и стравних их по метрике Холстеда, можно прийти к выводу о том, что наиболее подходящим языком для этого является Python.
Библиографический список
-
https://vunivere.ru/work24054/page2 -
https://ru.wikipedia.org/wiki/%D0%A8%D0%B8%D1%84%D1%80_%D0%A3%D0%B8%D1%82%D1%81%D1%82%D0%BE%D0%BD%D0%B0 -
https://techrocks.ru/2019/01/21/about-python-briefly/ -
https://web-creator.ru/articles/php -
https://spectrum.ieee.org/top-programming-languages/ -
https://ru.wikipedia.org/wiki/Python -
https://ru.wikipedia.org/wiki/PHP