
ОИУСЗИ / MSZI_2003
.pdf
Криптографическая система RSA 371
Широко известным примером криптосистемы с открытым ключом является криптосистема RSA, разработанная в 1977 году и получившая название в честь ее создателей: Ривеста, Шамира и Эйдельмана. Стойкость этой системы основывается на сложности обратимости степенной функции в кольце вычетов целых чисел по составному модулю n (при надлежащем выборе модуля).
Необходимые сведения из элементарной теории чисел
1.Простым числом называется натуральное число, имеющее только два неравных натуральных делителя.
2.Каждое натуральное число единственным образом, с точностью до порядка записи сомножителей, представляется в виде произведения степеней простых чисел.
3.Наибольшим общим делителем двух целых чисел НОД(a,b) (или (a,b)) называется наибольшее целое, на которое без остатка делится как a, так и b.
4.Пусть a > b и d = (a,b). Тогда существуют целые x и у, являющиеся решением уравнения xa + yb = d. Если d = 1, то a и b называются взаимно простыми.
5.Наибольший общий делитель двух чисел можно найти с помощью алгоритма Эвкли-
да. Для этого a делится с остатком на b, т.е. а = q1b + r1. Далее вместо a и b, рассматриваем соответственно b и r1: b = q2r1+ r2. На следующем шаге роль b и r1, играют r1 и r2: r1 = q3r2 + r3 ит.д. Процесс заканчивается на некотором шаге k+1, для которого rk+1= 0. Тогда НОД(a,b) = rk. Рассмотрим пример.
Найти НОД(1547, 560) 1547 = 2 х 560 + 427 560 = 1 х 427 + 133 427 = 3 х 133 + 28 133 = 4 х 28 + 21 28 = 1 х 21 + 7 21 = 3 х 7 + 0 НОД(1547,560)=7
6.Для решения уравнения xa + yb = d можно использовать данные, полученные в каждом шаге алгоритма Эвклида, двигаясь снизу вверх, с помощью выражения остатка
через другие элементы, используемые в соответствующем шаге. Например, из r2 = q4r3 + r4 следует r4 = r2 +q4r3. В последнем равенстве r3 можно заменить, исходя
из соотношения r1 = q3r2 + r3, т.е. r4 = r2 – q4(q3r2 – r1). Поэтому r4 = (1 – q4q3)r2
+ q4r1. Таким образом, мы выразили r4 в виде целочисленной комбинации остатков с меньшими номерами, которые, в свою очередь, могут быть выражены аналогично. Продвигаясь “снизу вверх”, в конце концов, мы выразим r4 через исходные числа a и b. Если бы мы начали не с r4, а с rk, то получили бы rk = xa + yb = d. Рассмотрим пример.
Решить 1547х + 560y = 7

