RSA-KEM

RSA-KEM (RSA Key Encapsulation Method) — однопроходный (store-and-forward) механизм шифрования ключа для передачи в криптосистемах с открытым ключом. Сочетает в себе ложные перестановки RSA и KDF (Key Derivation Function). Обладает простотой и превосходными защитными свойствами, по сравнению с OAEP или OAEP+.[источник не указан 3321 день] Основной недостаток состоит в том, что шифротекст немного больше исходного текста.

Описание

Введение

RSA-KEM относится к классу криптографических методов инкапсуляции ключа, спроектированных для безопасной отправки симметричных ключей шифрования с использованием алгоритмов на открытых ключах[1]. На практике, системы шифрования на основе открытых ключей неудобны для передачи длинных сообщений, вместо этого они используются для обмена симметричными ключами, которыми в итоге шифруется текст. Традиционным подходом к отправке симметричного ключа с помощью систем на открытых ключах является следующий алгоритм:

  1. Генерация случайного числа.
  2. Шифрование числа выбранным открытым ключом. Это зашифрованное сообщение отправляется получателю.
  3. Получатель расшифровывает его закрытым ключом и восстанавливает симметричный ключ.

Представленный алгоритм имеет несколько недостатков[2]. Во-первых, так как симметричный ключ мал, требуется его удлинение, а доказательство безопасности удлинения ключа не является строгим. Во-вторых, злоумышленник может отправить своё число, зашифрованное открытым ключом, и обмениваться сообщениями с получателем. В-третьих, не отслеживается целостность данных (обобщение второго пункта). Кроме того, шифры схожих сообщений могут быть похожими. Очевидно, что представленная схема недостаточно хороша и надёжна.

Метод инкапсуляции ключа демонстрирует иной, более продвинутый подход, решающий выявленные проблемы.

Процесс шифрования можно коротко представить следующим образом:

  1. Генерируется случайное входное w.
  2. Шифруется w с использованием RSA для передачи принимающему.
  3. Генерируется материал ключа y = KDF(w) для использования в последующем шифровании.

Принимающий может восстановить w из принятого шифртекста и затем сгенерировать y, чтоб и отправитель и принимающий могли согласиться с одинаковым симметричным ключом.

Параметры

Механизм шифрования ключа имеет следующие системные параметры:

  1. RSAKeyGen: алгоритм генерации ключа RSA.
  2. KDF: A key derivation function.
  3. KeyLen: положительное целое число.

Генерация ключа

Открытый ключ состоит из RSA коэффициента n {\displaystyle n} , который является произведением двух больших простых чисел и экспоненты e {\displaystyle e} , где g c d ( e , ϕ ( n ) ) = 1 {\displaystyle gcd(e,\phi (n))=1} ( g c d {\displaystyle gcd}  — наибольший общий делитель)[3]. Это так же выделяет key derivation function KDF. Пусть nLen обозначает длину n в байтах. Секретный ключ состоит из дешифровой экспоненты d, где e d = 1 m o d ϕ ( n ) {\displaystyle ed=1mod\phi (n)} . Алгоритм генерации ключа ничего не принимает на вход и выполняется следующим образом:

  1. Вычисление (n, e, d) = RSAKeyGen().
  2. Получение открытого ключа PK (public key).
  3. Получение закрытого ключа pk (private key).

n, e, d — целые положительные числа.

Шифрование

Целью алгоритма шифрования является произвести псевдослучайный ключ K длины KeyLen и шифротекст C 0 {\displaystyle C_{0}} , который шифрует K. Алгоритм шифрования принимает следующее:

  1. открытый ключ, состоящий из целого положительного n и e.
  2. нет опций шифрования.

Выполняется следующим образом[2]:

1) Генерируется случайное число z [ 0.. n ) {\displaystyle z\in [0..n)} .

2) Шифруется z {\displaystyle z} открытым ключом получателя ( n , e ) {\displaystyle (n,e)}

c = z e m o d n {\displaystyle c=z^{e}modn}

3) Число c {\displaystyle c} преобразуется в шифрованную строку C {\displaystyle C} , а z {\displaystyle z} в строчку Z {\displaystyle Z}

