シャミールの秘密の共有


17

与えられたn(プレイヤーの数)、 t(しきい値)、およびs(秘密)、出力nによって生成された秘密シャミール秘密分散アルゴリズム

アルゴリズム

このチャレンジの目的のために、計算はGF(251)(sizeの有限体251、または整数mod 251として知られる)で行われます。通常、フィールドは、サイズがより大きい素数になるように選択されnます。課題を簡素化するために、フィールドサイズは一定になります。251これは、8ビットの符号なし整数で表現できる最大の素数であるため選択されました。

  1. t-1(包括的)範囲でランダムな整数を生成します[0, 250]。これらのラベル1を通過T-1
  2. 構築t-1用い番目の多項式をsのパワーの係数として工程1からの一定値とランダムな整数としてxF(X)= S + X * 1 + X 2 * 2 + ... + X T- 1 * a t-1
  3. (包括的)範囲内の(f(z) mod 251)それぞれの出力。z[1, n]

参照実装

#!/usr/bin/env python
from __future__ import print_function
import random
import sys

# Shamir's Secret Sharing algorithm
# Input is taken on the command line, in the format "python shamir.py n t s"

n, t, s = [int(x) for x in sys.argv[1:4]]
if t > n:
    print("Error: t must be less than or equal to n")
    exit()
if n not in range(2, 251):
    print("Error: n must be a positive integer less than 251")
    exit()
if t not in range(2, 251):
    print("Error: t must be a positive integer less than 251")
    exit()
if s not in range(251):
    print("Error: s must be a non-negative integer less than 251")
    exit()
p = 251
a = [random.randrange(0, 251) for x in range(t-1)]

def f(x):
    return s + sum(c*x**(i+1) for i,c in enumerate(a))

# Outputting the polynomial is for explanatory purposes only, and should not be included
#  in the output for the challenge
print("f(x) = {0} + {1}".format(s, ' + '.join('{0}*x^{1}'.format(c, i+1) for i,c in enumerate(a))))
for z in range(1, n+1):
    print(f(z) % p)

検証

次のスタックスニペットを使用して、出力を確認できます。

ルール

  • sは未満の非負の整数251でありnt未満251およびより大きい正の整数です1。さらに、入力が有効であることが保証されます(つまりt <= n)。
  • 入力および出力は、合理的で明確で一貫性のある任意の形式にすることができます。
  • 乱数は均一な分布からサンプリングされます-可能な値はそれぞれ選択される確率が等しくなければなりません。

1
出力する必要がz あり f(z)ますか?f(z)sの配列を順番に印刷するとz、インデックスによって暗示されます。[[1, 5], [2, 2], [3, 9], [4, 14]]にはを超える情報は含まれません[5, 2, 9, 14]
orlp 16


@orlpフェアポイント。
メゴ

テストケースはありますか?
リーキー修道女

4
@LeakyNunこの質問にはrandomのタグが付けられているため、検証スニペットは実行ごとに異なるテストケースよりも価値があると思います。
FryAmTheEggman 16

回答:


13

ゼリー、15 バイト

251©xX€⁵0¦ḅЀ%®

コマンドライン引数としてtn、およびsを期待します。オンラインでお試しください!

使い方

251©xX€⁵0¦ḅЀ%®  Main link. Left argument: t. Right argument: n Third argument: s

251©             Yield 251 and copy it to the register.
    x            Repeat [251] t times.
     X€          Random choice each; pseudo-randomly choose t integers from
                 [1, ..., 251]. Since 251 = 0 (mod 251), this is equivalent to
                 choosing them from [0, ..., 250].
       ⁵0¦       Replace the last generated integer (index 0) with s (⁵).
          ḅЀ    Interpret the resulting array as a base-k number, for each k in
                 [1, ..., n], and convert to integer.
              ®  Yield 251 from the register.
             %   Take the generated integers modulo 251.

3
最後の整数を置き換えることはとてもエレガントです:)
リン

8

Mathematica 59 56バイト

