Shamir'in Gizli Paylaşımı


17

Verilen n(oyuncu sayısı), t(eşik değeri) ve s(sır), Shamir'in Gizli Paylaşım algoritmasın tarafından üretilen sırları çıkarır .

Algoritma

Bu zorluğun amaçları için, hesaplamalar GF (251) (sonlu boyut alanı 251, aksi halde tamsayı mod 251 olarak bilinir ) içinde yapılacaktır. Normalde, alan, büyüklüğü çok daha büyük olacak şekilde seçilecektir n. Zorluğu basitleştirmek için alan boyutu sabit olacaktır. 2518 bit işaretsiz tamsayı ile temsil edilebilen en büyük asal olduğu için seçilmiştir.

  1. t-1(Kapsayıcı) aralığında rastgele tamsayılar oluşturun [0, 250]. Bu etiket , bir 1 ile bir t-1 .
  2. Sabit değer ve adım 1'den rastgele tamsayıları kullanarak güçlerin katsayıları olarak bir t-1derece polinomu oluşturun : f (x) = s + x * a 1 + x 2 * a 2 + ... + x t- 1 * bir t-1 .sx
  3. (Dahil) aralığındaki (f(z) mod 251)her biri için çıktı .z[1, n]

Referans uygulaması

#!/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)

Doğrulama

Çıktıları doğrulamak için aşağıdaki Yığın Parçacığı kullanılabilir:

kurallar

  • sdaha az bir negatif olmayan bir tamsayı olacaktır 251ve nve tdaha pozitif tamsayı daha az olacaktır 251ve daha büyük 1. Ayrıca, girişlerin geçerli olduğu garanti edilir (anlam t <= n).
  • Giriş ve çıkış makul, açık ve tutarlı bir formatta olabilir.
  • Rastgele sayılar düzgün bir dağılımdan örneklenmelidir - olası her bir değerin eşit seçilme olasılığı olmalıdır.

1
Çıktı almalı mıyız z ve f(z) ? Bir f(z)s sırasını sırayla yazdırırsam , zdizin tarafından ima edilir. [[1, 5], [2, 2], [3, 9], [4, 14]]daha fazla bilgi içermiyor [5, 2, 9, 14].
orlp


@orlp Adil nokta.
Mego

Herhangi bir testcas?
Leaky Nun

4
@LeakyNun Bu soru rastgele etiketlendiğinden , doğrulama snippet'inin her çalışma için farklı olacak test durumlarından çok daha değerli olduğunu düşünüyorum.
FryAmTheEggman

Yanıtlar:


13

Jöle , 15 bayt

251©xX€⁵0¦ḅЀ%®

T , n ve s'yi komut satırı bağımsız değişkenleri olarak bekler . Çevrimiçi deneyin!

Nasıl çalışır

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
Son tamsayıyı değiştirmek çok zarif :)
Lynn

8

Mathematica, 59 56 bayt

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

T , n ve s sırasıyla üç argüman alır . N satırı ve t -1 sütunu olan bir 2d dizisi oluşturur . Her bir satır vektörü j sokmak 1 sayılı n , yetkilerini içeren j sokmak j t -1 . Daha sonra t- değerleri ile 0 ila 250 aralığında rastgele tamsayı katsayıları vektörü oluşturulur . Bu, 2d-dizisi ile matris çarpılır ve daha sonra s element-wise eklenir ve n noktasının her birindeki polinomun değerini almak için modül 251 alınır .


1
79 baytlık bir cevap, güzel bir numara göndermek üzereydi Sum!
LegionMammal978

1
Farklı bir yaklaşımım var, ama şu anda iki bayt daha uzun. Belki kısaltmak için bir fikriniz var:Mod[x#+#2&~Fold~RandomInteger[250,#2-1]x+#3/.x->Range@#,251]&
Martin Ender



3

JavaScript, 181 bayt

(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 _;}

Ungolfed:

(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 _;
}

Düzgün kontrol nasıl bilmiyorum, ama görünüşe göre .maptanımsız değerleri atlar beri JS yeni bir dizi arasında eşlemek için bir ağrı olduğunu biliyorum . Herhangi biri iyileşmenin herhangi bir yolunu görürse veya kusurları varsa, bana bildirmekten çekinmeyin.


123 bayt:(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))
Dendrobium

Kullanmıyorsunuz n, bu yanlış görünüyor. Kodunuzun ayrıca 1 tabanlı dizine ekleme olduğu varsayılıyor. [...Array()]biraz daha kısadır fiil(). Ayrıca, son iki satır azaltılabilirreturn _.map(f);
Neil

3

C #, 138134 bayt

(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);

C # lambda burada girişler intve çıkış bir IEnumerable<double>. Kodumu .NetFiddle üzerinde deneyebilirsiniz .

Algoritmamın geçerliliğinden% 100 emin değilim, bir şeyi yanlış anladıysam lütfen yorum yapın.

@ Raggy'nin numarasında 4 bayt kaydedildi .


3

MATL , 20 19 bayt

251tliq3$Yrihi:ZQw\

Girdi emirdir t, s, n.

Çevrimiçi deneyin!

açıklama

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 bayt

(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))

Bunun, reduceatımların nadir olduğu durumlardan biri olduğunu düşünmek istiyorum map.


1

NumPy'li Python 3 , 103 bayt

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

Dürüst olmak gerekirse ben asla kod golf için NumPy kullanmak bekleniyor söyleyebiliriz ...

Bağımsız değişken üzerinden girdi alan ve bir liste döndüren anonim bir işlev.

Nasıl çalışır

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 üzerinde deneyin


1

J , 32 30 bayt

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

N , t ve s değerlerini içeren bir liste alır .

@ Dennis'in çözümündeki 0 dizinindeki değiştir fikri kullanılarak 2 bayt kaydedildi .

açıklama

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 bayt:

(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;};

Bir Java 8 lambda ifadesi. Virgülle ayrılmış bir tamsayı dizisi çıktılar ve çıktı dizisindeki değerler, dizinin çıktısı olan Java'nın longveya 64-bit işaretli tamsayı veri türünün ötesine ulaşıncaya kadar mükemmel çalışır -200.

Çevrimiçi Deneyin! (Ideone)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.