ใช้การสร้างการแบ่งปันลับของ Shamir


11

รูปแบบการแบ่งปันความลับของ Shamirเป็นวิธีที่ง่ายในการปกป้องความลับโดยแบ่งออกเป็นหลายส่วนที่จำเป็นในการสร้างใหม่

งานของคุณคือการดำเนินการฟื้นฟูความลับร่วมกันมิร์เหนือจำกัด ฟิลด์1928049029ที่กำหนดโดยนายก หากคุณมีข้อสงสัยเกี่ยวกับความหมายของสิ่งนี้เพียงแค่ถามหรือดูการคำนวณทางคณิตศาสตร์ของ Finite Field & Finite Fieldในวิกิพีเดีย (แหล่งข้อมูลเพิ่มเติมด้านล่าง)

อินพุต

อินพุตดำเนินการโดยใช้ stdin ก่อนอื่นมาเป็นจำนวนเต็มkจากนั้นตามด้วยเส้น k แต่ละบรรทัดเหล่านี้มีคู่ของจำนวนเต็มที่x yแสดงถึงความลับ กล่าวอีกนัยหนึ่งf(x) = yในพหุนามดั้งเดิมที่ใช้ในการสร้างความลับ

จำนวนความลับที่ให้มานั้นเพียงพอที่จะสร้างความลับที่สอดคล้องกันได้เสมอ

เอาท์พุต

ส่งออกไปยัง stdout ความลับที่สร้างขึ้นใหม่

ตัวอย่าง

การป้อนข้อมูล:

5         
1 564797566
2 804114535
4 1354242660
6 1818201132
7 503769263

เอาท์พุท:

1234

การป้อนข้อมูล:

7
1 819016192
2 1888749673
3 1737609270
4 365594983
5 1628804870
6 1671140873
7 492602992

เอาท์พุท:

456457856

ทรัพยากร

บทความ Wikipedia

กระดาษ

ฟิลด์ จำกัดที่มา: Wikipedia

เลขคณิตฟิลด์ จำกัดที่มา: Wikipedia

พหุนาม Lagrangeที่มา: Wikipedia

บทที่เกี่ยวกับคณิตศาสตร์ฟิลด์ จำกัด

คำตอบ:


4

ทุบตี, 271 ตัวอักษร

R () {
[$ {1/0 /}] && {r $ (($ 2% $ 1)) $ 1; ((t = u, u = v- $ 2 / $ 1 * u, v = t));}
}
อ่าน
((n = 1928049029 n = 0))
ในขณะที่อ่าน x [$ n] y [$ n]
ทำ ((n ++))
เสร็จแล้ว
สำหรับ ((i = n; Z = (Z + L)% N ฉัน -;)) ทำ
สำหรับ ((ญ n = l = Y [ผม]; J -;)) ทำ
((U = 0, v = 1, d = x [เจ] -x [I], M = N + d))
r MN
[$ {d / 0 /}] && ((l = l * x [j]% N * (u + N)% N))
เสร็จแล้ว
เสร็จแล้ว
echo $ z

บรรทัดใหม่สามารถแทนที่ได้ในกรณีส่วนใหญ่ด้วยอัฒภาค แต่ฉันไม่คิดว่ามีช่องว่างที่ไม่จำเป็น

(ฉันไม่เคยรู้มาก่อนว่าวันนี้จำนวนเต็มของ bash เป็น 64- บิต - มีประโยชน์มาก)

สำหรับทุบตี GCD แบบเรียกซ้ำ (ใช้ประโยชน์จากสถานะทั่วโลก) ดูเหมือนว่าจะมีความกะทัดรัดมากกว่าแบบซ้ำซ้ำ นี่คือส่วนใหญ่ตรงไปตรงมา; เคล็ดลับที่น่าสนใจคือ[ ${d/0/} ]&&fooสิ่งที่มีประสิทธิภาพif [ $d -ne 0 ];then foo;fi


ดี! ฉันไม่เคยคาดหวังว่าจะได้เห็นคำตอบทุบตีของปัญหานี้ +1
Juan

@ หยวนฉันเริ่มทำมันใน Perl และเบื่อหน่ายกับการบังคับให้ทำหารจำนวนเต็มแทนที่จะลอย และฉันก็รู้ดีกว่าทุบตีอยู่ดีดังนั้นมันเกี่ยวข้องกับการตีหัวกับผนังน้อยกว่า
Peter Taylor

3

199 ตัวอักษรในระดับแปดเสียง:

m=@(x)mod(x,1928049029);[d,l]=scanf('%d');c=d(1);e=repmat(int64(d(2:2:l)),1,c);[_,b]=gcd(e-e',1928049029*ones(c));b=eye(c)+m(e.*b);x=b(1,:);for i=2:c;x=m(x.*b(i,:));end;disp(m(sum(m(x'.*d(3:2:l)))))

3

