Разделение секрета Шамира (SSS) — это эффективный алгоритм разделения секрета для распространения частной информации («секрета») среди группы. Секрет не может быть раскрыт, если кворум группы не объединит свои знания. Чтобы достичь этого, секрет математически делится на части («доли»), из которых секрет может быть собран заново только при объединении достаточного количества долей. SSS обладает свойством информационно-теоретической безопасности , что означает, что даже если злоумышленник украдет несколько долей, злоумышленник не сможет восстановить секрет, если он не украл количество долей кворума.
Разделение секрета Шамира используется в некоторых приложениях для совместного использования ключей доступа к главному секрету.
SSS используется для защиты секрета в распределенной форме, чаще всего для защиты ключей шифрования . Секрет делится на несколько частей, которые по отдельности не дают никакой информации о секрете.
Для восстановления секрета, защищенного SSS, необходимо некоторое количество акций, называемое порогом . Никакая информация о секрете не может быть получена из любого количества акций ниже порога (свойство, называемое совершенной секретностью ). В этом смысле SSS является обобщением одноразового блокнота (который можно рассматривать как SSS с порогом в два куска и двумя кусками в общей сложности). [1]
Компании необходимо защитить свое хранилище. Если код хранилища знает только один человек, код может быть утерян или недоступен, когда хранилище нужно будет открыть. Если код знают несколько человек, они могут не доверять друг другу и не всегда действовать честно.
В этой ситуации SSS может использоваться для генерации акций кода хранилища, которые распределяются среди уполномоченных лиц в компании. Минимальный порог и количество акций, предоставляемых каждому лицу, могут быть выбраны таким образом, чтобы хранилище было доступно только (группам) уполномоченных лиц. Если представлено меньше акций, чем порог, хранилище не может быть открыто.
Случайно, по принуждению или в качестве акта противодействия некоторые лица могут предоставить неверную информацию для своих акций. Если общее количество правильных акций не достигает минимального порога, хранилище остается заблокированным.
Секретный обмен Шамира можно использовать для
SSS имеет полезные свойства, но также и недостатки [5] , которые означают, что он непригоден для некоторых видов использования.
Полезные свойства включают в себя:
К слабым сторонам относятся:
Ади Шамир , израильский ученый, впервые сформулировал эту схему в 1979 году. [6]
Схема использует теорему интерполяции Лагранжа , в частности, что точки на многочлене однозначно определяют многочлен степени , меньшей или равной . Например, 2 точек достаточно для определения прямой , 3 точек достаточно для определения параболы , 4 точек достаточно для определения кубической кривой и т. д.
Разделение секрета Шамира — это идеальная и совершенная пороговая схема , основанная на полиномиальной интерполяции по конечным полям . В такой схеме цель состоит в том, чтобы разделить секрет (например, комбинацию к сейфу ) на части данных (известные как доли ) таким образом, чтобы:
Если , то для восстановления секрета необходимы все доли .
Предположим, что секрет может быть представлен как элемент конечного поля ( где больше, чем число генерируемых акций). Случайным образом выбираем элементы, , из и строим многочлен . Вычисляем любые точки на кривой, например, устанавливаем для поиска точек . Каждому участнику дана точка (ненулевой вход для многочлена и соответствующий выход). [7] Учитывая любое подмножество этих пар, можно получить с помощью интерполяции , причем одной из возможных формул для этого является , где список точек многочлена задан как пары вида . Обратите внимание, что равно первому коэффициенту многочлена .
Следующий пример иллюстрирует основную идею. Обратите внимание, однако, что вычисления в примере производятся с использованием целочисленной арифметики, а не арифметики конечных полей, чтобы сделать идею более понятной. Поэтому пример ниже не обеспечивает идеальной секретности и не является надлежащим примером схемы Шамира. Следующий пример объяснит проблему.
Предположим, что секрет, которым нужно поделиться, — 1234 .
В этом примере секрет будет разделен на 6 частей , где любой поднабор из 3 частей достаточен для восстановления секрета. числа берутся случайным образом. Пусть это будут 166 и 94.
Таким образом, полином для получения секретных долей (точек) имеет вид:
Шесть точек из полинома строятся как:
Каждый участник схемы получает разную точку (пару и ). Поскольку вместо точек начинаются с и не используется . Это необходимо, поскольку это секрет.
Для того, чтобы восстановить секрет, достаточно любых 3 точек.
Рассмотрите возможность использования 3-х точек .
Вычисление базисных полиномов Лагранжа :
Используя формулу полиномиальной интерполяции, получим:
Напоминая, что секрет — это свободный коэффициент, а это значит, что , и секрет восстановлен.
Использование полиномиальной интерполяции для нахождения коэффициента в исходном полиноме с использованием полиномов Лагранжа неэффективно , поскольку вычисляются неиспользуемые константы.
Учитывая это, оптимизированная формула для использования полиномов Лагранжа для нахождения определяется следующим образом:
Хотя упрощенная версия метода, продемонстрированная выше, которая использует целочисленную арифметику вместо арифметики конечных полей, работает, существует проблема безопасности: Ева получает информацию о каждом найденном элементе.
Предположим, что она находит 2 точки и . У нее по-прежнему нет точек, поэтому теоретически она не должна была получить больше информации о . Но она могла бы объединить информацию из 2 точек с общедоступной информацией: . Сделав это, Ева могла бы выполнить следующую алгебру:
Вышеуказанная атака использует ограничения на значения, которые может принимать полином в силу того, как он был построен: полином должен иметь коэффициенты, являющиеся целыми числами, и полином должен принимать целое число в качестве значения при оценке в каждой из координат, используемых в схеме. Это уменьшает его возможные значения в неизвестных точках, включая результирующий секрет, учитывая меньше, чем акций.
Эту проблему можно решить, используя арифметику конечного поля. Конечное поле всегда имеет размер , где — простое число, а — положительное целое число. Размер поля должен удовлетворять , и это больше, чем количество возможных значений секрета, хотя последнее условие можно обойти, разделив секрет на меньшие секретные значения и применив схему к каждому из них. В нашем примере ниже мы используем простое поле (т. е. r = 1). На рисунке показана полиномиальная кривая над конечным полем.
На практике это лишь небольшое изменение. Порядок q поля (т. е. количество значений, которые оно имеет) должен быть выбран больше, чем количество участников и количество значений, которые может принимать секрет. Все вычисления, включающие полином, также должны быть вычислены над полем (mod p в нашем примере, где берется как простое число), а не над целыми числами. Как выбор поля, так и отображение секрета на значение в этом поле считаются публично известными.
Для этого примера выберите , тогда многочлен примет вид , который дает точки:
На этот раз Ева не получает никакой информации, когда находит (пока у нее нет очков).
Предположим снова, что Ева находит и , а общедоступная информация: . Пытаясь выполнить предыдущую атаку, Ева может:
Существуют возможные значения для . Она знает, что всегда уменьшается на 3, поэтому если делится на , она могла бы заключить . Однако является простым числом, поэтому она не может заключить это. Таким образом, использование конечного поля позволяет избежать этой возможной атаки.
Кроме того, хотя Ева может заключить, что , это не дает никакой дополнительной информации, поскольку «циклическое» поведение модульной арифметики предотвращает утечку «S четно», в отличие от примера с целочисленной арифметикой выше.
Для большей ясности кода здесь используется простое поле. На практике для удобства схема, построенная с использованием меньшего двоичного поля, может быть отдельно применена к небольшим подстрокам битов секрета (например, GF(256) для побайтового применения) без потери безопасности. Строгое условие, что размер поля должен быть больше количества акций, все равно должно соблюдаться (например, если количество акций может превысить 255, поле GF(256) может быть заменено, скажем, на GF(65536)).
""" Следующая реализация Python для разделения секрета Шамира передается в общественное достояние на условиях CC0 и OWFa: https://creativecommons.org/publicdomain/zero/1.0/ http://www.openwebfoundation.org/legal/the-owf-1-0-agreements/owfa-1-0См. несколько нижних строк для использования. Протестировано на Python 2 и 3. """из __future__ импортировать подразделение из __future__ импортировать функцию_печатиимпорт случайный импорт functools# 12-й Мерсенн Прайм _PRIME = 2 ** 127 - 1_RINT = functools.partial ( random.SystemRandom ( ) . randint , 0 ) def _eval_at ( poly , x , prime ): """Оценивает полином (кортеж коэффициентов) при x, используемый для генерации пула Шамира в make_random_shares ниже. """ accum = 0 для coeff в reversed ( poly ): accum *= x accum += coeff accum %= prime return accum def make_random_shares ( secret , minimum , shares , prime = _PRIME ): """ Генерирует случайный пул Шамира для заданного секрета, возвращает баллы шар. """ если минимум > шар : raise ValueError ( "Секрет пула будет невосстановим." ) poly = [ secret ] + [ _RINT ( prime - 1 ) for i in range ( minimum - 1 )] points = [( i , _eval_at ( poly , i , prime )) for i in range ( 1 , shares + 1 )] return баллы def _extended_gcd ( a , b ): """ Деление целых чисел по модулю p означает нахождение обратной величины знаменателя по модулю p и последующее умножение числителя на эту обратную величину (Примечание: обратная величина для A — это B, такая что A*B % p == 1). Это можно вычислить с помощью расширенного алгоритма Евклида http://en.wikipedia.org/wiki/Shamir%27s_Secret_Sharing/Modular_multiplicative_inverse#Computation """ x = 0 last_x = 1 y = 1 last_y = 0 while b != 0 : quot = a // b a , b = b , a % b x , last_x = last_x - quot * x , x y , last_y = last_y - quot * y , y return last_x , last_y def _divmod ( num , den , p ): """Вычислить число/день по модулю простого числа p Чтобы объяснить это, результат будет таким: den * _divmod(num, den, p) % p == num """ inv , _ = _extended_gcd ( den , p ) return num * invdef _lagrange_interpolate ( x , x_s , y_s , p ): """ Найти значение y для заданного x, заданных n (x, y) точек; k точек определят полином до k-го порядка. """ k = len ( x_s ) assert k == len ( set ( x_s )), "точки должны быть различными" def PI ( vals ): # заглавная буква PI — произведение входных данных accum = 1 for v in vals : accum *= v return accum nums = [ ] # избежать неточного деления dens = [] for i in range ( k ) : others = list ( x_s ) cur = others.pop ( i ) nums.append ( PI ( x - o for o in others )) dens . append ( PI ( cur - o for o in others )) den = PI ( dens ) num = sum ([ _divmod ( nums [ i ] * den * y_s [ i ] % p , dens [ i ], p ) for i in range ( k )]) return ( _divmod ( num , den , p ) + p ) % p def recovery_secret ( shares , prime = _PRIME ): """ Восстановить секрет из общих точек (точек (x,y) на полиноме). """ if len ( shares ) < 3 : raise ValueError ( "нужно не менее трех общих частей" ) x_s , y_s = zip ( * общие части ) return _lagrange_interpolate ( 0 , x_s , y_s , prime ) def main (): """Основная функция""" секрет = 1234 доли = make_random_shares ( секрет , минимум = 3 , доли = 6 ) print ( 'Секрет:' , секрет ) print ( 'Доли:' ) если доли : для доли в долях : print ( ' ' , доля ) print ( 'Секрет, восстановленный из минимального подмножества акций: ' , recovery_secret ( shares [: 3 ])) print ( 'Секрет, восстановленный из другого минимального подмножества акций: ' , recovery_secret ( shares [ - 3 :]))если __name__ == '__main__' : main ()
Этот SLIP описывает стандартную и совместимую реализацию разделения секрета Шамира (SSS) и спецификацию для его использования при резервном копировании иерархических детерминированных кошельков, описанных в BIP-0032.
Разновидности разделения секрета Шамира (SSS) были реализованы несколько раз в сфере криптовалют, но позже разработчики поняли, что дополнительная сложность в конечном итоге снизила безопасность системы.