372 Глава 18. Криптографическая защита
7 |
= |
28 – 1 х 21 |
= 28 |
– 1 |
х |
(133 — 4 х 28) = 5 х 28 - 1 х 1ЗЗ = |
|||
= 5 |
х (427 |
- 3 х |
133) |
— 1 |
х |
13З = 5 х 427 – 16 х (560 - 1 х 427)= |
|||
= 21 |
х |
427 |
- 16 |
х 560 |
= 21 |
|
х (1547 - 2 х 560) - 16 х 560 = |
||
= |
21 |
х |
547 - 58 х 560 |
|
|
|
|||
Решение: x = 21, y = -58 |
|
7.Число a сравнимо с числом b по модулю n, если a – b делится на n. Запись данного утверждения имеет следующий вид: а = b(mod n). Наименьшее неотрица-
тельное число а, такое, что а = A(mod n) называется вычетом числа A по модулю n. Если (a,n) = 1, то существует x, такое, что x = a-1 (mod n).
Действительно, (a,n) = 1 = d = ax + ny, поэтому ax = 1(mod n). Такое число x называется обратным к апо модулю n и записывается в виде a-1 (mod n).
8.Пусть функция ϕ(n), где n — натуральное число, равна количеству натуральных чисел, меньших n, для которых (а,n)=1. Такая функция называется функцией Эйлера.
Для чисел n вида n = Пpi (pi — простое) функция Эйлера определяется как φ(n) =
i
i(pi – 1).
9.Теорема Эйлера. Пусть (а,n) = 1. Тогда aφ(n) = 1(mod n). Следствие. Если ed = 1(mod φ(n)) и (a, n) = 1, то (аe)d = а(mod n).
10.Для большинства вычетов по модулю n = pq показатель степени в соотношении aφ(n)
= 1(mod n) может быть уменьшен, но в этом случае он зависит от a. Наименьший показатель k(a), для которого ak(a) = 1(mod n), называется порядком числа a по мо-П
дулю n и обозначается как оrdn(a). Для любого a значение оrdn(a) является делителем значения функции Эйлера φ(n).
Алгоритм RSA
Криптосистема RSA на каждом такте шифрования преобразует двоичный блок открытого текста m длины size(n), рассматриваемый как целое число, в соответствии с формулой: c = me(mod n).
При этом n = pq, где p и q — случайные простые числа большой разрядности, которые уничтожаются после формирования модуля и ключей. Открытый ключ состоит из пары чисел e и n. Подключ e выбирается как достаточно большое число из диапазона 1 < e < φ(n), с условием: НОД(e, ϕ(n)) = 1, где ϕ(n) — наименьшее общее кратное чисел p–1 и q–1. Далее, решая в целых числах x, y уравнение xe + yφ(n) = 1, полагается d = х, т.е. ed = 1(ϕ(n)). При этом для всех m выполняется соотношение med = m(n), поэтому знание d позволяет расшифровывать криптограммы.
Чтобы гарантировать надежную защиту информации, к системам с открытым ключом предъявляются два следующих требования.
1.Преобразование исходного текста должно исключать его восстановление на основе открытого ключа.

Криптографическая система RSA 373
2.Определение закрытого ключа на основе открытого также должно быть вычислительно нереализуемым. При этом желательна точная нижняя оценка сложности (количества операций) раскрытия шифра.
Алгоритмы шифрования с открытым ключом получили широкое распространение в современных информационных системах.
Рассмотрим построение криптосистемы RSA на простом примере.
1.Выберем p = 3 и q = 11.
2.Определим n = 3 · 11 = 33.
3.Найдем ϕ(n) = (p – 1)(q – 1) = 20.
4.Выберем e, взаимно простое с 20, например, e = 7.
5.Выберем число d, удовлетворяющее 7d = 1(mоd 20).
Легко увидеть, что d = 3(mоd 20).
Представим шифруемое сообщение как последовательность целых чисел с помощью соответствия: А = 1, B = 2, С = 3, ..., Z = 26. Поскольку size(n) = 6, то наша криптосистема в состоянии зашифровывать буквы латинского алфавита, рассматриваемые как блоки, Опубликуем открытый ключ (e, n) = (7, 33) и предложим прочим участникам системы секретной связи зашифровывать с его помощью сообщения, направляемые в наш адрес. Пусть таким сообщением будет CAB, которое в выбранном нами кодировке принимает вид (3, 1, 2). Отправитель должен зашифровать каждый блок и отправить зашифрованное сообщение в наш адрес:
RSA(C) = RSA(3) = 37 = 2187 = 9(mod 33);
RSA(A) = RSA(1) = 17 = 1(mod 33);
RSA(B) = RSA(1) = 27 = 128 = 29(mod 33).
Получив зашифрованное сообщение (9, 1, 29), мы сможем его расшифровать на основе секретного ключа (d, n) = (3, 33), возводя каждый блок в степень d = 3:
93 = 729 = 3(mоd 33);
13 = 1(mоd 33);
293 = 24389 = 2(mоd 33).
Для нашего примера легко найти секретный ключ перебором. На практике это невозможно, т.к. для использования на практике рекомендуются в настоящее время следующие значения size(n):
•512–768 бит — для частных лиц;
•1024 бит — для коммерческой информации;
•2048 бит — для секретной информации.
Пример реализации алгоритма RSA представлен в листингах 18.1 и 18.2 (компилято-
ры — Delphi, FreePascal).

