Chia sẻ bí mật của Shamir


17

Cho n(số lượng người chơi), t(giá trị ngưỡng) và s(bí mật), xuất ra các nbí mật được tạo bởi thuật toán Chia sẻ bí mật của Shamir .

Thuật toán

Đối với mục đích của thử thách này, việc tính toán sẽ được thực hiện trong GF (251) (trường hữu hạn về kích thước 251, còn được gọi là số nguyên mod mod 251 ). Thông thường, trường sẽ được chọn sao cho kích thước của nó lớn hơn nhiều so với n. Để đơn giản hóa thử thách, kích thước trường sẽ không đổi. 251đã được chọn vì nó là số nguyên tố lớn nhất có thể biểu thị bằng số nguyên không dấu 8 bit.

  1. Tạo t-1số nguyên ngẫu nhiên trong phạm vi (bao gồm) [0, 250]. Nhãn này một 1 thông qua một t-1 .
  2. Xây dựng một t-1đa thức bậc một sử dụng slàm giá trị không đổi và các số nguyên ngẫu nhiên từ bước 1 làm hệ số của các lũy thừa của x: f (x) = s + x * a 1 + x 2 * a 2 + ... + x t- 1 * một t-1 .
  3. Đầu ra (f(z) mod 251)cho mỗi ztrong phạm vi (bao gồm) [1, n].

Thực hiện tham khảo

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

xác minh

Đoạn mã sau đây có thể được sử dụng để xác minh đầu ra:

Quy tắc

  • ssẽ là một số nguyên không âm nhỏ hơn 251, và ntsẽ là các số nguyên dương nhỏ hơn 251và lớn hơn 1. Hơn nữa, bạn được đảm bảo rằng các đầu vào là hợp lệ (có nghĩa t <= n).
  • Đầu vào và đầu ra có thể ở bất kỳ định dạng hợp lý, rõ ràng và nhất quán.
  • Các số ngẫu nhiên sẽ được lấy mẫu từ một phân phối đồng đều - mỗi giá trị có thể sẽ có xác suất được chọn bằng nhau.

1
Chúng ta có phải đầu ra z f(z) ? Nếu tôi in một mảng f(z)s theo thứ tự, zđược ngụ ý bởi chỉ mục. [[1, 5], [2, 2], [3, 9], [4, 14]]không chứa nhiều thông tin hơn [5, 2, 9, 14].
orlp


@orlp Điểm công bằng.
Mego

Bất kỳ thử nghiệm?
Leaky Nun

4
@LeakyNun Vì câu hỏi này được gắn thẻ ngẫu nhiên , tôi nghĩ đoạn mã xác minh có giá trị hơn nhiều so với các trường hợp thử nghiệm sẽ khác nhau cho mỗi lần chạy.
FryAmTheEggman

Câu trả lời:


13

Thạch , 15 byte

251©xX€⁵0¦ḅЀ%®

Yêu cầu t , ns là đối số dòng lệnh. Hãy thử trực tuyến!

Làm thế nào nó hoạt động

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
Thay thế số nguyên cuối cùng thật thanh lịch :)
Lynn

8

Toán học, 59 56 byte

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

Đưa ra ba đối số theo thứ tự t , ns . Xây dựng một mảng 2d với n hàng và t -1 cột. Mỗi vectơ hàng j , được đánh số từ 1 đến n , chứa các lũy thừa của j thru j t -1 . Sau đó, một vectơ các hệ số nguyên ngẫu nhiên trong phạm vi từ 0 đến 250 được tạo ra với các giá trị t -1. Đó là ma trận nhân với mảng 2d, và sau đó s được thêm phần tử-khôn ngoan và lấy mô-đun 251 để lấy giá trị của đa thức tại mỗi điểm n .


1
Chỉ là để gửi một câu trả lời 79 byte, thủ thuật hay với Sum!
LegionMammal978

1
Tôi đã có một cách tiếp cận khác, nhưng hiện tại nó dài hơn hai byte. Có thể bạn có một ý tưởng làm thế nào để rút ngắn nó:Mod[x#+#2&~Fold~RandomInteger[250,#2-1]x+#3/.x->Range@#,251]&
Martin Ender



3

JavaScript, 181 byte

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

Ung dung:

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

Tôi không biết cách kiểm tra nó một cách chính xác, nhưng tôi biết rằng thật khó để bắt JS phải lập bản đồ trên một mảng mới kể từ khi rõ ràng .map bỏ qua các giá trị không xác định. Nếu bất cứ ai thấy bất kỳ cách nào để cải thiện hoặc sai sót, đừng ngần ngại cho tôi biết.


123 byte:(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

Bạn không sử dụng n, có vẻ sai. Mã của bạn dường như cũng đang giả sử lập chỉ mục dựa trên 1. [...Array()]là hơi ngắn hơn fiil(). Ngoài ra, hai dòng cuối cùng có thể được giảm xuốngreturn _.map(f);
Neil

3

C #, 138 134 byte

(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 nơi đầu vào là intvà đầu ra là một IEnumerable<double>. Bạn có thể thử mã của tôi trên .NetFiddle .

Tôi không chắc chắn 100% về tính hợp lệ của thuật toán của mình, vui lòng bình luận nếu tôi hiểu nhầm điều gì đó.

4 byte được lưu với thủ thuật @ raggy's .


3

MATL , 20 19 byte

251tliq3$Yrihi:ZQw\

Trật tự đầu vào là t, s, n.

Hãy thử trực tuyến!

Giải trình

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 byte

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

Tôi muốn nghĩ rằng đây là một trong những trường hợp hiếm hoi có reducenhịp đập map.


1

Python 3 với NumPy , 103 byte

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

Tôi có thể thành thật nói rằng tôi chưa bao giờ mong đợi sử dụng NumPy cho mã golf ...

Một hàm ẩn danh nhận đầu vào thông qua đối số và trả về một danh sách.

Làm thế nào nó hoạt động

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

Hãy thử nó trên Ideone


1

J , 32 30 byte

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

Đưa ra một danh sách với các giá trị n , ts .

Đã lưu 2 byte bằng cách sử dụng ý tưởng thay thế tại chỉ mục 0 từ giải pháp của @ Dennis .

Giải trình

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

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

Một biểu thức lambda Java 8. Xuất ra một mảng số nguyên được phân tách bằng dấu phẩy và hoạt động hoàn hảo cho đến khi các giá trị trong mảng đầu ra vượt ra ngoài phạm vi của longkiểu dữ liệu, hoặc số nguyên có chữ ký 64 bit, -200được đưa vào mảng.

Dùng thử trực tuyến! (Ý)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.