沙米尔的秘密分享


17

给定n(玩家数量),t(阈值)和s(秘密),输出nShamir的秘密共享算法生成的秘密

算法

出于这一挑战的目的,将在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 * A 2 + ... + X 叔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将是小于的非负整数251n并且t将是小于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


@orlp公平点。
Mego

有测试用例吗?
Leaky Nun

4
@LeakyNun因为这个问题被标记为random,所以我认为验证代码段比每次运行的测试用例都要有价值。
FryAmTheEggman '16

Answers:


13

果冻,15 字节

251©xX€⁵0¦ḅЀ%®

期望tns作为命令行参数。在线尝试!

怎么运行的

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
替换最后一个整数非常好:)
Lynn

8

Mathematica,59 56字节

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

tns的顺序接受三个参数。构造具有n行和t -1列的2d数组。从1到n编号的每个行向量j包含jj t -1的幂。然后,使用t -1值创建范围为0到250的随机整数系数向量。将其与2d阵列矩阵相乘,然后将s逐元素相加并取入模块251,以获取n个点中每个点处的多项式的值。


1
正要发布一个79字节的答案,不错的招Sum
LegionMammal978 '16

1
我有一种不同的方法,但是目前要长两个字节。也许您有个想法可以缩短它:Mod[x#+#2&~Fold~RandomInteger[250,#2-1]x+#3/.x->Range@#,251]&
Martin Ender



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

我不知道如何正确地检查它,但是我确实知道让JS映射到新数组上很痛苦,因为显然.map跳过了未定义的值。如果有人发现任何改进的方法或存在缺陷,请随时让我知道。


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))
D石

您没有使用n,这似乎是错误的。您的代码似乎还假设基于1的索引。[...Array()]比略短fiil()。此外,最后两行可以减少为return _.map(f);
Neil

3

C#,138134字节

(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#lambda 是一个IEnumerable<double>。您可以在.NetFiddle上尝试我的代码。

我不确定我算法的有效性100%,如果我误解了一些内容,请发表评论。

用@raggy的把戏保存了4个字节。


3

MATL20 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跳动情况之一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&{

取得值nts的列表

通过使用@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 lambda表达式。输出一个逗号分隔的整数数组,并且可以完美地工作直到输出数组中的值超出Java的范围long(即64位带符号整数)数据类型的范围,然后将其-200输出到数组中。

在线尝试!(爱迪生)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.