シャミアの秘密分散法(SSS) は、グループ内で秘密情報(「秘密」) を配布するための効率的な秘密分散 アルゴリズムです。グループの定足数が協力して知識を共有しない限り、秘密は公開されません。これを実現するために、秘密は数学的に部分 (「シェア」) に分割され、十分な数のシェアが結合された場合にのみ秘密を再構成できます。SSS には情報理論的セキュリティの特性があり、攻撃者が一部のシェアを盗んだとしても、定足数のシェアを盗まない限り、攻撃者が秘密を再構築することは不可能です。
シャミアの秘密共有は、マスターシークレットへのアクセスキーを共有するために一部のアプリケーションで使用されます。
高レベルの説明
SSS は、分散形式で秘密を保護するために使用され、最もよく使用されるのは暗号化キーを保護することです。秘密は複数の共有に分割されますが、各共有からは秘密に関する情報は提供されません。
SSS によって保護された秘密を再構築するには、しきい値と呼ばれる一定数のシェアが必要です。しきい値以下のシェア数では、秘密に関する情報は得られません (完全な秘密性と呼ばれる特性)。この意味で、SSS はワンタイム パッドの一般化です(ワンタイム パッドは、2 つのシェアしきい値と合計 2 つのシェアを持つ SSS と見なすことができます)。[1]
アプリケーション例
企業は金庫を安全に保護する必要があります。金庫のコードを知っている人が1 人だけだと、金庫を開ける必要があるときにコードが紛失したり、利用できなくなったりする可能性があります。コードを知っている人が複数いると、お互いを信頼できず、常に正直に行動できない可能性があります。
このような状況では、SSS を使用して、会社の許可された個人に配布される金庫のコードのシェアを生成することができます。各個人に与えられるシェアの最小しきい値と数は、許可された個人 (のグループ) のみが金庫にアクセスできるように選択できます。しきい値よりも少ないシェアが提示された場合、金庫を開くことはできません。
事故、強制、または反対行為により、一部の個人が自分の株式について誤った情報を提示する場合があります。正しい株式の合計が最小しきい値を満たさない場合、金庫はロックされたままになります。
ユースケース
シャミアの秘密分散法は、
- パスワードマネージャーのルートキーを復号するためのキーを共有する、[2]
- 暗号化された電子メールにアクセスするためのユーザーキーを回復する[3 ]
- マスターシークレットを再作成するために使用されるパスフレーズを共有し、それが暗号通貨ウォレットへのアクセスに使用されます。[4]
特性と弱点
SSSは有用な特性を持っていますが、弱点[5]もあり、一部の用途には適していません。
便利なプロパティは次のとおりです。
- 安全: この方式は情報理論的に安全です。
- 最小: 各ピースのサイズは元のデータのサイズを超えません。
- 拡張可能: 任意のしきい値に対して、既存の共有に影響を与えることなく、共有を動的に追加または削除できます。
- 動的: 秘密を変更せずに、多項式を時々変更し (同じ自由項を維持)、参加者ごとに新しいシェアを構築することで、セキュリティを強化できます。
- 柔軟性: 階層が重要な組織では、組織内での重要性に応じて、各参加者に異なる数の株式を発行できます。たとえば、しきい値が3の場合、社長は 3 つの株式を与えられれば単独で金庫を開けることができますが、それぞれ 1 つの株式を持つ 3 人の秘書は、金庫を開けるために株式を組み合わせる必要があります。
弱点は次のとおりです。
- 検証可能な秘密共有なし: シェアの再構成プロセス中、SSS は使用されている各シェアの正確性を検証する方法を提供しません。検証可能な秘密共有は、株主が誠実であり、偽のシェアを提出していないことを確認することを目的としています。
- 単一障害点: 秘密は、共有に分割されるときに 1 か所に存在し、再構成されるときにも 1 か所に存在する必要があります。これらは攻撃ポイントであり、マルチ署名などの他のスキームでは、これらの単一障害点の少なくとも 1 つが排除されます。
歴史
イスラエルの科学者アディ・シャミールが1979年に初めてこの計画を考案した。[6]
数学的原理
この方式はラグランジュの補間定理、具体的には多項式上の点が 次数以下の多項式を一意に決定するという定理を利用します。たとえば、直線を定義するには2点、放物線を定義するには 3 点、3次曲線を定義するには 4 点、といった 具合です。
数学的定式化
シャミアの秘密分散法は、有限体上の多項式補間に基づく理想的かつ完全なしきい値方式です。この方式では、秘密(たとえば、金庫への組み合わせ) を次のようにデータ断片(シェアと呼ばれる) に分割することを目的とします。
- 任意のシェアまたは複数のシェアに関する知識があれば、計算が可能になります。つまり、シェアの任意の組み合わせから秘密全体を再構築できます。
- 任意のシェア数またはそれより少ないシェア数を知っていると、 の可能な値は、シェア数を知っている場合と同様に、最大 シェア数を知っている場合でも同じであるという意味で、完全に未確定のままになります。 シェア数より少ないシェア数では、秘密を再構築することはできません。
の場合、秘密を再構築するにはすべてのシェアが必要になります。

