การแบ่งปันความลับของ Shamir


17

ป.ร. ให้ไว้n(จำนวนของผู้เล่น) t(ค่าเกณฑ์) และs(ความลับ) เอาท์พุทnลับที่สร้างขึ้นโดยอัลกอริทึมที่ใช้ร่วมกันความลับของมิร์

อัลกอริทึม

สำหรับจุดประสงค์ของการท้าทายนี้การคำนวณจะกระทำในGF (251) (เขตข้อมูลขนาด จำกัด251หรือที่รู้จักกันในชื่อจำนวนเต็มmod 251 ) ตามปกติแล้วฟิลด์จะถูกเลือกเพื่อให้ขนาดของมันใหญ่กว่าnมาก เพื่อลดความท้าทายขนาดของสนามจะคงที่ 251ได้รับเลือกเนื่องจากเป็นจำนวนที่ใหญ่ที่สุดที่สามารถแทนได้โดยเลขจำนวนเต็ม 8 บิตที่ไม่ได้ลงชื่อ

  1. สร้างt-1จำนวนเต็มสุ่มใน (รวม) [0, 250]ช่วง ป้ายเหล่านี้1ผ่านT-1
  2. สร้างt-1พหุนามระดับปริญญาที่ใช้sเป็นค่าคงที่และจำนวนเต็มแบบสุ่มจากขั้นตอนที่ 1 เป็นค่าสัมประสิทธิ์ของพลังของx: f (x) = s + x * a 1 + x 2 * a 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)

การตรวจสอบ

Stack Snippet ต่อไปนี้สามารถใช้เพื่อตรวจสอบผลลัพธ์:

กฎระเบียบ

  • sจะเป็นจำนวนเต็มไม่เป็นลบน้อยกว่า251และnและtจะเป็นจำนวนเต็มบวกน้อยกว่าและมากกว่า251 1นอกจากนี้คุณรับประกันได้ว่าปัจจัยการผลิตที่ถูกต้อง (ความหมายt <= n)
  • อินพุตและเอาต์พุตสามารถอยู่ในรูปแบบที่สมเหตุสมผลไม่คลุมเครือและสอดคล้องกัน
  • สุ่มตัวเลขที่จะสุ่มตัวอย่างจากการกระจายเครื่องแบบ - แต่ละค่าที่เป็นไปได้ควรมีความน่าจะเป็นเท่ากันของการเลือก

1
เราจำเป็นต้องเอาท์พุทz และ f(z) ? ถ้าฉันสั่งพิมพ์อาเรย์ของf(z)เรียงตามลำดับzจะถูกบอกเป็นนัยโดยดัชนี ไม่ได้มีข้อมูลมากกว่า[[1, 5], [2, 2], [3, 9], [4, 14]] [5, 2, 9, 14]
orlp

1
ความท้าทายสำหรับการทำสิ่งที่ตรงกันข้าม
FryAmTheEggman

@orlp จุดยุติธรรม
Mego

มีตัวอย่างอะไรบ้าง?
Leun Nun

4
@LeakyNun เนื่องจากคำถามนี้ถูกติดแท็กแบบสุ่มฉันคิดว่าตัวอย่างการยืนยันมีคุณค่ามากกว่ากรณีทดสอบที่จะแตกต่างกันไปสำหรับการทดสอบแต่ละครั้ง
FryAmTheEggman

คำตอบ:


13

เยลลี่ 15 ไบต์

251©xX€⁵0¦ḅЀ%®

ต้องการอาร์กิวเมนต์t , nและ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]&

ใช้เวลาสามข้อโต้แย้งในการสั่งซื้อเสื้อ , nและs สร้างอาร์เรย์ 2d พร้อมn row และคอลัมน์t -1 แต่ละแถวเวกเตอร์เจมีจำนวนจาก 1 ถึงnมีอำนาจของJผ่านเจที -1 จากนั้นเวกเตอร์ของสัมประสิทธิ์จำนวนเต็มแบบสุ่มในช่วง 0 ถึง 250 ถูกสร้างด้วยค่าt -1 นั่นคือเมทริกซ์คูณกับอาร์เรย์ 2d จากนั้นsจะถูกเพิ่มองค์ประกอบที่ชาญฉลาดและนำโมดูล 251 เพื่อรับค่าพหุนามในแต่ละnจุด


1
เป็นเพียงเกี่ยวกับการโพสต์คำตอบ 79 ไบต์เคล็ดลับดีด้วยSum!
LegionMammal978

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

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

ฉันไม่รู้วิธีตรวจสอบอย่างถูกต้อง แต่ฉันรู้ว่ามันเป็นความเจ็บปวดที่จะให้ JS ทำแผนที่ข้ามแถวใหม่เนื่องจากดูเหมือน.mapจะข้ามค่าที่ไม่ได้กำหนด หากใครเห็นวิธีปรับปรุงหรือข้อบกพร่องอย่าลังเลที่จะแจ้งให้เราทราบ


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

คุณไม่ได้ใช้nงานซึ่งดูเหมือนว่าผิด รหัสของคุณดูเหมือนว่าจะมีการทำดัชนีแบบ 1 สั้นกว่าเล็กน้อย[...Array()] fiil()นอกจากนี้สองบรรทัดสุดท้ายสามารถลดลงได้return _.map(f);
Neil

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

# แลมบ์ดา C ที่ปัจจัยการผลิตที่มีและการส่งออกเป็นint IEnumerable<double>คุณสามารถลองใช้รหัสของฉันใน. NetFiddle

ฉันไม่แน่ใจ 100% เกี่ยวกับความถูกต้องของอัลกอริทึมของฉันโปรดแสดงความคิดเห็นหากฉันเข้าใจผิดบางอย่าง

4 ไบต์บันทึกด้วย @ raggy ของเคล็ดลับ


3

MATL , 20 19 ไบต์

251tliq3$Yrihi:ZQw\

เพื่อป้อนข้อมูลเป็นt, ,sn

ลองออนไลน์!

คำอธิบาย

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

ผมอยากจะคิดว่านี่เป็นหนึ่งในกรณีที่หายากที่เต้นreducemap


1

Python 3 ที่มีNumPy , 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 สำหรับ code golf ...

ฟังก์ชั่นไม่ระบุชื่อที่รับอินพุตผ่านการโต้แย้งและส่งกลับรายการ

มันทำงานอย่างไร

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

J , 32 30 ไบต์

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

ทำรายการด้วยค่าn , tและs s

ที่บันทึกไว้ 2 ไบต์โดยใช้แทนที่ที่ดัชนี 0ความคิดจาก @ เดนนิสวิธีการแก้ปัญหา

คำอธิบาย

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

นิพจน์ lambda ของ Java 8 เอาต์พุตอาร์เรย์จำนวนเต็มที่คั่นด้วยเครื่องหมายจุลภาคและทำงานอย่างสมบูรณ์แบบจนกว่าค่าในอาร์เรย์เอาต์พุตจะเกินขอบเขตของช่วงของlongจำนวนเต็มของ Java หรือ 64 บิตที่ลงนามแล้วชนิดข้อมูลซึ่ง-200เป็นเอาต์พุตในอาร์เรย์

ลองออนไลน์! (Ideone)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.