C = i n t T o S t r ( c , n L e n ) , {\displaystyle C=intToStr(c,nLen),}
Z = i n t T o S t r ( z , n L e n ) {\displaystyle Z=intToStr(z,nLen)}

4) Создаётся так называемый key-encrypting key(KEK), длиной k e k L e n {\displaystyle kekLen} , с использованием Key Derivation Function(KDF):

K E K = K D F ( z , k e k L e n ) {\displaystyle KEK=KDF(z,kekLen)}

5) Передаваемая информация оборачивается (в англ. литературе WRAP) ключом KEK, с использованием key-wrapping схемы. На выходе получим шифорованный текст W K {\displaystyle WK}

W K = W r a p ( K E K , K ) {\displaystyle WK=Wrap(KEK,K)}

6) Объединяем C {\displaystyle C} и зашифрованный текст

E K = C | | W K {\displaystyle EK=C||WK}

E K {\displaystyle EK} является выходом алгоритма

Функция производства ключа (KDF)

KDF принимает на вход байтовую строчку и целое число L > 0 {\displaystyle L>0} . Например, функция KDF1. Она параметризуется некоторой хеш функцией и определяется следующим образом[2]: на вход идут аргументы ( Z , L ) {\displaystyle (Z,L)} , на выходе получаем первые L {\displaystyle L} байт выражения:

H a s h ( Z {\displaystyle Hash(Z} || I 2 O S P ( 0 , 4 ) ) {\displaystyle I2OSP(0,4))} || ... || H a s h {\displaystyle Hash} ( Z {\displaystyle (Z} || I 2 O S P ( k 1 , {\displaystyle I2OSP(k-1,} 4 ) ) , {\displaystyle 4)),}
где k = L / H a s h . o u t p u t L e n . {\displaystyle k=L/Hash.outputLen.}

"Близнецом" функции KDF1 является KDF2. Она отличается от KDF1 лишь тем, что счётчик проходит от 1 {\displaystyle 1} до k {\displaystyle k} , а не от 0 {\displaystyle 0} до k 1 {\displaystyle k-1} . Однако для этих функций трудно установить, насколько "хорошими" генераторами псевдослучайных чисел они являются. В связи с этой потенциальной уязвимостью желательно использовать функцию KDF3, например. Она принимает в качестве параметров Hash и p a d d i n g 4. {\displaystyle padding\geqslant 4.} На выход идут первые L {\displaystyle L} байт выражения:

H a s h ( I 2 O S P ( 0 , p a d d i n g ) {\displaystyle Hash(I2OSP(0,padding)} || Z ) {\displaystyle Z)} || · · · || H a s h ( I 2 O S P ( k 1 {\displaystyle Hash(I2OSP(k-1} , p a d d i n g ) {\displaystyle padding)} || Z ) , {\displaystyle Z),}
где k = L / H a s h . o u t p u t L e n {\displaystyle k=L/Hash.outputLen} .

Рекомендуемые хеш-функции SHA1 и RIPMD-160. Рекомендуемый p a d d i n g = 4 {\displaystyle padding=4} . О надёжности KDF3 уже можно судить достаточно уверенно. Функция I 2 O S P {\displaystyle I2OSP} описанная в стандарте IEEE P1363, преобразует число в строку. Её работа основана на функции O S 2 I P {\displaystyle OS2IP} , которая наоборот, из строки получает число.

Схема обертки ключа (Key Wrapping Schema)

Спецификация RFC 5990 требует, чтобы в качестве схемы обертки использовалась одна из следующих:

  1. AES Key Wrap
  2. Triple-DES Key Wrap
  3. Camillia Key Wrap

Наиболее распространена схема обертки AES[4]. Она оперирует блоками по 64 бита и требует на вход сообщение длиной более одного такого блока. Если длина сообщения 64бита или меньше, постоянная определённая спецификацией и ключевая информация формируют единственный 128-битный блок, обертывание которого бессмысленно.

Дешифрование

Алгоритм дешифрования принимает на вход следующее:

  1. закрытый ключ, состоящий из целого положительного n и d.
  2. шифротекст C 0 {\displaystyle C_{0}} .

