Большие экспоненты и 8-битные процессоры PIC

Кто-нибудь знает, могут ли 8-битные (PIC) процессоры обычно обрабатывать большие экспоненты, например, 5^15 mod 23с разумной скоростью? Приводит ли это к большему количеству циклов, чем на 16-разрядных процессорах?

Я надеюсь реализовать обмен ключами Диффи-Хеллмана на одном из них, но мысль о вычислении больших экспонент кажется пугающей.

Обычно ли большие экспоненты выполняются на 8-битных процессорах? Обмен ключами DH обычно реализуется на таких недорогих устройствах?

Ну, я не могу комментировать точную проблему, которую вы описали, но я могу сказать, что однажды использовал язык JAL для 8-битных микропроцессоров PIC. Я настроил библиотеку, которая использовала математическую библиотеку с плавающей запятой (Vasile Surducan) для отображения цифр на ЖК-дисплее. Это работало, но математика была довольно медленной. Это, конечно, связано с гораздо большим количеством операций, необходимых для процессора RISC. В конце концов, если тактовую частоту можно поднять очень высоко, это может не иметь значения.
Я никогда не использовал его, но я считаю, что MPLAB X IDE имеет секундомер, который измеряет количество циклов между точками останова. Я считаю, что это в разделе «Окно> Отладка> Секундомер». Думаю можно это сделать с помощью симулятора (которым я тоже не пользовался).
У старого MPLAB был секундомер, как упоминает @Tut, поэтому я ожидаю, что MPLABX тоже. Хитрость в том, что это работало только в симуляторе MPLAB, а не при отладке на реальном оборудовании.
На самом деле коэффициенты намного больше, чем следует из данного примера. см. tools.ietf.org/html/rfc5114#page-4

Ответы (3)

Как отметил Crasic в комментариях, вам на самом деле не нужно вычислять фактическую экспоненту. Вы можете использовать модульную арифметику, чтобы уменьшить максимальное значение, которое вам нужно сохранить:

( а б )   мод   м "=" ( ( а   мод   м ) ( б   мод   м ) )   мод   м

Для ( а б )   мод   м , максимальное значение, которое вам когда-либо потребуется хранить, равно ( м 1 ) 2 , что m=23означает, что вы должны иметь возможность хранить 484. Это выходит за пределы диапазона 8-битных чисел, но подходит для 16-битных. Однако, как указал Олин, некоторые 8-битные микропроцессоры могут эффективно манипулировать 16-битными значениями, так что это не является большой проблемой.

Общая реализация на C может выглядеть так:

uint16_t exp_mod(uint16_t base, uint16_t power, uint16_t m)
{
    uint16_t res = 1;
    while(power)
    {
        if(power & 1)
        {
            res = (res * base) % m;
        }
        res = (res*res) % m;
        power >>= 1;
    }
    return  res;
}

Если ваш UC имеет эффективную инструкцию по модулю, этого обычно достаточно. Однако, если вы этого не сделаете и знаете, что n всегда будет определенным значением, существует эффективная реализация деления (и, следовательно, по модулю) Т. Гранлуна и П. Л. Монтомери . У Agner Fog также есть описание того, как это работает .

Вот взломанная реализация для m=23.

uint16_t mod23(uint16_t m)
{
    // note: I didn't actually figure out what n and the error correction term is suppose
    // to be, I just guessed a value for n which produces a simple function
    // only checked to be correct for m <= 484
    // 
    // n = 11
    uint16_t res = a - 23*((m*89)>>11);
    return (res == 23) ? 0 : res;
}

Единственными обязательными 16-битными операциями являются:

  • сложение/вычитание
  • умножение
  • побитовый сдвиг
  • побитовое и
  • сравнение равенства

Я не знаком с набором инструкций PIC, но вот примерное количество инструкций для наихудшего случая:

  • 4*log2(power)сравнения
  • 4*log2(power)прыжки
  • 2*log2(power)вычитания
  • 3*log2(power)побитовый сдвиг
  • 6*log2(power)умножения

Для power=15, это примерно 76 инструкций. Обратите внимание, что это может произойти, если у вас есть доступ к инструкциям множественного сложения или другим специальным инструкциям. Я бы счел это вполне разумным.