Mod[Power~Array~{#2,#-1}.RandomInteger[250,#-1]+#3,251]&

tn、およびsの順序で3つの引数を取ります。n行の2D配列を構築し、 t -1列をます。各行ベクトルJスルー1から番号を付け、Nは、のべき乗含まJスルーjは Tを -1。次に、0〜250の範囲のランダムな整数係数のベクトルが t -1値で作成されます。それは2d配列と行列乗算され、次に sが要素ごとに追加され、モジュール251を取得して、 n点のそれぞれで多項式の値を取得します。


1
ちょうど79バイトの回答を投稿しようとしていましたSum
LegionMammal978 16

1
別のアプローチがありますが、現在は2バイト長くなっています。たぶんあなたはそれを短くする方法を考えている:Mod[x#+#2&~Fold~RandomInteger[250,#2-1]x+#3/.x->Range@#,251]&
マーティン・エンダー



3

JavaScript、181バイト

(n,t,s)=>{r=Array(t-1).fill(0).map($=>{return Math.random()*251});f=(x=>{p = 0;r.map((k,c)=>p+=k*Math.pow(x, c));return s+p});_=Array(t-1).fill(0);_.map((l,i)=>_[i]=f(i));return _;}

ゴルフをしていない:

(n, t, s) => {
    r = Array(t - 1).fill(0).map($ =>{return Math.random() * 251});
    f = (x => {
        p = 0;
        r.map((k, c) => p += k * Math.pow(x, c));
        return s + p
    });
    _ = Array(t - 1).fill(0);
    _.map((l, i) => _[i] = f(i));
    return _;
}

私はそれを適切にチェックする方法を知りませんが、明らかに.map未定義の値をスキップするため、JSを新しい配列にマッピングさせるのが苦痛だったことを知っています。誰かが改善する方法、または欠陥を見つけたら、私に知らせてください。


123バイト:(n,t,s,A=f=>Array(t-1).fill(0).map(f),r=A($=>Math.random()*251))=> A((l,i,_,p=0)=>(r.map((k,c)=>p+=k*Math.pow(i,c)),s+p))
デンドロビウム

を使用していないためn、間違っているようです。また、コードは1ベースのインデックス付けを想定しているようです。[...Array()]は、より少し短いですfiil()。また、最後の2行を次のように減らすことができますreturn _.map(f);
ニール

3

C#、138 134バイト

(n,t,s)=>new int[n+1].Select((_,x)=>(s+new int[t-1].Select(k=>new Random(e).Next(251)).Select((c,i)=>c*Math.Pow(x+1,i+1)).Sum())%251);

入力がintあり、出力がであるC#ラムダIEnumerable<double>.NetFiddleで私のコードを試すことができますます。

私は自分のアルゴリズムの妥当性について100%確信が持てません。何か誤解した場合はコメントしてください。

@ raggy's trickで4バイトを節約しました。


3

MATL 20 19バイト

251tliq3$Yrihi:ZQw\

入力順は tsn

オンラインでお試しください!

説明

251t    % Push 251 twice
l       % Push 1
iq      % Take input t. Subtract 1
3$Yr    % Generate t-1 random integers in [1 2 ... 251]
ih      % Take input s. Concatenate with the random integers
i:      % Take input n. Generate range [1 2 ... n]
ZQ      % Evvaluate polynomial at those values
w       % Swap to move copy og 251 to the top of the stack
\       % Modulo. Implicitly display


1

JavaScript(ES6)、116バイト

(n,t,s)=>[...Array(n)].map((_,i)=>++i&&t.reduce((r,a)=>r*i+a)%251,t=[...Array(t)].map(_=>--t?Math.random()*251|0:s))

これはreduceビートのまれなケースの1つだと思いますmap


1

NumPyを使用した Python 3、103バイト

from numpy import*
lambda n,t,s:[poly1d(append(random.randint(0,251,t-1),s))(i+1)%251for i in range(n)]

私は、NumPyをコードゴルフに使用することを決して期待していなかったと正直に言うことができます...

引数を介して入力を受け取り、リストを返す匿名関数。

使い方

from numpy import*         Import everything in the NumPy library
lambda n,t,s...            Function with input number of players n, threshold value t and
                           secret s
random.randint(0,251,t-1)  Generate a NumPy array R of t-1 random integers in [0,250]
append(...,s)              Append s to R
poly1d(...)                Generate a polynomial p of order t-1 with coefficients R and
                           constant term s
...for i in range(n)       For all integers i in [0,n-1]...
...(i+1)                   ...evaluate p(i+1), so for all integers in [1,n]...
...%251                    ...and take modulo 251
...:[...]                  return as list

Ideoneでお試しください


1

J32 30バイト

251|(1+i.@{.)p.~{:0}251?@#~1&{

nt、およびsを持つリストを取得します。

@Dennis のソリューションからのインデックス0で置換のアイデアを使用して2バイトを保存しました

説明

251|(1+i.@{.)p.~{:0}251?@#~1&{  Input: [n t s]
                           1&{  Select at index 1 (t)
                    251  #~     Create that many copies of 251
                       ?@       Generate that many random integers in [0, 251)
                {:              Get the tail of the input (s)
                  0}            Replace the value at index 0 of the random integer list
                                with s to make a coefficient list of the polynomial
          {.                    Get the head of the input (n)
       i.@                      Make the range [0, n-1]
     1+                         Add 1 to each to get [1, n]
             p.~                Evaluate the polynomial at each value [1, n]
251|                            Take each value mod 251 and return

0

Java 8、224バイト:

(n,t,s)->{int[]W=new int[t-1];for(int i=0;i<t-1;i++){W[i]=new java.util.Random().nextInt(251);};long[]O=new long[n];for(int i=1;i<=n;i++){long T=0;for(int h=1;h<t;h++){T+=W[h-1]*Math.pow(i,h);}O[i-1]=((T+s)%251);}return O;};

Java 8ラムダ式。カンマ区切りの整数配列を出力し、出力配列の値が配列の出力先であるJavaのlongデータ型(64ビット符号付き整数)の範囲を超えるまで完全に機能します-200

オンラインでお試しください!(イデオン)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.