Выполняется следующим образом:

  1. Разделение зашифрованной информации о ключе E K {\displaystyle EK} на шифротекст C {\displaystyle C} длины n L e n {\displaystyle nLen} байт и обернутую информацию о ключе:

    C | | W K = E K {\displaystyle C||WK=EK}

    Если длина зашифрованной информации о ключе отличается от n L e n {\displaystyle nLen} , то дешифрование прекращается с ошибкой.
  2. Преобразование шифротекста C {\displaystyle C} в целое число c {\displaystyle c} и его расшифровка с использованием закрытого ключа принимающего:

    c = S t r T o I n t ( C ) {\displaystyle c=StrToInt(C)}
    z = c d m o d n {\displaystyle z=c^{d}modn}

    Если c {\displaystyle c} не находится в пределах 0 c n 1 {\displaystyle 0\leqslant c\leqslant n-1} , то дешифрование прекращается с ошибкой.
  3. Преобразование целого z {\displaystyle z} в байтовую строку Z {\displaystyle Z} длины n L e n . {\displaystyle nLen.}

    Z = I n t T o S t r ( z , n L e n ) {\displaystyle Z=IntToStr(z,nLen)}

  4. Создание K E K {\displaystyle KEK} длины k e k L e n {\displaystyle kekLen} байт из строки Z {\displaystyle Z} при помощи KDF:

    K E K = K D F ( Z , k e k L e n ) {\displaystyle KEK=KDF(Z,kekLen)}

  5. Разворачивание информации о ключе W K {\displaystyle WK} при помощи K E K {\displaystyle KEK} :

    K = U n w r a p ( K E K , W K ) {\displaystyle K=Unwrap(KEK,WK)}

    Если операция разворачивания прекращается с ошибкой, выполнение всего алгоритма прекращается с ошибкой.
  6. Получение K {\displaystyle K} на выходе алгоритма.

Оценка надёжности

Безопасность RSA-KEM может быть проанализирована в модели случайного оракула (Random Oracle Model, далее RO)[2]. Суть модели состоит в следующем. Предположим, что существует некая общедоступная функция обладающая такими свойствами:

  1. На каждый новый аргумент функция отвечает новым значением и записывает пару (аргумент, значение) в таблицу.
  2. Если аргумент уже встречался, то функция обратится к своей таблице и вернёт значение, соответствующее этому аргументу.

Доказательство основано на предположении, что KDF является случайным оракулом, и что решение обратной задачи RSA невозможно (проще говоря, RSA нельзя взломать). Для любого алгоритма генерации ключа для RSA (то есть алгоритма, возвращающего n, e и d), всегда выполнено n >= nBound (то есть nBound наименьшая допустимая граница для чисел n), и для каждого злоумышленника A справедливо:

A d v a n t a g e R S A K E M ( A ) A d v a n t a g e R S A ( A ) {\displaystyle Advantage_{RSA-KEM}(A)\leq Advantage_{RSA}(A')} + q D / n B o u n d ( ) , {\displaystyle qD/nBound(*),}

где q D {\displaystyle qD} — это максимальное число запросов к оракулу, которое может сделать злоумышленник для попытки разгадать шифр A {\displaystyle A} , AdvantageRSA-KEM(A) = |Pr[b*-b] - 1/2| — предсказательная способность А, AdvantageRSA(A') обозначает вероятность успешного решения инверсной задачи RSA. Нужно заметить, что приведённое выше неравенство не учитывает тот факт, что в реальности R S A K e y G e n {\displaystyle RSAKeyGen} с ненулевой вероятностью возвращает «плохие» ключи. Чтобы учесть его, требуется лишь прибавить эту вероятность к правой части неравенства.

Приведём доказательство, рассматривая последовательность игр G i {\displaystyle G_{i}} , и в каждой игре противник A проводит атаку. Каждая из этих игр проходит в одном вероятностном пространстве — меняются только правила того, как рассчитываются случайные величины. В каждой игре будет событие S i {\displaystyle S_{i}} , связанное с событием S 0 {\displaystyle S_{0}} . Докажем, что разность | P r [ S i ] P r [ S i 1 ] | {\displaystyle |Pr[S_{i}]-Pr[S_{i-1}]|} мала, и, более того, она будет свидетельствовать о том что в последней игре P r [ S k ] = 1 / 2 {\displaystyle Pr[S_{k}]=1/2} . Пусть G 0 {\displaystyle G0} — первая игра, S 0 {\displaystyle S0} — событие, обозначающее что A {\displaystyle A} правильно угадывает бит b {\displaystyle b} в игре G 0 {\displaystyle G0} . Пусть H {\displaystyle H} обозначает случайное предсказание оракула, размещающее элементы Z n {\displaystyle Z_{n}} в битовые строчки длины k e y L e n {\displaystyle keyLen} в свою таблицу. Пусть y Z n {\displaystyle y^{*}\in Z_{n}} — атакуемый шифротекст, и r = ( y ) 1 / e Z n {\displaystyle r^{*}=(y^{*})^{1/e}\in Z_{n}} . Далее мы определим следующую игру G 1 {\displaystyle G1} , точно такую же как игру G 0 {\displaystyle G0} . Если окажется так, что оракул был вызван для дешифрования с аргументом y {\displaystyle y^{*}} раньше, и вызов был успешным, то игра останавливается. Пусть S 1 {\displaystyle S1} — событие в игре G 1 {\displaystyle G1} , соответствующее событию S 0 {\displaystyle S0} . Пусть F 1 {\displaystyle F1}  — событие, сигнализирующее о том, что игра G 1 {\displaystyle G1} была остановлена. Понятно, что

P r [ F 1 ] q D / n B o u n d , {\displaystyle Pr[F1]\leq qD/nBound,}

и в промежуток времени, когда игры G 0 {\displaystyle G0} и G 1 {\displaystyle G1} проходят одинаково, а именно, до того момента как случается F 1 {\displaystyle F1} , выполняется следующая лемма:

Пусть E , E {\displaystyle E,E'} и F {\displaystyle F} — события, определённые на пространстве случайных событий таким образом, что

P r [ E {\displaystyle Pr[E} {\displaystyle \land } ¬ {\displaystyle \neg } F ] = P r [ E {\displaystyle F]=Pr[E'} {\displaystyle \land } ¬ {\displaystyle \neg } F ] {\displaystyle F]}

Тогда выполняется:

| P r [ E ] {\displaystyle |Pr[E]} P r [ {\displaystyle -Pr[} E ] | {\displaystyle E']|} P r [ F ] . {\displaystyle \leq Pr[F].}

В нашем случае | P r [ S 0 ] {\displaystyle |Pr[S0]} P r [ S 1 ] | {\displaystyle -Pr[S1]|} {\displaystyle \leq } q D / n B o u n d . {\displaystyle qD/nBound.} Далее определим игру G 2 {\displaystyle G2} , такую же как G 1 {\displaystyle G1} , за исключением того, что атакуемый шифротекст генерируется в начале игры, и если противник запрашивает H {\displaystyle H} для r {\displaystyle r^{*}} , игра останавливается. Пусть S 2 {\displaystyle S2} &mdash событие в G 2 {\displaystyle G2} , соответствующее событию S 0 {\displaystyle S0} . Очевидно, что

P r [ S 2 ] = 1 / 2 {\displaystyle Pr[S2]=1/2}

в силу того, что ключ H ( r ) {\displaystyle H(r^{*})} независим от чего-либо, доступного противнику в игре G 2 {\displaystyle G2} . В этой игре H {\displaystyle H} в r {\displaystyle r^{*}} вызывается только с целью шифрования.

Пусть F 2 {\displaystyle F2} — событие, сигнализирующее о том, что предыдущая игра прервалась. Понятно, что игры G 1 {\displaystyle G1} и G 2 {\displaystyle G2} протекают одинаково до тех пор, пока не случится F 2 {\displaystyle F2} , и, следовательно, по лемме мы получим:

| P r [ S 1 ] P r [ S 2 ] | {\displaystyle |Pr[S1]-Pr[S2]|} P r [ F 2 ] {\displaystyle \leq Pr[F2]}

Потребуем, чтобы P r [ F 2 ] A d v a n t a g e R S A ( A ) {\displaystyle Pr[F2]\leq Advantage_{RSA}(A')} для алгоритма A', время работы которого ограничено временем, описанным выше. Тогда неравенство (*) будет выполнено. Алгоритм А' запускается следующим образом. Он получает на вход случайный RSA модуль n {\displaystyle n} , RSA экспоненту e {\displaystyle e} и случайный элемент y Z n {\displaystyle y*\leq Zn} . A' создаёт открытый ключ, используя n {\displaystyle n} и e {\displaystyle e} , а затем разрешает противнику A начать игру. Когда А вызывает оракул для шифрования, А' отвечает А парой ( K , y ) {\displaystyle (K^{*},y^{*})} , где K {\displaystyle K^{*}} — случайный бит строки длиной k e y L e n {\displaystyle keyLen} , а y {\displaystyle y^{*}} подаётся на вход A. Алгоритм A' симулирует случайное предсказание H {\displaystyle H} , как и дешифрующее RO, следующим образом. Для каждого входного r Z n {\displaystyle r\leq Z_{n}} для случайного предсказания A' вычисляет y = r e Z n {\displaystyle y=r^{e}\in Z_{n}} , и размещает r {\displaystyle r} , y {\displaystyle y} и случайное значение K = H ( r ) {\displaystyle K=H(r)} в таблицу. Однако, если y = y {\displaystyle y=y^{*}} А' вместо того выводит r {\displaystyle r} и завершается. Когда противник A предоставляет шифротекст y Z n {\displaystyle y\in Z_{n}} дешифрующему предсказанию, А' ищет значение y {\displaystyle y} в описанной таблице, чтобы определить было ли вычислено значение случайного предсказания при r = y ( 1 / e ) Z n {\displaystyle r=y^{(1/e)}\in Z_{n}} . Если да, то А' отвечает дешифрующему предсказанию значением K = H ( r ) {\displaystyle K=H(r)} , хранящемся в таблице. Иначе, алгоритм создаёт новый случайный ключ K {\displaystyle K} , и размещает пару ( y , K ) {\displaystyle (y,K)} во второй таблице. Более того, если в будущем противник А должен будет вычислить случайное предсказание при r Z n {\displaystyle r\leq Z_{n}} таком что r e = y {\displaystyle r^{e}=y} , то ключ K {\displaystyle K} , сгенерированный выше, будет использован как значение H ( r ) {\displaystyle H(r)} . Понятно, что A' отлично симулирует А, и даёт на выходе решение для данного случая RSA с вероятностью P r [ F 2 ] {\displaystyle Pr[F2]} . Это и доказывает безопасность алгоритма. Количественно можно проверить, что RSA-KEM обеспечивает лучшую защиту по сравнению с RSA-OAEP+ и RSA-OAEP. Это преимущество выражается тем более, чем больше число сообщений, зашифрованных одним открытым ключом (замоделировано в BBM00). Это можно показать воспользовавшись тем, что решение инверсионной задачи RSA является очень трудозатратным. Таким образом безопасность RSA-KEM совсем не уменьшается с возрастанием числа зашифрованных текстов. Нужно заметить, что это утверждение справедливо только если число r в алгоритме шифрования для Simple RSA выбрано равномерно по модулю n, либо, как минимум, его распределение должно быть неотличимо от равномерного с точки зрения вычислений. Кроме прочего, RSA-KEM, в отличие от RSA-OAEP or RSA-OAEP+, нельзя назвать «хрупким» алгоритмом, то есть не найдены возможности для атак на его реализации.

Примечания

  1. Use of the RSA-KEM Key Transport Algorithm
  2. 1 2 3 4 V. Shoup. A Proposal for an ISO Standard for Public Key Encryption
  3. FCD 18033-2 Encryption algorithms — Part 2: Asymmetric ciphers
  4. AES Key Wrap Specification

Ссылки

  • V. Shoup. A Proposal for an ISO Standard for Public Key Encryption. Preprint, December 2001. Архивная копия от 5 июля 2008 на Wayback Machine
  • FCD 18033-2 Encryption algorithms — Part 2: Asymmetric ciphers. Архивная копия от 24 декабря 2010 на Wayback Machine
  • Securing RSA-KEM via the AES (недоступная ссылка)
  • RSA Algorithm Архивная копия от 22 ноября 2010 на Wayback Machine
  • The Random Oracle Methodology Архивная копия от 3 марта 2016 на Wayback Machine
  • Use of the RSA-KEM Key Transport Algorithm Архивная копия от 26 октября 2014 на Wayback Machine
  • AES Key Wrap Specification Архивная копия от 17 сентября 2008 на Wayback Machine