Thực hiện tái thiết chia sẻ bí mật của Shamir


11

Kế hoạch chia sẻ bí mật của Shamir là một cách đơn giản để bảo vệ bí mật bằng cách chia nó thành nhiều phần cần thiết để tái cấu trúc nó.

Nhiệm vụ của bạn là triển khai tái cấu trúc Chia sẻ bí mật của Shamir trên Trường hữu hạn được xác định bởi số nguyên tố 1928049029. Nếu bạn có bất kỳ nghi ngờ gì về ý nghĩa của điều này, chỉ cần hỏi hoặc xem Số học trường hữu hạn & số lượng trường hữu hạn trong wikipedia (nhiều tài nguyên dưới đây).

Đầu vào

Đầu vào được thực hiện bằng cách sử dụng stdin. Đầu tiên đến một số nguyên k, sau đó k dòng tiếp theo. Mỗi dòng này chứa một cặp số nguyên x yđại diện cho một bí mật. Nói cách khác f(x) = ytrong đa thức ban đầu được sử dụng để xây dựng các bí mật.

Số lượng bí mật được đưa ra luôn đủ để xây dựng bí mật tương ứng.

Đầu ra

Đầu ra để stdout bí mật được xây dựng lại.

Ví dụ

Đầu vào:

5         
1 564797566
2 804114535
4 1354242660
6 1818201132
7 503769263

Đầu ra:

1234

Đầu vào:

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

Đầu ra:

456457856

Tài nguyên

Bài viết trên Wikipedia

Giấy

Trường hữu hạn Nguồn: Wikipedia

Số học trường hữu hạn Nguồn: Wikipedia

Đa thức Lagrange Nguồn: Wikipedia

Chương về số học trường hữu hạn

Câu trả lời:


4

bash, 271 ký tự

r () {
[$ {1/0 /}] && {r $ (($ 2% $ 1)) $ 1; ((t = u, u = v- $ 2 / $ 1 * u, v = t));}
}
đọc
((N = 1928049029, n = 0))
trong khi đọc x [$ n] y [$ n]
làm ((n ++))
làm xong
cho ((i = n; z = (z + l)% N, i -;)) làm
cho ((j = n, l = y [i]; j -;)) làm
((u = 0, v = 1, d = x [j] -x [i], M = N + d))
r MN
[$ {d / 0 /}] && ((l = l * x [j]% N * (u + N)% N))
làm xong
làm xong
tiếng vang $ z

Các dòng mới có thể được thay thế trong hầu hết các trường hợp bằng dấu chấm phẩy, nhưng tôi không nghĩ có bất kỳ khoảng trắng không cần thiết nào.

(Hôm nay tôi đã không nhận ra rằng số nguyên của bash là 64 bit - rất hữu ích).

Đối với bash, GCD đệ quy (khai thác trạng thái toàn cầu) dường như gọn hơn so với phép lặp. Điều này chủ yếu là đơn giản; mẹo thú vị [ ${d/0/} ]&&foolà hiệu quảif [ $d -ne 0 ];then foo;fi


Đẹp! Tôi không bao giờ mong đợi để xem một câu trả lời bash cho vấn đề này. +1
Juan

@Juan, tôi bắt đầu thực hiện nó ở Perl, và chán ngấy với việc buộc nó phải phân chia số nguyên thay vì thả nổi. Và dù sao thì tôi cũng biết bash tốt hơn, vì vậy nó liên quan đến việc đập đầu vào tường ít hơn.
Peter Taylor

3

199 ký tự trong Octave:

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) ký tự

Nếu bạn không quan tâm đến việc đạt được kết quả trong tuần này, thì 65 ký tự là đủ:

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

Nhưng nếu bạn đang tìm kiếm hiệu quả, nó sẽ hơi dài hơn ở mức 86 ký tự:

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

Điều này được mổ xẻ chi tiết hơn nhiều so với tôi muốn lặp lại ở đây trên blog của tôi .


Chủ yếu không phải là công việc của tôi, nhưng viết rất nhiều từ Nabb cho 47 ký tự:

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

Lưu ý: Tôi chỉ có lý do về mã này: cố gắng chạy nó sẽ là vô nghĩa với thời lượng và dung lượng bộ nhớ mà nó sẽ sử dụng.


3

Golfscript - 52 46 (67)

Một cách tiếp cận vũ phu cho nghịch đảo mô-đun trong 46 ký tự. Liên tục tính toán một ^ (N-2) với các số nguyên chính xác tùy ý.

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

Việc thực hiện thuật toán Euclide mở rộng chỉ khiến chúng tôi tốn thêm 15 ký tự.

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

Mã này được chi tiết đầy đủ trên bài đăng trên blog của tôi , bao gồm một số lựa chọn thay thế để tính toán nghịch đảo nhân mô-đun.


1
Đẹp, nhưng tôi nghĩ vẫn còn ít nhất hai ký tự được lưu. Thay thế {*N%2<}bằng {*N%1=}như trong blog và bạn có thể bỏ qua (;sau N,. Nhưng sau đó, đối với mục nhập hiệu suất không liên quan, bạn có thể sử dụng định lý nhỏ của Fermat mà không cần bận tâm về khía cạnh mô đun của lũy thừa - chỉ cần để điều đó cho gọn gàng cuối cùng - vì vậy người nhận sẽ trở thành N((?.
Peter Taylor

1
@Peter: {*N%1=}+sẽ bỏ lỡ trường hợp có mẫu số 0, sẽ mất ít nhất 3 ký tự để xử lý. Rất tốt khi chỉ cần làm x ^ (N-2), chúng ta thực sự có thể nhận được 46 ký tự bằng cách này.
Nabb

2

Lua 444 Chars

Hoạt động cho ví dụ trên trang wiki

3
2 1942
4 3402
5 4414

Nhưng bằng cách nào đó không làm việc cho các ví dụ ở đây trên trang này. Nếu ai có thể tìm thấy lỗi?

Phiên bản không chơi gôn:

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

Đã đánh gôn (không sử dụng trường hữu hạn), ký tự 444:

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

Ví dụ Wikipedia không sử dụng một trường hữu hạn, điều này thực sự đáng xấu hổ, điều đó sẽ mang tính hướng dẫn nhiều hơn. Đó rất có thể là nguồn gốc của lỗi của bạn.
aaaaaaaaaaaa

2

Java, 435 407 ký tự

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

Ung dung:

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