秘密は有限体の元(ただし は生成されるシェアの数より大きい)として表せると仮定します。から元 をランダムに選択し、多項式 を構築します。曲線上の任意の点(たとえば)を計算して点 を見つけます。各参加者には点(多項式への非ゼロの入力とそれに対応する出力)が与えられます。[7]これらのペアの任意のサブセットが与えられた場合、補間 を使用して を取得できます。これを行うための 1 つの可能な式は です。ここで、多項式上の点のリストは、形式 のペアとして与えられます。 は多項式 の最初の係数に等しいことに注意してください。
計算例
次の例は、基本的な考え方を示しています。ただし、この例の計算は、理解しやすくするために有限体演算ではなく整数演算を使用して行われていることに注意してください。したがって、以下の例は完全な秘密性を提供しておらず、シャミアの方式の適切な例ではありません。次の例で問題について説明します。
準備
共有する秘密が 1234 であるとします。
この例では、秘密は 6 つのシェアに分割されます。3 つのシェアのサブセットがあれば、秘密を再構築するのに十分です。数字はランダムに選択されます。166 と 94 とします。
- これにより係数が得られる。秘密は
したがって、秘密シェア(ポイント)を生成する多項式は次のようになります。
多項式の 6 つの点は次のように構築されます。
スキームの各参加者は、異なるポイント(とのペア)を受け取ります。の代わりに が使用されるため、ポイントは から始まり、 から始まるわけではありません。が秘密である ため、これが必要です。
復興
秘密を再現するには、3つのポイントがあれば十分です
3 つのポイントの使用を検討してください。
ラグランジュ基底多項式の計算:
多項式補間の式を使用すると、次のようになります。
秘密は自由係数であることを思い出してください。つまり、 となり、秘密が復元されました。
計算効率の高いアプローチ
ラグランジュ多項式を使用してソース多項式の係数を見つけるために多項式補間を使用すると、未使用の定数が計算されるため効率的ではありません。
これを考慮すると、ラグランジュ多項式を使用して見つけるための最適化された式は次のように定義されます。
整数演算の使用に関する問題
上で示した方法の簡略版は有限体演算ではなく整数演算を使用して機能しますが、セキュリティ上の問題があります。イブは見つけたものごと にに関する情報を取得してしまうのです。
彼女が 2 つの点と を見つけたとします。彼女はまだ点を持っていないので、理論的には についてこれ以上の情報を得ることはできないはずです。しかし、彼女は 2 つの点からの情報と公開情報を組み合わせることができます: 。そうすることで、イブは次の代数計算を実行できます。
- の式に との値を入力します。
- (1)にとの値を記入する。
- (1)にとの値を記入する。
- (3)-(2)を引くと、これを書き直すことができる。
- ここで、イブは(4)の結果を(2)に置き換えることができます。これにより、Sが偶数であるという情報が得られます。
有限体演算を用いた解法