374 Глава 18. Криптографическая защита
Листинг 18.1. Пример реализации алгоритма RSA на языке Pascal
program Rsa; {$APPTYPE CONSOLE} {$IFDEF FPC} {$MODE DELPHI} {$ENDIF}
uses SysUtils, uBigNumber;
//Генератор случайных чисел var t: array[0..255] of Byte; var pos: Integer;
var cbox: array[0..255] of Byte =
(237, 240, 161, 1, 130, 141, 205, 98, 27, 169, 181, 202, 173, 47, 114, 224, 35, 183, 79, 82, 153, 220, 172, 22, 17, 11, 200, 131, 14, 154, 167, 91, 250, 31, 213, 112, 126, 241, 236, 155, 198, 96, 87, 143, 244, 151, 134, 38, 129, 233, 186, 101, 41, 94, 231, 115, 113, 199, 51, 145, 229, 37, 69, 180, 85, 33, 207, 163, 102, 187, 4, 89, 7, 44, 75, 88, 81, 120, 10, 232, 221, 168, 230, 158, 247, 211, 216, 156, 95, 64, 242, 215, 77, 165, 122, 5, 15, 119, 100, 43, 34, 48, 30, 39, 195, 222, 184, 92, 78, 135, 103, 166, 147, 32, 60, 185, 26, 251, 214, 90, 139, 45, 73, 150, 97, 116, 136, 68, 219, 248, 191, 192, 16, 8, 243, 50, 132, 105, 62, 201, 204, 65, 0, 99, 182, 121, 194, 108, 160, 170, 56, 226, 206, 254, 117, 178, 9, 197, 234, 127, 58, 171, 40, 29, 177, 142, 3, 228, 188, 162, 212, 157, 49, 175, 174, 140, 70, 106, 123, 66, 196, 246, 179, 42, 218, 71, 217, 227, 18, 164, 24, 67, 159, 25, 111, 255, 193, 245, 2, 238, 133, 21, 137, 152, 109, 148, 63, 124, 203, 104, 54, 55, 223, 80, 107, 210, 225, 149, 252, 76, 12, 189, 93, 46, 23, 13, 36, 209, 61, 249, 110, 144, 86, 52, 253, 72, 28, 53, 57, 125, 59, 235, 84, 128, 208, 146, 20, 74, 6, 239, 190, 83, 19, 138, 118, 176);
procedure InicMyRandom; var i: Integer;
var s: string; begin
WriteLn('Введите какой-либо текст для инициализации генератора случайных чисел (до 256 символов):');
ReadLn(s); i := 1;
while (i<=255) and (i<=Length(s)) do

