Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Введение в криптологию. В 4 частях. Ч.1. Учебное пособие.pdf
Скачиваний:
0
Добавлен:
06.09.2026
Размер:
1 Мб
Скачать
61
отбросим ноль из разряда единиц
1001002  100102
и переведём полученное число в десятичный вид
100102 = 1810.
Поэтому более экономичным с точки зрения компьютерной реализации является отобра­жение, которое также сохраняет НОД, но использует операцию деления на 2:
 
 
.чётноеинечётноеесли),2/,(
;нечётноеичётноеесли),,2/(
;нечётныеиесли),,2/)((
),(
baba
baba
babba
ba
(1.55)
Например, для нечётных a = 19 и b = 15 отображение сохраняет НОД, равный 1:
(19, 15)  ((19 – 15) / 2, 15) = (2, 15).
Для чётного a = 20 и нечётного b = 5 отображение сохраняет НОД, равный 5:
(20, 5)  (20 / 2, 5) = (10, 5).
Для нечётного a = 27 и чётного b = 30 отображение сохраняет НОД, равный 3:
(27, 30)  (27, 30 / 2) = (27, 15).
Отображение (1.55) даёт основу для двоичного алгоритма Евклида, который обыч­но и реализуется в компьютерных программах. По существу, этот алгоритм использует последнее отображение после того, как выделит из НОД максимально возможную степень двойки. Например, для чётных a = 216 и b = 256 сначала из НОД выделяется максималь­ная степень двойки, равная восьми:
(216, 256)  (216/ 2, 256/ 2) = (108, 128) (выделена
221
),
(108, 128)  (108 / 2, 128 / 2) = (54, 64) (выделена
422
),
(54, 64)  (54 / 2, 64 / 2) = (27, 32) (выделена
823
).
Затем используется отображение (1.55):
(27, 32)  (27, 32 / 2) = (27, 16),
(27, 16)  (27, 16 / 2) = (27, 8),
(27, 8)  (27, 8 / 2) = (27, 4),
(27, 4)  (27, 4 / 2) = (27, 2),
62
(27, 2)  (27, 2 / 2) = (27, 1),
(27, 1)  ((27 – 1) / 2, 1) = (13, 1),
(13, 1)  ((13 – 1) / 2, 1) = (6, 1),
(6, 1)  (6 / 2, 1) = (3, 1),
(3, 1)  ((3 – 1) / 2, 1) = (1, 1),
(1, 1)  ((1 – 1) / 2, 1) = (0, 1).
Наконец, НОД (216, 256) вычисляется как максимальная степень двойки (8), умноженная на итоговое значение b (1):
НОД (216, 256) = 8 · 1 = 8.
Реализация двоичного алгоритма Евклида на языке Си имеет следующий вид:
// Двоичный алгоритм Евклида вычисления НОД(a, b)
#include<stdio.h>
#include<conio.h>
void main()
{
int a,b,nod;
int dae(int, int);
clrscr();
printf("a = ");
scanf("%d",&a);
printf("b = ");
scanf("%d",&b);
nod=dae(a,b);
printf("NOD(%d,%d) = %d ",a,b,nod);
printf("\nPress any key...");
getch();
}
int dae(int a, int b)
{
printf("a = %d, b = %d\n",a,b);
int g=1;
printf("g = %d\n",g);
// Выделение степени двойки из НОД
while ((a%2==0) && (b%2==0))
63
{
a=a/2;
b=b/2;
printf("a = %d, b = %d\n",a,b);
g=2*g;
printf("g = %d\n",g);
}
// По крайней мере одно из a и b сейчас нечётно
while (a!=0)
{
while (a%2==0)
{
a=a/2;
printf("a = %d\n",a);
}
while (b%2==0)
{
b=b/2;
printf("b = %d\n",b);
}
// Сейчас как a, так и b нечётны
if (a>=b)
{
a=(a-b)/2;
printf("a = %d\n",a);
}
else
{
b=(b-a)/2;
printf("b = %d\n",b);
}
}
return g*b;
}
Результаты исполнения двоичного алгоритма Евклида вычисления НОД (a, b) для некоторых пар значений переменных a и b представлены в табл. 1.61.
64
Таблица 1.61
Пример исполнения двоичного алгоритма Евклида
1 2 3
a = 21, b = 12
g = 1
b = 6
b = 3
a = 9
a = 3
a = 0
NOD(21,12) = 3
Press any key…
a = 24, b = 36
g = 1
a = 12, b = 18
g = 2
a = 6, b = 9
g = 4
a = 3
b = 3
a = 0
NOD(24,36) = 12
Press any key…
a = 52, b = 36
g = 1
a = 26, b = 18
g = 2
a = 13, b = 9
g = 4
a = 2
a = 1
b = 4
b = 2
b = 1
a = 0
NOD(52,36) = 4
Press any key…
Продолжение табл. 1.61
Пример исполнения двоичного алгоритма Евклида
4 5 6
a = 108, b = 256
g = 1
a = 54, b = 128
g = 2
a = 27, b = 64
g = 4
b = 32
b = 16
b = 8
b = 4
b = 2
b = 1
a = 13
a = 6
a = 3
a = 1
a = 0
NOD(108,256) = 4
Press any key...
a = 216, b = 256
g = 1
a = 108, b = 128
g = 2
a = 54, b = 64
g = 4
a = 27, b = 32
g = 8
b = 16
b = 8
b = 4
b = 2
b = 1
a = 13
a = 6
a = 3
a = 1
a = 0
NOD(216,256) = 8
Press any key...
a = 218, b = 256
g = 1
a = 109, b = 128
g = 2
b = 64
b = 32
b = 16
b = 8
b = 4
b = 2
b = 1
a = 54
a = 27
a = 13
a = 6
a = 3
a = 1
a = 0
NOD(218,256) = 2
Press any key...
65
Если же необходимо разделить многочлен f на многочлен g с остатком, то необхо­димо найти такие многочлены q и r (
gr degdeg0
)5, что
f = qg + r. (1.56)
Например, если в кольце F2[x] разделить многочлен f = x5 + x4 + x2 + x на многочлен
g = x4 + 1 с остатком, то будут найдены такие многочлены q = x + 1 и r = x2 + 1 (
2deg r,4deg g
,
gr degdeg0
), что
f = q g + r = (x + 1) ∙ (x4 + 1) + (1 + x2).

1.3.5. РАСШИРЕННЫЙ АЛГОРИТМ ЕВКЛИДА

Вычисляя НОД (a, N) с помощью алгоритма Евклида, можно выяснить, обратимо ли число a по модулю N. Однако до сих пор неизвестно, как найти обратный к a элемент, даже если он существует.
Напомним, что алгоритм Евклида осуществляет последовательное деление с остатком:
a = q0 ∙ b + r1,
b = q1 ∙ r1 + r2,
r1 = q2 ∙ r2 + r3,
r
k – 2
= q
k – 1
∙ r
k – 1
+ rk,
r
n – 3
= q
n – 2
∙ r
n – 2
+ r
n - 1
,
r
n – 2
= q
n – 1
∙ r
n – 1
+ rn,
r
n – 1
= qn ∙ rn
и НОД (a, b) = rn – последнему ненулевому члену этой последовательности.
Перепишем формулы для остатков от деления ri следующим образом:
a = q0 ∙ b + r1 → r1 = a + b ∙ (–q0),
b = q1 ∙ r1 + r2 → r2 = b – r1 ∙ q1 =
= b – (a + b ∙ (–q0)) ∙ q1 = b – a ∙ q1 + b ∙ q0 ∙ q1 =
= a ∙ (–q1 ) + b ∙ (1 + q0 q1 ),
5
Напомним, что, например, символ deg r обозначает степень многочлена r, которая равна наиболь-
шей степени входящих в него мономов.
66
r1 = q2 r2 + r3 r3 = r1 q2 r2 =
= a + b ∙ (–q0) – q2 ∙ (a ∙ (–q1 ) + b ∙ (1 + q0 q1 )) =
= a + b ∙ (–q0) + a ∙ (q1 ∙ q2) + b ∙ (– q2) ∙ (1 + q0 q1 ) =
= a ∙ (1 + q1 ∙ q2) + b ∙ (–q0 – q2 – q0 ∙ q1 ∙ q2),
………………….
rn = a ∙ s + b ∙ t,
где s и t – целые числа.
Это представление наибольшего общего делителя НОД (a, b) = rn в виде НОД (a, b) = = as + b ∙ t называется соотношением Безу, а числа s и tкоэффициентами Безу.
Например, получим соотношение Безу и определим коэффициенты Безу в случае, когда a = 21 и b = 12:
a = q0 b + r1 r1 = a + b ∙ (–q0),
21 = 1 ∙ 12 + 9 → 9 = 21 + 12 ∙ (–1),
b = q1 ∙ r1 + r2 → r2 = a ∙ (–q1 ) + b ∙ (1 + q0 ∙ q1 ),
12 = 1 ∙ 9 + 3 → 3 = 21 ∙ (–1) + 12 ∙ (1 + 1 ∙ 1) = 21 ∙ (–1) + 12 ∙ 2,
НОД (a, b) = rn = as + b t,
НОД (21, 12) = r2 = 3 = 21 ∙ (–1) + 12 ∙ 2,
s = –1, t = 2.
Во втором примере получим соотношение Безу и определим коэффициенты Безу в случае, когда a = 19 и b = 7:
a = q0 b + r1 r1 = a + b ∙ (–q0),
19 = 2 7 + 5 5 = 19 + 7 ∙ (–2),
b = q1 ∙ r1 + r2 → r2 = a ∙ (–q1 ) + b ∙ (1 + q0 ∙ q1 ),
7 = 1 ∙ 5 + 2 2 = 19 ∙ (–1) + 7 ∙ (1 + 2 ∙ 1) = 19 ∙ (–1) + 7 3,
r1 = q2 ∙ r2 + r3 → r3 = a ∙ (1 + q1 ∙ q2) + b ∙ (–q0 – q2 – q0 ∙ q1 ∙ q2),
5 = 2 ∙ 2 + 1 1 = 19 (1 + 1 ∙ 2) + 7 ∙ (–2 – 2 – 2 ∙ 1∙ 2) =
= 19 ∙ 3 + 7 ∙ (–8),
НОД (a, b) = rn = as + b t,
НОД (19, 7) = r3 = 1 = 19 ∙ 3 + 7 ∙ (–8),
s = 3, t = –8.
67
Приведём реализацию расширенного алгоритма Евклида на языке Си:
#include <stdio.h>
#include <conio.h>
int main()
{
int a, // Число a
b, // Число b
d, // НОД (a,b)
s, // Коэффициент s соотношения Безу НОД (a,b)= a*s + b*t
t; // Коэффициент t соотношения Безу НОД (a,b)= a*s + b*t
// Прототип функции extGCD (расширенный алгоритм Евклида)
void extGCD(int, int, int *, int *, int *);
printf("Введите a и b:\n");
scanf("%d%d", &a, &b);
printf("a = %d b = %d\n",a,b);
if (a == 0 && b == 0)
{
printf("Должно быть хотя бы одно ненулевое.\n");
return 1; // Возврат кода некорректного завершения
}
// Вызов расширенного алгоритма Евклида
extGCD(a, b, &d, &s, &t);
// Вывод ответа
printf("НОД(%d, %d) = %d, s = %d, t = %d\n", a, b, d, s, t);
printf("Press any key ...");
getch();
printf("\n\n");
return 0; // Возврат кода успешного завершения
}
void extGCD(int a, int b, int *d, int *s, int *t)
{
int x, y, q, r, s1, t1, s2, t2;
int tmp; // Вспомогательная переменная
68
// Инициализация
x = a; y = b;
s1 = 1; t1 = 0;
s2 = 0; t2 = 1;
printf("%d = %d * (%d) + %d * (%d)\n",x,a,s1,b,t1);
// Утверждение: НОД(x, y) == НОД(a, b) &&
// x == a * s1 + b * t1 &&
// y == a * s2 + b * t2;
while (y != 0)
{
// Инвариант: НОД(x, y) == НОД(a, b) &&
// x == a * s1 + b * t1 &&
// y == a * s2 + b * t2;
q = x / y; // Целая часть частного x / y
r = x % y; // Остаток от деления x на y
x = y; y = r; // Замена пары (x, y) на (y, r)
// Вычисление новых значений переменных s1, s2
tmp = s2; // Запоминание старого значения s2
s2 = s1 - q * s2; // Вычисление нового значения s2
s1 = tmp; // Новому s1 присвоить старое s2
// Вычисление новых значений переменных t1, t2
tmp = t2;
t2 = t1 - q * t2;
t1 = tmp;
printf("%d = %d * (%d) + %d * (%d)\n",x,a,s1,b,t1);
}
// Утверждение: y == 0 &&
// НОД(x, y) == НОД(m, n) &&
// x == s1 * m + t1 * n;
// Выдаем ответ
*d = x;
*s = s1; *t = t1;
}
69
Результаты исполнения расширенного алгоритма Евклида вычисления НОД (a, b) и получения соотношения Безу для некоторых пар значений переменных a и b представ­лены в табл. 1.62.
Таблица 1.62
Пример исполнения расширенного алгоритма Евклида
1
2
a = 21 b = 12
21 = 21 * (1) + 12 * (0) 12 = 21 * (0) + 12 * (1)
9 = 21 * (1) + 12 * (-1) 3 = 21 * (-1) + 12 * (2)
НОД(21, 12) = 3, s = -1, t = 2
Press any key ...
a = 19 b = 7
19 = 19 * (1) + 7 * (0) 7 = 19 * (0) + 7 * (1)
5 = 19 * (1) + 7 * (-2) 2 = 19 * (-1) + 7 * (3)
1 = 19 * (3) + 7 * (-8)
НОД(19, 7) = 1, s = 3, t = -8 Press any key ...
Продолжение табл. 1.62
Пример исполнения расширенного алгоритма Евклида
3
4
a = 31 b = 12
31 = 31 * (1) + 12 * (0)
12 = 31 * (0) + 12 * (1)
7 = 31 * (1) + 12 * (-2)
5 = 31 * (-1) + 12 * (3)
2 = 31 * (2) + 12 * (-5)
1 = 31 * (-5) + 12 * (13)
НОД(31, 12) = 1, s = -5, t = 13
Press any key ...
a = 43 b = 15
43 = 43 * (1) + 15 * (0)
15 = 43 * (0) + 15 * (1)
13 = 43 * (1) + 15 * (-2)
2 = 43 * (-1) + 15 * (3)
1 = 43 * (7) + 15 * (-20)
НОД(43, 15) = 1, s = 7, t = -20
Press any key ...
Продолжение табл. 1.62
Пример исполнения расширенного алгоритма Евклида
5
6
a = 12 b = 21
12 = 12 * (1) + 21 * (0)
21 = 12 * (0) + 21 * (1)
12 = 12 * (1) + 21 * (0)
9 = 12 * (-1) + 21 * (1)
3 = 12 * (2) + 21 * (-1)
НОД(12, 21) = 3, s = 2, t = -1
Press any key ...
a = 7 b = 19
7 = 7 * (1) + 19 * (0)
19 = 7 * (0) + 19 * (1)
7 = 7 * (1) + 19 * (0)
5 = 7 * (-2) + 19 * (1)
2 = 7 * (3) + 19 * (-1)
1 = 7 * (-8) + 19 * (3)
НОД(7, 19) = 1, s = -8, t = 3
Press any key ...
70
Окончание табл. 1.62
Пример исполнения расширенного алгоритма Евклида
7
8
a = 12 b = 31
12 = 12 * (1) + 31 * (0)
31 = 12 * (0) + 31 * (1)
12 = 12 * (1) + 31 * (0)
7 = 12 * (-2) + 31 * (1)
5 = 12 * (3) + 31 * (-1)
2 = 12 * (-5) + 31 * (2)
1 = 12 * (13) + 31 * (-5)
НОД(12, 31) = 1, s = 13, t = -5
Press any key ...
a = 15 b = 43
15 = 15 * (1) + 43 * (0)
43 = 15 * (0) + 43 * (1)
15 = 15 * (1) + 43 * (0)
13 = 15 * (-2) + 43 * (1)
2 = 15 * (3) + 43 * (-1)
1 = 15 * (-20) + 43 * (7)
НОД(15, 43) = 1, s = -20, t = 7
Press any key ...
Как видно из приведённых в таблице примеров 1 – 4 и 5 – 8, перестановка местами значений переменных a и b влечёт соответствующую перестановку местами значений ко­эффициентов Безу s и t.
Теперь можно решить исходную задачу по определению обратного элемента для числа a по модулю N, если такой элемент существует.
Сначала применим расширенный алгоритм Евклида к числам a и N и получим при этом такие числа d, s и t, что
d = НОД (a, N) = rn = a ∙ s + N ∙ t.
Следовательно, d (mod N) = a s + N t (mod N) = a s (mod N).
Заметим, что уравнение a x = 1 (mod N) имеет (единственное) решение тогда и только тогда, когда d = НОД (a, N) = 1. В этом случае корень x уравнения a x = 1 (mod N) является обратным элементом для числа a по модулю N. Из соотношений
d = НОД (a, N) = 1 = as (mod N)
и
ax = 1 (mod N)
следует, что a
–1
= x = s.
Таким образом, если НОД (a, N) = 1, то обратный элемент для числа a по модулю N равен коэффициенту s соотношения Безу НОД (a, N) = as + N t.
В качестве примера вычислим обратный элемент к a = 7 по модулю N = 19. Как видно из табл. 1.61, соотношение Безу для НОД (7, 19) = 1 = 7 ∙ (–8) + 19 ∙ 3, следовательно:
)19(mod7
1
=
)19(mod8
=
)19(mod198
=
)19(mod11
.
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]