上記の攻撃は、多項式が構築された方法によって多項式が取ることのできる値に対する制約を悪用します。多項式の係数は整数でなければならず、スキームで使用される各座標で評価されるときに多項式は値として整数を取らなければなりません。これにより、シェア数が より少ない場合、結果の秘密を含む未知のポイントでの可能な値が減ります。
この問題は、有限体演算を使用することで解決できます。有限体は常にサイズ で、 は素数、は正の整数です。体のサイズはを満たし、秘密の可能な値の数よりも大きくなければなりませんが、後者の条件は、秘密をより小さな秘密値に分割し、それぞれにスキームを適用することで回避できます。以下の例では、素体 (つまりr = 1) を使用します。図は、有限体上の多項式曲線を示しています。
実際には、これは小さな変更にすぎません。フィールドの位数q (つまり、フィールドが持つ値の数) は、参加者の数と秘密が取る値の数よりも大きくなるように選択する必要があります。多項式を含むすべての計算は、整数ではなくフィールド (この例ではp を法として計算され、 は素数と見なされます)で計算する必要があります。フィールドの選択と、このフィールドの値への秘密のマッピングは、どちらも公に知られているものと見なされます。
この例では、 を選択すると、多項式は となり、点が与えられます。
今回、イブは(ポイントを獲得するまで)を見つけても何の情報も得られません。
再び、イブがと を見つけ、公開情報が であると仮定します。前の攻撃を試みた場合、イブは次のことができます。
- 式にとおよびの値を入力します。
- (1)にとの値を記入する。
- (1)にとの値を記入する。
- (3)-(2)を引くと、これを次のように書き直す。
には 個の値が考えられます。 は常に 3 ずつ減少することがわかっているので、が で割り切れる場合は と結論付けることができます。しかし、は素数なので、これを結論付けることはできません。したがって、有限体を使用すると、この攻撃の可能性を回避できます。
また、Eve は と結論付けることができますが、上記の整数演算の例とは異なり、モジュラー演算の「ラップアラウンド」動作により「S は偶数である」という漏洩が防止されるため、追加情報は提供されません。
Pythonコード
コードをより明確にするため、ここでは素体を使用します。実際には、便宜上、より小さなバイナリ体を使用して構築されたスキームを、セキュリティを損なうことなく、秘密のビットの小さな部分文字列に個別に適用できます (バイト単位の適用の場合は 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__ からdivisionをインポートします __future__からprint_functionをインポートします
ランダム
インポート 関数ツールのインポート
#12位 メルセンヌプライム
_PRIME = 2 ** 127 - 1
_RINT = 関数ツール。部分的(ランダム. SystemRandom () . randint , 0 )
def _eval_at ( Poly , x , prime ):
""" 以下の make_random_shares でシャミール プールを生成するために使用される、x での多項式 (係数タプル) を評価します 。 """ accum = 0 for coeff in reversed ( poly ): accum *= x accum += coeff accum %=素数return accum
def make_random_shares ( secret , minimum , shares , prime = _PRIME ):
""" 指定された secret のランダム シャミア プールを生成し、share points を返します。 """ if minimum > shares : raise ValueError ( "プール secret は回復不可能です。" ) 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 points
def _extended_gcd ( a , b ):
""" p を法とする整数の除算は、 分母を法として逆数を求め、その逆数を分子に掛けることを意味します (注: A の逆数は A*B % p == 1 となる B です)。これは、 拡張ユークリッド互除法で計算できます http://en.wikipedia.org/wiki/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 の num / den を計算します。
これを説明すると、結果は次のようになります:
den * _divmod(num, den, p) % p == num
"""
inv , _ = _extended_gcd ( den , p )
return num * inv
def _lagrange_interpolate ( x , x_s , y_s , p ):
""" n 個の (x, y) ポイントが与えられた場合、指定された 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 recover_secret ( shares , prime = _PRIME ):
""" 共有ポイント (多項式上のポイント (x,y)) から秘密を回復します。 """ if len ( shares ) < 3 : raise ValueError ( "少なくとも 3 つの共有が必要です" ) x_s , y_s = zip ( * shares ) return _lagrange_interpolate ( 0 , x_s , y_s , prime )
def main ():
"""メイン関数""" secret = 1234 shares = make_random_shares ( secret 、minimum = 3 、shares = 6 )
print ( 'Secret: ' ,
secret )
print ( 'Shares:' )
if shares :
for share in shares :
print ( ' ' , share )
print ( 'シークレットは最小のシェアのサブセットから回復されました: ' ,
recover_secret ( shares [ : 3 ]))
print ( 'シークレットは別の最小のシェアのサブセットから回復されました: ' ,
recover_secret ( shares [ - 3 :]))
__name__ == '__main__'の場合:
main ()
参照
参考文献
- ^ Krenn, Stephan; Loruenser, Thomas (2023).秘密共有入門: プロトコル選択のための体系的な概要とガイド。doi : 10.1007 /978-3-031-28161-7. ISBN 978-3-031-28160-0。
- ^ 「Seal/Unseal」。HashiCorpのVault。2022年 10 月 2 日閲覧。
- ^ 「PreVeilレビュー」。PCMag 。 2022年10月2日閲覧。
- ^ Rusnak, Pavol; Kozlik, Andrew; Vejpustek, Ondrej; Susanka, Tomas; Palatinus, Marek; Hoenicke, Jochen (2017-12-18). 「SLIP-0039 : Shamir's Secret-Sharing for Mnemonic Codes」. GitHub . SatoshiLabs . 2022-10-03取得。
この SLIP は、Shamir の秘密共有 (SSS) の標準的かつ相互運用可能な実装と、BIP-0032 で説明されている階層的決定論的ウォレットのバックアップに使用する仕様について説明しています。
- ^ Lopp, Jameson (2020-10-01). 「シャミアの秘密分散の欠点」 . 2022-10-03閲覧。
シャミアの秘密分散 (SSS) のバリエーションは、暗号通貨の分野で何度も実装されてきましたが、開発者は後になって、複雑さが増すとシステムのセキュリティが低下することに気付きました。
- ^ シャミール、アディ(1979)、「秘密を共有する方法」、Communications of the ACM、22(11):612–613、doi:10.1145 / 359168.359176、S2CID 16321225
- ^ Knuth, DE (1997)、『コンピュータプログラミングの芸術』第 2 巻: 半数値アルゴリズム (第 3 版)、Addison-Wesley、p. 505。
さらに読む
- ドーソン、E.; ドノバン、D. (1994)、「シャミアの秘密共有スキームの広さ」、コンピュータ&セキュリティ、13:69-78、doi:10.1016/0167-4048(94)90097-3。
- Benzekki, K. (2017)。「安全なマルチクラウド ストレージのための検証可能な秘密共有アプローチ」。ユビキタス ネットワーキング。コンピュータ サイエンスの講義ノート。第 10542 巻。カサブランカ: Springer。pp. 225–234。doi : 10.1007/978-3-319-68179-5_20。ISBN 978-3-319-68178-8。。
