В данной заметке я планирую кратко рассказать об аффинном шифре, а также о реализации программы шифрования и дешифрования на C++ Builder.
В качестве примера буду использовать латинский алфавит. Так что если вы нуждаетесь в шифровании кириллических символов, то, прежде всего, учтите, что кириллица содержит большее количество букв.
Начну, пожалуй, с того, что аффинная криптосистема определяется при помощи двух целых чисел: a и b. При этом 0 ≤ а, b ≤ 25. Верхняя граница обусловлена количеством букв в латинском алфавите (для тех, кто не в курсе – их 26). Кроме того, эти числа взаимно просты. В таком шифре заменой для буквы а будет jа + b (mod 26). При этом j представляет собой вес места расположения буквы в алфавите. Здесь нам предстоит работать с числовыми кодами букв. Отмечу, что все арифметические действия выполняются по модулю числа 26 (это количество букв в латинском алфавите). К примеру, если а = 3 и b = 5, то получаем следующее соответствие для числовых кодов букв (см. таблицу ниже).
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
5 | 8 | 11 | 14 | 17 | 20 | 23 | 0 | 3 | 6 | 9 | 12 | 15 |
13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
18 | 21 | 24 | 1 | 4 | 7 | 10 | 13 | 16 | 19 | 22 | 25 | 2 |
Когда декодируем числа в буквы, получим следующее соответствие для букв (см. таблицу ниже).
a | b | c | d | e | f | g | h | i | j | k | l | m |
f | i | l | o | r | u | x | a | d | g | j | m | p |
n | o | p | q | r | s | t | u | v | w | x | y | z |
s | v | y | b | e | h | k | n | q | t | w | z | c |
Таким образом, исходное сообщение noteverysteambathissauna зашифруется в svkrqrezhkrfpifkadhhfnsf.
Условие взаимной простоты пары чисел а и b необходимо для обеспечения биективности отображения f(а) = jа + b. Если мы рассмотрим отображение 10a+1, где данное условие не выполняется, то буквы a и n обе отображаются в b и, следовательно, b может быть расшифрована и как a, и как n. С другой стороны, нет числового кода отображаемого в o, и, следовательно, o не требуется в алфавите подстановок. Легко найти все пары букв, отображаемых в одну и ту же букву так же, как и все буквы, не требующиеся в алфавите подстановок.
В общем, с теорией покончено. Перейдем к практике.
Первым делом создаем массив, содержащий латинский алфавит (путем посимвольного разбиения строки):
sh="abcdefghijklmnopqrstuvwxyz";
for(int i=1;i<27;i++)
alf[i]=sh.SubString(i,1);
где alf []
– латинский алфавит.
Далее переходим к созданию массива соответствующих кодирующих букв:
for(int j=1;j<27;j++)
{
if((b+a*(j-1))>25)
{int f=(b+a*(j-1))/26;
shifr[j]=alf[b+1+a*(j-1)-26*f];
}
else shifr[j]=alf[b+1+a*(j-1)];
}
где shifr []
– шифрующий алфавит.
Сам же процесс кодировки полученной строки может быть выполнен так:
for(int i;i
где len
– длина исходной строки;
ich []
– исходный массив символов;
kod []
– результирующий массив символов.
Вот и все, собственно говоря. Пост о дешифровке создам в другой раз (если нужно, ессно).
UPD
Пост о дешифровке аффинного шрифта находится здесь.
ошибка:”request for member “SubString” in something not structure or union”
как это решить (код адаптировал по C#)?
Вы бы код привели. Так сложно что-то сказать, кроме как: компилятор уверяет, что данные не структура )
Собсно берётся всё, что выше… (код дорабатывается, так что это черновик)
Попробуйте расширить тип данных для строковых переменных, т.е. в строке 6 вместо char сделать String. Вот так:
Ещё раз уточняю: я делаю на C#. Там емнип String’а нет, как альтернатива ему выступает char.
Ммм…. вы уверены?
Только что погуглила – первый результат http://
msdn.microsoft.com/ru-ru/library/362314fe.aspx. Все же попробуйте расширить строковый тип данных.В том и дело, что попробовал в точности, как вы предложили, но string даже не идентифицируется как тип(
может какую библиотеку нужно подключать?) И string, кстати, с большой буквы пишется.
С большой) И 3 основных библиотеки подключены.
Тогда с маленькой попробуйте. Должен ведь работать)
Оу, нашла еще один момент – где определение длины строки? Например, такое:
или (еще вариант) вместо разбиения строки при помощи SubString использовать прямое обращение к элементу массива, например
&&
в строках 11 и 19 соответственно.
a=3; b=4;
len=str.Length; // определение длины строки
Console.Write(len);
for (i = 1; i < 27; i++)
{
alf[i] = sh[i];//sh.SubString(i,1); //разделение строки на символы
for (j = 1; j 25)
{
int f = (b + a * (j – 1)) / 26;
shifr[i] = alf[b + 1 + a * (j – 1) – 26 * f];
}
else shifr[i] = alf[Math.Abs(b + 1 + a * (j – 1))];
в последней строке индекс выходит за границы массива, что бы это могло значить?
ps
С предыдущими вопросами разобрался – стандарт C# (в CodeBlox) действительно не поддерживает строки, однако в MS Visual Studio 2010 есть. Сейчас в этой среде и работаю.
> в последней строке индекс выходит за границы массива, что бы это могло значить?
Дык, как объявили массив, такого он и размера – ноль и в Африке ноль. Либо пропишите определенное количество символов изначально (например так:
), либо объявите динамический массив – я о них писала где-то здесь
Он был объявлен. Динамический массив не помогает, в случае, когда строка закомментирована индекс выходит за границы в строке shifr[i] = alf[b + 1 + a * (j – 1) – 26 * f];.
int a, b, i, j, len; //a,b- ключи, i,j- счетчики, len- длина исходной строки
char [] sh = {‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’, ‘g’, ‘h’, ‘i’, ‘j’,’k’,’l’,’m’,’n’,’o’,’p’,’q’,’r’,’s’,’t’,’u’,’v’,’w’,’x’,’y’,’z’};
char [] str = {‘a’,’b’,’c’};
char [] alf = {‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘};
//char [] shifr = {‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘};
char [] shifr = new char[26];
char [] ich = {‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘};
char [] kod = {‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘};
/* sh- строка для создания алфавита, str-строка которая шифруется, alf-алфавит, shifr-шифр.алфавит, ich – исх. символы, kod – кодир.символы
*/
a=3; b=4;
len=str.Length; // определение длины строки
Console.Write(len);
for (i = 1; i < 27; i++)
{
alf[i] = sh[i];//sh.SubString(i,1); //разделение строки на символы
for (j = 1; j 25)
{
int f = (b + a * (j – 1)) / 26;
shifr[i] = alf[b + 1 + a * (j – 1) – 26 * f];
}
else shifr[i] = alf[b + 1 + a * (j – 1)];
//Console.Write(alf);
}
}
for(i=1; i<len+1; i++) //кодировка строки
ich=str;//.SubString(i,1);
for(i=1; i<len+1; i++)
{
for(j=1; j<27; j++)
{
if(ich[i]==alf[j])
{
kod[i]=shifr[j];
j++;
Console.Write(kod);//при a=3, b=4 abc=EHK
Он был объявлен. Динамический массив не помогает, в случае, когда строка закомментирована индекс выходит за границы в строке shifr[i] = alf[b + 1 + a * (j – 1) – 26 * f];.
В приведенном вами коде я динамического массива не вижу. Мало того, я не понимаю зачем вы используете такого рода конструкцию:
char [] alf = {‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘};
и да – вам нужно 26 элементов, а в конструкции их меньше. Посчитайте. Отсюда и переполнение в первом же цикле.
ОГРОМНОЕ Вам человеческое спасибо, что отзывались!
Привожу полный рабочий код, может кому пригодится;)
ps
Постараюсь больше не тревожить... Разве что другие шифры разбирать будете;)
Пожалуйста. Заходите еще )))
В принципе, я планирую разобрать шифр Плейфера и Вижинера =)
Если вы таки провели разбор шифра Виженера, не могли бы вы поделиться ссылкой?
ой ( я про него вообще забыла…
Доброе времени суток! Вы не могли бы подсказать как можно реализовать Аффинный рекуррентный шифр. Заранее благодарен.
Доброе )
В статье (двух, если точнее) именно он разобран: аффинный рекурентный шифр = аффинный шифр, т.е. это одно и то же.
Ну просто мне говорили, что их различие заключается в том, что в аффинном рекуррентном шифре для каждого символа открытого текста вычисляется новое ключевое значение на основе предыдущего.
Вы точно говорите о шифре подстановки (которым является аффинный)?
Просто вот это
совсем не вяжется с данным видом шифров.
Вот что я сказал это и есть отличие аффинного рекуррентного шифра от аффинного шифра.
Я так полагаю что вы мне ничем не можете помочь???
Выкладывайте СВОИ наработки, уточните что на основе чего генерируется в вашем таинственном “Афинном рекуррентном шифре”. Или вы предлагаете разобраться в чем-то что “вам сказали” да ещё и программу написать?
Да, мне надо в этом разобраться и написать программу. Но дело в том, что я не силен в программировании(((
Еще раз: аффинный шифр является одним из шифров подстановки – алфавит шифрации един для любого шифруемого символа, т.е. он не изменяется в процессе шифрования. То, о чем вы говорите, это не аффинный шифр.
И как уже ниже сказали: для того, чтоб помочь – нужно видеть, что уже сделано.
Здравствуйте)Помогите пожалуйста. Вроде делала все как у Вас в инструкции, но почему-то неправильно работает(
Алфавит почему-то не как у Вас(не смотря на то, что а=3,b=5, без одной буквы, и в закодированном слове буквы тоже не все..
пишу на с++ в code::blocks
Скриншот выполнения:
http
://s017.radikal.ru/i431/1412/ff/c9cfdf6889db.pngГлючно отобразился код, жалко, что нельзя отредактировать сообщение. Попробую код без тега:
#include
#include
using namespace std;
int main()
{
string sh =”abcdefghijklmnopqrstuvwxyz”;
int i,j,a,b,f,len;
string alf[26],shifr[26],ich[26],str1,kod[26];
cout << sh << 'n';
for(int i=1;i<27;i++)
alf[i]=sh.substr(i,1);
a=3; b=5;
for(int j=1;j25)
{
int f=(b+a*(j-1))/ 26;
shifr[j]=alf[b+1+a*(j-1)-26*f];
}
else shifr[j]=alf[b+1+a*(j-1)];
}
for(int j=1;j<27;j++)
cout << shifr[j];
cout << "n" << "vvedi text bez probelov: " <> str1;
len = str1.length();
cout << "v texte " << len <<" simvolov"<< 'n';
cout << "shifr:"<< 'n';
for(int i=1;i<(len+1);i++)
ich[i]=str1.substr(i,1);
for(int i=1;i<len+1;i++)
{
for(int j=1;j<27;j++)
{
if(ich[i]==alf[j])
{
kod[i]=shifr[j]; //cout << kod[i];
j++;
}
}
}
for(int i=1;i<len;i++)
cout << kod[i];
return 0;
}
Здравствуй, не могла бы ты скинуть готовый код? Была бы очень благодарна)))
Доброй ночи. К сожалению, исходники погибли вместе со старым винтом ((( Сейчас уже копирую исходник сразу к записи, но старые утеряны безвозвратно ;(
огромная печаль((…может быть у вас где-нибудь завалялся расширенный алгоритм евклида?(на с++) или другие шифры =) попытка не пытка..может мне повезет =)
Метод Гронсфельда?)
нет. именно расширенный алгоритм евклида, его используют для того чтобы найти обратное значение при дешифрации афинного шифра.
(((
к сожалению, нету.
Про метод Гронсфельда написала, потому что нашла реализованным. Надо, наверно, пост о нем наваять =)
Помощь уже не нужна, написала по-другому. Простите за беспокойство, удачи Вам)
Вам тоже удачи )
А алфавит-то сошелся? – В статье верный указан…
Да, сошелся, лабу сдала, спасибо)
Здравствуйте, помогите пожалуйста реализовать шифр Playfair в с++ или в JavaScript
Добрый вечер. Помочь можно, если есть хоть какие-то наработки =)
Подскажите что не так с программой?
#include
#include
#include
using namespace std;
int main();
{
int a,b,i,j,len;
String sh, str, alf[i], shifr[i], ich[i], kod[i];
sh=”abcdefghijklmnopqrstuvwxyz”;
for (int i=1; i<27; i++)
alf[i]=sh.SubString(i,1); //разделение строки на символы
str="abc";
a=3; b=5;
for ( int j=1; j25)
int f=(b+a*(j-1))/26;
shifr[j]=alf[b+1+a*(j-1)-26*f];
}
else shifr[j]=alf[b+1+a*(j-1)];
}
for(int i; i<len+1; i++)
ich[i]=str.SubString(i,1);
for(int i=1; i<len+1; i++)
{
for(int j=1; j<27; j++)
{
if(ich[i]==alf[j])
{
kod[i]=shifr[j];
j++;
printf();//при a=3, b=5 abc=EHK
}
}
}
{
for(int i=1;i<len;i++)
cout << kod[i];
return 0;
}
Выводит ошибку expected unqualified id before '{' token
String sh, str, alf[i], shifr[i], ich[i], kod[i];
Вот здесь у вас динамические массивы, но созданы они неверно. Либо создавайте правильно, либо сразу указывайте размерность.