Криптографическая система RSA 375
Продолжение листинга 18.1
begin
t[i] := Ord(s[i]); Inc(i);
end;
pos := 0; WriteLn('OK'); WriteLn;
end;
function MyRandom: Cardinal; var i: Integer;
var l: Cardinal; |
|
|
begin |
0) then |
|
if (pos = |
|
|
begin |
1 to 255 do |
t[i] := cbox[(t[i-1]+t[i]) and 255]; |
for i := |
for i := 254 downto 0 do t[i] := cbox[(t[i]+t[i+1]) and 255]; end;
l := 0;
for i := 0 to 3 do l := l shl 8 + Cardinal(t[pos+i]); Result := l;
pos := (pos+4) and 255; end;
//-------------------------------------------------------------
//Главная программа var i,j: Integer; var maxbit: Integer;
var none,ntwo: TBigNum; var n1,n2: TBigNum; var p,q,z: TBigNum; var n,e,d: TBigNum; var s1,s2: string;
begin WriteLn;
InicMyRandom(); repeat
Write('Введите максимальный размер простых чисел (p и q) в
битах (8-257): '); ReadLn(maxbit);

376 Глава 18. Криптографическая защита
Продолжение листинга 18.1
until (maxbit>=8) and (maxbit<=257); //p
WriteLn('Введите большое десятичное значение, которое будет использовано в качестве первого простого числа (Enter -> генерируется программой): ');
ReadLn(s1); BN_dec_to_bignum(s1,p); BN_bignum_to_dec(p,s2); if (s1<>s2) then
begin
if (s1<>'') then WriteLn('Число задано неверно!'); s1 := '0'; BN_dec_to_bignum(s1,p);
for i := 0 to BIGNUM_DWORD do n1[i] := MyRandom(); BN_a_shr_k(n1,(BIGNUM_DWORD+1)*32-maxbit,p); BN_bignum_to_dec(p,s2);
WriteLn('Сгенерированное число: ',s2); end;
WriteLn('Поиск первого простого числа... Ждите...'); p[0] := p[0] or 1;
s1 := '2'; BN_dec_to_bignum(s1,ntwo); j := 0;
while (BN_PrimeTest(p)=0) and (j<8192) do begin
BN_a_add_b(p,ntwo,n1);
Move(n1,p,sizeof(n1));
Inc(j);
Write('.');
end;
WriteLn;
if (j>=8192) then begin
WriteLn('К сожалению, простое число не найдено!'); WriteLn('Нажмите Enter для выхода.'); ReadLn; Halt(1);
end; BN_bignum_to_dec(p,s1);
WriteLn('Первое простое число p = ',s1); //q
WriteLn('Введите большое десятичное значение, которое будет использовано в качестве второго простого числа (Enter -> генерируется программой): ');

Криптографическая система RSA 377
Продолжение листинга 18.1
ReadLn(s1); BN_dec_to_bignum(s1,q); BN_bignum_to_dec(q,s2); if (s1<>s2) then
begin
if (s1<>'') then WriteLn('Число задано неверно!'); s1 := '0'; BN_dec_to_bignum(s1,q);
for i := 0 to BIGNUM_DWORD do n1[i] := MyRandom(); BN_a_shr_k(n1,(BIGNUM_DWORD+1)*32-maxbit,q); BN_bignum_to_dec(q,s2);
WriteLn('Сгенерированное число: ',s2); end;
WriteLn('Поиск первого простого числа... Ждите...'); q[0] := q[0] or 1;
s1 := '2'; BN_dec_to_bignum(s1,ntwo); j := 0;
while (BN_PrimeTest(q)=0) and (j<8192) do begin
BN_a_add_b(q,ntwo,n1);
Move(n1,q,sizeof(n1));
Write('.');
end;
WriteLn;
if (j>=8192) then begin
WriteLn('К сожалению, простое число не найдено!'); WriteLn('Нажмите Enter для выхода.'); ReadLn; end;
BN_bignum_to_dec(q,s1);
WriteLn('Второе простое число q = ',s1); WriteLn;
//n = p*q BN_a_mul_b(p,q,n); BN_a_div_b(n,q,n1);
if (BN_a_cmp_b(p,n1)<>0) then begin
WriteLn('К сожалению, результат умножения p*q слишком велик!'); WriteLn('Нажмите Enter для выхода.'); ReadLn;
Halt(1);
end; BN_bignum_to_dec(n,s1);

378 Глава 18. Криптографическая защита
Продолжение листинга 18.1
WriteLn('n = p*q = ',s1); // z =(p-1)*(q-1)
s1 := '1'; BN_dec_to_bignum(s1,none); BN_a_sub_b(p,none,n1); BN_a_sub_b(q,none,n2); BN_a_mul_b(n1,n2,z); BN_bignum_to_dec(z,s1);
WriteLn('z = (p-1)*(q-1) = ',s1); // d
WriteLn('Введите большое десятичное значение, которое будет использовано в качестве открытого ключа (Enter -> генерируется программой): ');
ReadLn(s1); BN_dec_to_bignum(s1,d); BN_bignum_to_dec(d,s2); if (s1<>s2) then
begin
if (s1<>'') then WriteLn('Число задано неверно!'); s1 := '0'; BN_dec_to_bignum(s1,n1);
for i := 0 to BIGNUM_DWORD do n1[i] := MyRandom(); BN_a_mod_b(n1,z,d);
BN_bignum_to_dec(d,s2); WriteLn('Сгенерированное число: ',s2); end;
WriteLn('Поиск открытого ключа... Ждите...'); d[0] := d[0] or 1;
s1 := '1'; BN_dec_to_bignum(s1,none);
s1 := '2'; BN_dec_to_bignum(s1,ntwo); j := 1;
BN_ab_GCD(d,z,n1);
while (BN_a_cmp_b(n1,none)<>0) and (j<1000) do begin
BN_a_add_b(d,ntwo,n1);
Move(n1,d,sizeof(n1)); BN_ab_GCD(d,z,n1);
j := j+1; end;
BN_ab_GCD(d,z,n1);
if (BN_a_cmp_b(n1,none)<>0) then begin
WriteLn('К сожалению, подходящего простого числа не найдено!');

Криптографическая система RSA 379
Продолжение листинга 18.1
WriteLn('Нажмите Enter для выхода.'); ReadLn; Halt(1);
end;
WriteLn; BN_bignum_to_dec(d,s1);
WriteLn('Открытый ключ d = ',s1); WriteLn;
// e
WriteLn('Вычисление секретного ключа...'); BN_a_modinv_b(d,z,e); BN_bignum_to_dec(e,s1);
WriteLn('Секретный ключ e = ',s1); WriteLn;
//e*d mod z = 1 ? BN_a_mul_b(e,d,n1); BN_a_mod_b(n1,z,n2);
if (BN_a_cmp_b(n2,none)<>0) then begin
WriteLn('СБОЙ: e*d mod z <> 1!'); WriteLn('Нажмите Enter для выхода.'); ReadLn; Halt(1);
end;
WriteLn('e*d mod z = 1'); WriteLn;
//Проверка ключей.
WriteLn('Введите большое значение для проверки ключей (Enter -> генерируется программой):');
ReadLn(s1); BN_dec_to_bignum(s1,n1); BN_bignum_to_dec(n1,s2); if (s1<>s2) then
begin
if (s1<>'') then WriteLn('Число задано неверно!'); s1 := '0'; BN_dec_to_bignum(s1,n1);
for i := 0 to BIGNUM_DWORD do n1[i] := MyRandom(); end;
n1[7] := 0; BN_a_mod_b(n1,n,n2);
BN_bignum_to_hex(n2,s2);

380 Глава 18. Криптографическая защита
Окончание листинга 18.1
WriteLn('Исходное значение = 0x',s2); BN_a_exp_b_mod_c(n2,e,n,n1); BN_bignum_to_hex(n1,s1); WriteLn('Зашифрованное значение = 0x',s1); BN_a_exp_b_mod_c(n1,d,n,n2); BN_bignum_to_hex(n2,s1); WriteLn('Расшифрованное значение = 0x',s1); if (s1<>s2) then
begin
WriteLn('СБОЙ: расшифрованное значение не совпадает с исходным!');
WriteLn('Нажмите Enter для выхода.'); ReadLn; Halt(1);
end;
WriteLn('OK');
WriteLn;
//Техническая информация.
WriteLn('-------------------------------------------------- |
'); |
BN_bignum_to_hex(e,s1); |
(',BN_a_upbit(e),'bit)'); |
WriteLn(' e = 0x',s1,' |
|
BN_bignum_to_hex(d,s1); |
(',BN_a_upbit(d),'bit)'); |
WriteLn(' d = 0x',s1,' |
|
BN_bignum_to_hex(n,s1); |
(',BN_a_upbit(n),'bit)'); |
WriteLn(' n = 0x',s1,' |
|
WriteLn('-------------------------------------------------- |
'); |
WriteLn; |
|
WriteLn(' Размер блока исходного текста: ',IntToStr(BN_a_upbit(n)-1),' бит'); WriteLn(' Размер блока зашифрованного текста: ',IntToStr(BN_a_upbit(n)),' bit');
WriteLn;
WriteLn('Нажмите Enter для выхода.'); ReadLn; end.
Листинг 18.2. Вспомогательный модуль uBigNumber
unit uBigNumber; {$IFDEF FPC} {$MODE DELPHI} {$ASMMODE INTEL} {$ENDIF}