HTML Diff
2 added 2 removed
Original 2026-01-01
Modified 2026-02-21
1 <p><strong>Об авторе</strong></p>
1 <p><strong>Об авторе</strong></p>
2 <p>Доктор Майкл Паунд - исследователь, работающий в Ноттингемском университете, специалист по компьютерной безопасности.</p>
2 <p>Доктор Майкл Паунд - исследователь, работающий в Ноттингемском университете, специалист по компьютерной безопасности.</p>
3 <p><strong>Переводчик</strong></p>
3 <p><strong>Переводчик</strong></p>
4 <p>Марина Демидова</p>
4 <p>Марина Демидова</p>
5 <p>В<a>видео</a>на YouTube-канале Numberphile Мэтт Паркер проверяет, может ли очень большое число быть простым.</p>
5 <p>В<a>видео</a>на YouTube-канале Numberphile Мэтт Паркер проверяет, может ли очень большое число быть простым.</p>
6 <p>В одном месте Мэтт приводит такое выражение:</p>
6 <p>В одном месте Мэтт приводит такое выражение:</p>
7 <p>23373 mod 747 - число 23 возводят в степень 373 и вычисляют результат по модулю 747.</p>
7 <p>23373 mod 747 - число 23 возводят в степень 373 и вычисляют результат по модулю 747.</p>
8 <p>Почему это меня заинтересовало? Дело в том, что подобные вычисления используются при шифровании данных с помощью алгоритма RSA с открытым ключом. Это могут быть, например, электронные подписи или шифрование в<a>S/MIME, TLS/SSL</a>и других приложениях.</p>
8 <p>Почему это меня заинтересовало? Дело в том, что подобные вычисления используются при шифровании данных с помощью алгоритма RSA с открытым ключом. Это могут быть, например, электронные подписи или шифрование в<a>S/MIME, TLS/SSL</a>и других приложениях.</p>
9 Мэтт Паркер<em>Кадр: Computerphile / YouTube</em><p>Этот материал - пересказ<a>видео</a>Майкла Паунда.</p>
9 Мэтт Паркер<em>Кадр: Computerphile / YouTube</em><p>Этот материал - пересказ<a>видео</a>Майкла Паунда.</p>
10 <p>Открытый ключ состоит из двух чисел {e, n}, где e - экспонента (простое число), а n - модуль (произведение двух простых чисел). Данные шифруются следующим образом:</p>
10 <p>Открытый ключ состоит из двух чисел {e, n}, где e - экспонента (простое число), а n - модуль (произведение двух простых чисел). Данные шифруются следующим образом:</p>
11 <p>E = xe mod n</p>
11 <p>E = xe mod n</p>
12 <p>Здесь x - исходное значение, а E - полученный шифр. Мы возводим число x в степень e и вычисляем результат по модулю n.</p>
12 <p>Здесь x - исходное значение, а E - полученный шифр. Мы возводим число x в степень e и вычисляем результат по модулю n.</p>
13 - <p>Вернёмся к задаче Паркера. Такое вычисление нельзя сделать на карманном калькуляторе, и в видео на Numberphile Мэттью использует программу<a>WolframAlpha</a>, что разумно - я и сам часто провожу вычисления именно в этой программе.</p>
13 + <p>Вернёмся к задаче Паркера. Такое вычисление нельзя сделать на карманном калькуляторе, и в видео на Numberphile Мэттью использует программу<a>WolframAlpha</a>, что разумно - я и сам часто провжу вычисления именно в этой программе.</p>
14 <em>Скриншот: Skillbox Media</em><p>Но мы попробуем применить алгоритм Square &amp; Multiply (возведения в квадрат и умножения). Его можно использовать даже при вычислениях с очень большими числами.</p>
14 <em>Скриншот: Skillbox Media</em><p>Но мы попробуем применить алгоритм Square &amp; Multiply (возведения в квадрат и умножения). Его можно использовать даже при вычислениях с очень большими числами.</p>
15 <p>Например, нам нужно рассчитать результат вычисления некоторого числа, возведённого в степень с показателем из 2000 бит, состоящего из 600 или более цифр, по модулю другого 2000-битного числа.</p>
15 <p>Например, нам нужно рассчитать результат вычисления некоторого числа, возведённого в степень с показателем из 2000 бит, состоящего из 600 или более цифр, по модулю другого 2000-битного числа.</p>
16 <p>Это невероятно большие числа, и если проводить вычисления последовательно: сначала возводить исходное значение в степень, а потом вычислять результат по модулю - то это потребует больших ресурсов процессора и займёт много времени. Но с помощью алгоритма Square &amp; Multiply время вычисления можно значительно сократить.</p>
16 <p>Это невероятно большие числа, и если проводить вычисления последовательно: сначала возводить исходное значение в степень, а потом вычислять результат по модулю - то это потребует больших ресурсов процессора и займёт много времени. Но с помощью алгоритма Square &amp; Multiply время вычисления можно значительно сократить.</p>
17 <p>Напомним, что вычисление по модулю означает, что 23373 нужно последовательно делить на 747, пока остаток не будет меньше 747 (напомню, это всё числа из задачи Паркера). В итоге такая операция похожа на часы.</p>
17 <p>Напомним, что вычисление по модулю означает, что 23373 нужно последовательно делить на 747, пока остаток не будет меньше 747 (напомню, это всё числа из задачи Паркера). В итоге такая операция похожа на часы.</p>
18 <em>Кадр: Computerphile / YouTube</em><p>Вы прокручиваете стрелки до 12, а потом опять начинаете с 1, 2, 3. Но в нашем случае делений на циферблате будет намного больше.</p>
18 <em>Кадр: Computerphile / YouTube</em><p>Вы прокручиваете стрелки до 12, а потом опять начинаете с 1, 2, 3. Но в нашем случае делений на циферблате будет намного больше.</p>
19 <em>Кадр: Computerphile / YouTube</em><p>Даже если не брать операцию с модулем, то возвести 23 в степень 373 очень сложно. Чтобы ускорить вычисление, применим алгоритм Square &amp; Multiply.</p>
19 <em>Кадр: Computerphile / YouTube</em><p>Даже если не брать операцию с модулем, то возвести 23 в степень 373 очень сложно. Чтобы ускорить вычисление, применим алгоритм Square &amp; Multiply.</p>
20 <p>Сначала рассмотрим его на простом примере - вычислим 28.</p>
20 <p>Сначала рассмотрим его на простом примере - вычислим 28.</p>
21 <p>Мы можем произвести семь операций умножения:</p>
21 <p>Мы можем произвести семь операций умножения:</p>
22 <p>2 × 2 × 2 × 2 × 2 × 2 × 2 × 2</p>
22 <p>2 × 2 × 2 × 2 × 2 × 2 × 2 × 2</p>
23 <p>Но можно пойти другим путём:</p>
23 <p>Но можно пойти другим путём:</p>
24 <p>2 × 2 = 22</p>
24 <p>2 × 2 = 22</p>
25 <p>(22) × (22) = 24</p>
25 <p>(22) × (22) = 24</p>
26 <p>(24) × (24) = 28</p>
26 <p>(24) × (24) = 28</p>
27 <p>Прекрасно - на выходе мы получили всего три операции умножения! Здесь мы возводим в квадрат не исходное число, а промежуточные значения.</p>
27 <p>Прекрасно - на выходе мы получили всего три операции умножения! Здесь мы возводим в квадрат не исходное число, а промежуточные значения.</p>
28 <p>Чтобы перейти к большим числам, рассмотрим механизм, который называется "квадрат слева направо".</p>
28 <p>Чтобы перейти к большим числам, рассмотрим механизм, который называется "квадрат слева направо".</p>
29 <p>Идея состоит в том, чтобы представить показатель степени в двоичном формате. Рассмотрим ещё один пример:</p>
29 <p>Идея состоит в том, чтобы представить показатель степени в двоичном формате. Рассмотрим ещё один пример:</p>
30 <p>345 mod 7</p>
30 <p>345 mod 7</p>
31 <p>Пример достаточно необычный. Сначала нужно вычислить огромное промежуточное значение 345, от которого в итоге по mod 7 получим маленькое число от 0 до 6.</p>
31 <p>Пример достаточно необычный. Сначала нужно вычислить огромное промежуточное значение 345, от которого в итоге по mod 7 получим маленькое число от 0 до 6.</p>
32 <p>Переведём показатель степени 45 в двоичную систему счисления:</p>
32 <p>Переведём показатель степени 45 в двоичную систему счисления:</p>
33 <p>101101</p>
33 <p>101101</p>
34 <p>Теперь нам нужно определить, чему равно 3101101.</p>
34 <p>Теперь нам нужно определить, чему равно 3101101.</p>
35 <p>Отвлечёмся от конкретных цифр и представим, что нам нужно возвести в квадрат y1 (показатель степени записан в двоичном формате).</p>
35 <p>Отвлечёмся от конкретных цифр и представим, что нам нужно возвести в квадрат y1 (показатель степени записан в двоичном формате).</p>
36 <p>Получим</p>
36 <p>Получим</p>
37 <p>(y1) × (y1) = y10 (1 + 1 = 10 в двоичной системе)</p>
37 <p>(y1) × (y1) = y10 (1 + 1 = 10 в двоичной системе)</p>
38 <p>Результат снова возведём в квадрат:</p>
38 <p>Результат снова возведём в квадрат:</p>
39 <p>(y10) × (y10) = y100 (10 + 10 = 100 в двоичной системе)</p>
39 <p>(y10) × (y10) = y100 (10 + 10 = 100 в двоичной системе)</p>
40 <p>Мы видим, что каждый раз, когда число возводится в квадрат, показатель степени сдвигается на один бит влево.</p>
40 <p>Мы видим, что каждый раз, когда число возводится в квадрат, показатель степени сдвигается на один бит влево.</p>
41 <p>Умножив результат на исходное число, получим</p>
41 <p>Умножив результат на исходное число, получим</p>
42 <p>(y100) × y = y101</p>
42 <p>(y100) × y = y101</p>
43 <p>Мы получили два правила:</p>
43 <p>Мы получили два правила:</p>
44 <ul><li>если число возводится в квадрат, к показателю степени слева "приписывается" 0;</li>
44 <ul><li>если число возводится в квадрат, к показателю степени слева "приписывается" 0;</li>
45 <li>если результат умножается на исходное число, к показателю степени прибавляется 1.</li>
45 <li>если результат умножается на исходное число, к показателю степени прибавляется 1.</li>
46 </ul><p>Используя эти правила, мы сможем воссоздать показатель степени 101101 за минимальное количество шагов. Цифры показателя будем получать слева.</p>
46 </ul><p>Используя эти правила, мы сможем воссоздать показатель степени 101101 за минимальное количество шагов. Цифры показателя будем получать слева.</p>
47 <p>Сбоку напишем код операции:</p>
47 <p>Сбоку напишем код операции:</p>
48 <ul><li>S (Square) - возведение в квадрат;</li>
48 <ul><li>S (Square) - возведение в квадрат;</li>
49 <li>M (Multiply) - умножение на исходное число.</li>
49 <li>M (Multiply) - умножение на исходное число.</li>
50 </ul>КодВ двоичном форматеВ десятичном форматеS31 × 31 = 31032S310 × 310 = 310034M3100 × 3 = 310135S3101 × 3101 = 31010310M31010 × 3 = 31011311S31011 × 31011 = 310110322S310110 × 310110 = 3101100344M3101100 × 3 = 3101101345<p>Чтобы посчитать остаток 345 mod 7, используем свойство оператора mod:</p>
50 </ul>КодВ двоичном форматеВ десятичном форматеS31 × 31 = 31032S310 × 310 = 310034M3100 × 3 = 310135S3101 × 3101 = 31010310M31010 × 3 = 31011311S31011 × 31011 = 310110322S310110 × 310110 = 3101100344M3101100 × 3 = 3101101345<p>Чтобы посчитать остаток 345 mod 7, используем свойство оператора mod:</p>
51 <p>(a × b) mod n = [(a mod n) × (b mod n)] mod n</p>
51 <p>(a × b) mod n = [(a mod n) × (b mod n)] mod n</p>
52 <p>Это означает, что мы можем не вычислять результат каждой операции S или M, а найти остатки по модулю каждого сомножителя, перемножить их и применить к произведению операцию mod.</p>
52 <p>Это означает, что мы можем не вычислять результат каждой операции S или M, а найти остатки по модулю каждого сомножителя, перемножить их и применить к произведению операцию mod.</p>
53 <p>В результате получим:</p>
53 <p>В результате получим:</p>
54 КодВ двоичном формате<strong>mod 7</strong>S31 × 31 = 3103 × 3 mod 7 = 2S310 × 310 = 31002 × 2 mod 7 = 4M3100 × 3 = 31014 × 3 mod 7 = 5S3101 × 3101 = 310105 × 5 mod 7 = 4M31010 × 3 = 310114 × 3 mod 7 = 5S31011 × 31011 = 3101105 × 5 mod 7 = 4S310110 × 310110 = 31011004 × 4 mod 7 = 2M3101100 × 3 = 31011012 × 3 mod 7 = 6<p>Используя алгоритм Square &amp; Multiply, мы легко посчитали, что 345 mod 7 = 6. Для этого нам не пришлось 45 раз перемножать тройки, чтобы вычислить огромное-огромное промежуточное число - 3 в 45-й степени. Это очень полезно для криптографии.</p>
54 КодВ двоичном формате<strong>mod 7</strong>S31 × 31 = 3103 × 3 mod 7 = 2S310 × 310 = 31002 × 2 mod 7 = 4M3100 × 3 = 31014 × 3 mod 7 = 5S3101 × 3101 = 310105 × 5 mod 7 = 4M31010 × 3 = 310114 × 3 mod 7 = 5S31011 × 31011 = 3101105 × 5 mod 7 = 4S310110 × 310110 = 31011004 × 4 mod 7 = 2M3101100 × 3 = 31011012 × 3 mod 7 = 6<p>Используя алгоритм Square &amp; Multiply, мы легко посчитали, что 345 mod 7 = 6. Для этого нам не пришлось 45 раз перемножать тройки, чтобы вычислить огромное-огромное промежуточное число - 3 в 45-й степени. Это очень полезно для криптографии.</p>
55 <em>Кадр: Computerphile / YouTube</em><p>Вернёмся к нашему первому примеру 23373 mod 747. Показатель степени 373 в двоичном формате будет равен 101110101. Это большое число, и мы не будем применять к нему весь алгоритм Square &amp; Multiply. Распишем коды операций возведения в квадрат и умножения.</p>
55 <em>Кадр: Computerphile / YouTube</em><p>Вернёмся к нашему первому примеру 23373 mod 747. Показатель степени 373 в двоичном формате будет равен 101110101. Это большое число, и мы не будем применять к нему весь алгоритм Square &amp; Multiply. Распишем коды операций возведения в квадрат и умножения.</p>
56 S10232S100234M101235S10102310M10112311S101102322M101112323S1011102346S10111002392M10111012393S1011101023186S10111010023372M10111010123373<p>Если расписать, как в предыдущем примере, все операции S и M и вычислить результаты по mod 747 (без калькулятора здесь не обойтись), то конечный результат будет равен 131.</p>
56 S10232S100234M101235S10102310M10112311S101102322M101112323S1011102346S10111002392M10111012393S1011101023186S10111010023372M10111010123373<p>Если расписать, как в предыдущем примере, все операции S и M и вычислить результаты по mod 747 (без калькулятора здесь не обойтись), то конечный результат будет равен 131.</p>
57 <p>Количество операций здесь - 13. Мы видим, что оно зависит от показателя степени. Для каждого нуля промежуточное значение возводится в квадрат, а для единицы - возводится в квадрат и умножается на исходное значение. Получается, чем больше единиц, тем больше операций.</p>
57 <p>Количество операций здесь - 13. Мы видим, что оно зависит от показателя степени. Для каждого нуля промежуточное значение возводится в квадрат, а для единицы - возводится в квадрат и умножается на исходное значение. Получается, чем больше единиц, тем больше операций.</p>
58 <p>Теперь рассмотрим простое число 65537. Его используют в качестве экспоненты в открытых ключах большинства сертификатов RSA. Например, когда сервер выдаёт вам сертификат, открытый ключ обычно состоит из числа 65537 и какого-то полупростого числа n.</p>
58 <p>Теперь рассмотрим простое число 65537. Его используют в качестве экспоненты в открытых ключах большинства сертификатов RSA. Например, когда сервер выдаёт вам сертификат, открытый ключ обычно состоит из числа 65537 и какого-то полупростого числа n.</p>
59 <p>Почему так? Дело в том, что 65537 - это число Ферма, которое можно представить как 216 + 1. В двоичной системе счисления оно равно:</p>
59 <p>Почему так? Дело в том, что 65537 - это число Ферма, которое можно представить как 216 + 1. В двоичной системе счисления оно равно:</p>
60 <p>100000000000000001 (две единицы, а между ними 16 нулей).</p>
60 <p>100000000000000001 (две единицы, а между ними 16 нулей).</p>
61 - <p>При проверке электронной подписи, помимо проверки заполнения и множества других веще, компьютер вычисляет какое-то сообщение, или его хеш, или его представление в таком виде:</p>
61 + <p>При проверке электронной подписи, помимо проверки заполнения и множества других вещей, компьютер вычисляет какое-то сообщение, или его хеш, или его представление в таком виде:</p>
62 <p>h(m)65537</p>
62 <p>h(m)65537</p>
63 <p>Вычисление будет выполняться достаточно быстро, так как в двоичном представлении числа 65537 почти нет единиц. Вычисляется множество квадратов, и только в конце производится одно умножение. Подобная проверка осуществляется каждый раз, когда вы заходите на веб-сайт.</p>
63 <p>Вычисление будет выполняться достаточно быстро, так как в двоичном представлении числа 65537 почти нет единиц. Вычисляется множество квадратов, и только в конце производится одно умножение. Подобная проверка осуществляется каждый раз, когда вы заходите на веб-сайт.</p>
64 <p>Но здесь я хочу добавить, что скорость проверки зависит не только от открытого, но и от закрытого ключа, который в RSA используется для расшифровки данных. А в нём количество нулей и единиц может быть каким угодно. Тем не менее использование числа 65537 в открытом ключе ускоряет вычисление и экономит ресурсы компьютеров.</p>
64 <p>Но здесь я хочу добавить, что скорость проверки зависит не только от открытого, но и от закрытого ключа, который в RSA используется для расшифровки данных. А в нём количество нулей и единиц может быть каким угодно. Тем не менее использование числа 65537 в открытом ключе ускоряет вычисление и экономит ресурсы компьютеров.</p>