Golfscript, 114 112 111 110 109 65 (86) ตัวอักษร

หากคุณไม่ต้องการรับผลลัพธ์ในสัปดาห์นี้ 65 ตัวอักษรก็พอเพียง:

~](;2/0\:X{~\.X{0=}%^\{\.@- 1928049029:P.,\@{@*\%(!}++?**}+/+P%}/

แต่ถ้าคุณกำลังมองหาประสิทธิภาพมันจะยาวกว่าเล็กน้อยที่ 86 ตัวอักษร:

~](;2/0\:X{~\.X{0=}%^\{\[.0](@-[1928049029:P%P]{.~/{\.(;@@~@*-+\}+2*.1=}do;0=*}+/+P%}/

นี้จะชำแหละในรายละเอียดมากเกินกว่าที่ฉันต้องการที่จะทำซ้ำที่นี่บนบล็อกของฉัน


ไม่ใช่งานของฉันเป็นหลัก แต่การเปลื้องผ้าอย่างหนักจาก Nabb ให้ตัวอักษร 47 ตัว

n%(!\:A{~A{~;.3$- 1928049029:N((?1or**}/\/+N%}/

หมายเหตุ: ฉันแค่ให้เหตุผลเกี่ยวกับรหัสนี้: พยายามที่จะเรียกใช้มันจะไม่มีจุดหมายเนื่องจากระยะเวลาและจำนวนหน่วยความจำที่จะใช้


3

Golfscript - 52 46 (67)

วิธีการบังคับดุร้ายสำหรับผู้บุกรุกแบบแยกส่วนใน 46 ตัวอักษร คำนวณซ้ำ ^ (N-2) ด้วยจำนวนเต็มความแม่นยำโดยพลการ

n%(!\:A{~A{~;.3$-.!+1928049029:N((?**}/\/+N%}/

การใช้อัลกอริทึมแบบยุคลิดแบบขยายนั้นทำให้เราเพิ่ม 15 อักขระเท่านั้น

n%(!\:A{~A{~;.3$-:|!1\1928049029:N{@2$|3$/*-\|\:|%.}do;;**}/\/+N%}/

รหัสนี้มีรายละเอียดครบถ้วนเกี่ยวกับการโพสต์บล็อกของฉันรวมถึงทางเลือกบางอย่างสำหรับการคำนวณอินเวอร์สการคูณแบบแยกส่วน


1
ดี แต่ฉันคิดว่ายังมีตัวอักษรอย่างน้อยสองตัวที่จะได้รับการบันทึก แทนที่{*N%2<}ด้วย{*N%1=}เช่นเดียวกับในบล็อกและคุณสามารถคลองหลัง(; N,แต่แล้วในการดำเนินงานเป็นที่ไม่เกี่ยวข้อง-รายการคุณสามารถใช้ทฤษฎีบทเล็ก ๆ น้อย ๆ ของแฟร์มาต์โดยไม่ต้องรบกวนเกี่ยวกับด้านแบบแยกส่วนของการยกกำลัง - เพียงแค่ออกจากที่สำหรับเป็นระเบียบเรียบร้อยสุดท้าย - ดังนั้น recip N((?กลายเป็น
Peter Taylor

1
@Peter: {*N%1=}+จะพลาดกรณีที่มีตัวส่วนศูนย์ซึ่งจะใช้เวลาอย่างน้อย 3 ตัวอักษรเพื่อจัดการ ทำได้ดีเพียงแค่ทำ x ^ (N-2) แต่เราสามารถรับ 46 ตัวอักษรโดยใช้สิ่งนี้
Nabb

2

Lua 444 ตัวอักษร

ใช้งานได้กับตัวอย่างในหน้า wiki

3
2 1942
4 3402
5 4414

แต่อย่างใดไม่ได้ผลสำหรับตัวอย่างที่นี่ในหน้านี้ หากใครสามารถหาข้อผิดพลาด?

รุ่นที่ไม่ใช่กอล์ฟ:

-- Reconstruct shamir secret
-- convention, poly = {[0]=a0,a1,...,an}
i=io.read
f=math.fmod
w=1928049029
k=i():match"%d+"
x={} -- Will contain X values
y={} -- Will contain Y values
p={} -- will contain lagrange polynomials

-- Read data
for j=0,k-1 do
    x[j],y[j]=i():match("(%d+) (%d+)")
    print(j,x[j],y[j])
end
-- Multiplication and scaling function
function mul(p,q,s)
    -- multiply polies
    r={} -- poly to be returned
    for k=0,#p do 
        for l=0,#q do
            r[l+k]=r[l+k] or 0 -- if the coeff for degree l+k of x doesn't exist, put 0
            p[k]=p[k] or 0 -- if p hasn't got a coeff for x^k
            q[l]=q[l] or 0 -- idem for q
            r[l+k]=(r[l+k]+s*p[k]*q[l]%w -- calculate increment for coeff for x^(l+k) 
        end
    end
    -- Debugging
    io.write"Multiplied "
    printPoly(p)
    io.write"With       "
    printPoly(q)
    io.write("And scaling factor ",tostring(s),"\n")
    io.write"Yielding   "
    printPoly(r)
    return r
end

function printPoly(p) -- "Pretty" printing of the polynomial
    for k=#p,1,-1 do
        io.write(tostring(p[k] or 0),"x^",tostring(k),"+")
    end
    io.write(p[0])
    io.write"\n"
end
function egcd(a,b)
    if a == 0 then
        return b, 0, 1
    else
        local g, y, x = egcd(b % a, a)
        return g, x - math.floor(b / a) * y, y
    end
end

function inv(a,m)
    a=a>=0 and a or a+m
    local g,x,y = egcd(a,m)
    if g== 1 then
        return x%m
    else
        print(a,"has no inverse mod",m)
    end
end


-- generate lagrange polynomials
for j=0,#x do
    print("j=",j,"*********")
    for m=0,k-1 do
        if m~=j then -- if m==j, continue
            p[j]=p[j]or{[0]=1} -- if this poly doesn't exist, take 1
            p[j]=mul( p[j], {[0]=-x[m],1},inv(x[j]-x[m],w))-- multiply with (x-x_m)/(x_j-x_m)
            io.write"---------------------------------\n"
        end
    end
end
r=0 -- Result for x^0
for k=0,#p do
    print("l_"..k)
    printPoly(p[k]) -- print l_k
    r=r+f(y[k]*p[k][0],w) -- add coeff for x^0 to result
end
print("Secret was",f(r,w)) -- display result

Golfed (ไม่ใช้ฟิลด์ จำกัด ) 444 chars:

i=io.read f=math.fmod w=1928049029 k=i():match"%d+"x={}y={}p={}for j=0,k-1 do x[j],y[j]=i():match("(%d+) (%d+)")end
function mul(p,q,s)r={}for k=0,#p do for l=0,#q do r[l+k]=r[l+k]or 0 p[k]=p[k]or 0 q[l]=q[l]or 0 r[l+k]=f(r[l+k]+s*p[k]*q[l],w)end end return r end
for j=0,#x do for m=0,k-1 do if m~=j then p[j]=p[j]or{[0]=1}p[j]=mul(p[j],{[0]=-x[m],1},1/(x[j]-x[m]))end end end r=0 for k=0,#p do r=r+f(y[k]*p[k][0],w)end
print(f(r,w))

ตัวอย่างวิกิพีเดียไม่ได้ใช้ฟิลด์ จำกัด ซึ่งเป็นเรื่องน่าอายจริง ๆ ซึ่งน่าจะเป็นคำแนะนำที่มากขึ้น นั่นเป็นสาเหตุของความผิดพลาดของคุณ
aaaaaaaaaaaa

2

Java, 435 407 ตัวอักษร

import java.util.*;public class G{public static void main(String[]args){Scanner s=new Scanner(System.in);int i,k,n=s.nextInt();long N=1928049029L,x[]=new long[n],y[]=new long[n],z=0,l,c;for(i=n;i-->0;){x[i]=s.nextInt();y[i]=s.nextInt();}for(i=n;i-->0;){l=y[i];for(long j:x)if(x[i]!=j){c=1;for(long a=N+j-x[i],b=N,d=0,t;b>0;){t=d;d=c-a/b*d;c=t;t=b;b=a%b;a=t;}l=l*j%N*(c+N)%N;}z+=l;}System.out.println(z%N);}}

Ungolfed:

import java.util.*;
public class G {
    public static void main(String[] args) {
        Scanner s=new Scanner(System.in);
        int i,k,n=s.nextInt();
        long N=1928049029L,x[]=new long[n],y[]=new long[n],z=0,l,c;
        for (i=n; i-->0;) {
            x[i]=s.nextInt();
            y[i]=s.nextInt();
        }
        for (i=n; i-->0;) {
            l=y[i];
            for (long j:x)
                if (x[i]!=j) {
                    // Extended Euclid algorithm - iterative version -
                    // to find the reciprocal of j-x[i] (mod N)
                    c=1;
                    for (long a=N+j-x[i], b=N, d=0, t; b>0;) {
                        t=d; d=c-a/b*d; c=t;
                        t=b; b=a%b; a=t;
                    }
                    l = l*j%N;
                    l = l*(c+N)%N;
                }
                z+=l;
        }
        System.out.println(z%N);
    }
}

2

Haskell, 183

p=1928049029
a#0=(1,0)
a#b=let(s,t)=b#mod a b in(t,s-div a b*t)
s d=sum[y*product[z*fst((z-x)#p)|[z,_]<-d,z/=x]|[x,y]<-d]
main=interact$show.(`mod`p).s.map(map read.words).tail.lines
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.