примечание: эта реализация имеет переменные тайминги для того, сколько времени занимает exp_mod в зависимости от входного параметра, поэтому она уязвима для взломов, основанных на тайминге (хотя для 16-битного ключа тоже можно просто взломать методом грубой силы). Относительно легко изменить этот код, чтобы он был устойчивым к этому, введя фиктивные инструкции, которые теоретически должны только повредить средней производительности, а производительность в худшем случае не изменится.

Любая математика может быть выполнена на любом процессоре. Вопрос только в том, сколько операций, а значит и сколько времени это займет.

5 15 = 2 34,8 , поэтому для выражения требуется не менее 35 бит. Биты приходят в байтах по 8 каждый на PIC 18, поэтому вы должны использовать 40 бит или 5 байтов для представления этого значения.

Итак, все, что вам нужно написать, это процедура, которая умножает 1-байтовое число на 5-байтовое число в 5-байтовое число. На самом деле это довольно просто, так как PIC 18 имеет аппаратный множитель 8x8 в 16 бит. По сути, вы умножаете один входной байт на каждый из широких числовых байтов отдельно и суммируете результаты. Я бы, вероятно, написал это как развернутый цикл, поэтому кишки будут состоять из 5 наборов умножения и двух сложений или 15 инструкций.

Добавлен

Как правильно указал Дэн Д. в комментарии, я забыл обратиться к модульной части. Это значительно сложнее, чем вычисление 5 15 . По сути, вы делите на 23 и оставляете только остаток. Вы можете сохранить несколько инструкций, потому что вам не нужно частное в конце, но в основном вам все равно придется писать 5-байтовый алгоритм, разделенный на 1-байтовый с 1-байтовым остатком.

Опять же, все это можно сделать на PIC 18 или других небольших процессорах, но потребуется гораздо больше инструкций, чем на процессоре, который изначально может манипулировать 40-битными числами.

Вы, кажется, пропустили, что это было модульное возведение в степень . Данный пример можно быстро выполнить с помощью одиночных байтов с модульным возведением в степень путем возведения в квадрат. 5^15 mod 23только 19.
@Dan: см. дополнение к ответу.
Возможно, можно найти вдохновение в библиотеке GMP, в которой есть код для выполнения таких вычислений с целыми числами произвольной длины, хранящимися в полубайтах (4-битных объектах).
@OlinLathrop Спасибо. Но если бы это был PIC 16, к сожалению, в ALU не было бы аппаратного аппаратного умножителя 8x8, поэтому я считаю, что умножение будет более сложным. Стоит ли писать выражение на C как есть и позволить MPLAC XC8 сделать всю работу?
Модульные показатели легко вычисляются с использованием результатов старой теории чисел. Не требует фактического вычисления большого экспоненциального значения
Старый школьный способ использует модульную арифметику, чтобы переписать выражение в произведение 5, возведенных в простые степени по модулю 23. К ним применяется маленькая теорема Ферма, и вам нужно только взять мод небольшого числа. Существует также несколько алгоритмов эффективного использования памяти для этой операции на цифровых компьютерах, которые были тщательно исследованы.

Отказ от ответственности: если вы хотите сделать это в образовательных целях, продолжайте. Если вы хотите использовать его для реальной защиты связи, возьмите копию «Руководства по прикладной криптографии».

Как уже говорилось, проблема не в возведении в степень, а в операции по модулю (если делать это наивно). Умножение Монтгомери — эффективный способ решить эту проблему. Короче говоря, проблема сопоставляется с другой группой, которая обладает тем свойством, что операция по модулю может быть заменена сдвигом битов (и/или копированием памяти).

Я не знаю о реализации DH на 8-битных чипах, но точно знаю, что есть реализации RSA для 8-битных микропроцессоров.

Настройка вещей таким образом, чтобы два самых значащих байта модуля были равны 1 и 0, очень поможет, но, к сожалению, использование операнда в инструкциях умножения не особенно подходит для эффективного расширенного умножения. Если бы у PIC был регистр «фактор» (который мог хранить свое значение между умножениями) и инструкция, которая вычисляла бы PRODH+FACTOR*op -> PRODH:W, это позволило бы сократить основной цикл длинного умножения до две однотактные инструкции: "XMULA POSTINC0,c / ADDWFC POSTINC1,f,c"