샤미르의 비밀 공유 재구성을 구현하십시오


11

Shamir의 비밀 공유 체계 는 비밀을 재구성하는 데 필요한 여러 부분으로 나누어 비밀을 보호하는 간단한 방법입니다.

당신의 임무는 소수에 의해 정의 된 유한 필드에 Shamir의 비밀 공유 재구성을 구현 하는 것 1928049029입니다. 이것이 의미하는 바에 대해 의문이있는 경우 Wikipedia에서 유한 필드 및 유한 필드 산술 을 요청하거나 참조하십시오 (아래 추가 리소스 참조).

입력

입력은 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

유한 필드 산술에 관한 장

답변:


4

강타, 271 자

아르 자형(){
[$ {1 / 0 /}] && {r $ (($ 2 % $ 1)) $ 1; ((t = u, u = v- $ 2 / $ 1 * u, v = t));}
}
읽다
((N = 1928049029, n = 0))
읽는 동안 x [$ n] y [$ n]
do ((n ++))
끝난
for ((i = n; z = (z + 1) % N, i-;)) do
for ((j = n, l = y [i]; j-;)) do
((u = 0, v = 1, d = x [j] -x [i], M = N + d))
r MN
[$ {d / 0 /}] && ((l = l * x [j] % N * (u + N) % N))
끝난
끝난
에코 $ z

줄 바꿈은 대부분의 경우 세미콜론으로 대체 될 수 있지만 불필요한 공백이 없다고 생각합니다.

(나는 오늘 bash의 정수가 64 비트라는 것을 깨닫지 못했습니다. 매우 유용합니다).

bash의 경우 재귀 적 GCD (글로벌 상태 탐색)는 반복적 인 것보다 압축 가능한 것으로 보입니다. 이것은 대부분 간단합니다. 재미있는 트릭은 [ ${d/0/} ]&&foo효율적이다if [ $d -ne 0 ];then foo;fi


좋은! 나는이 문제에 대한 bash 답변을 기대하지 않았습니다. +1
Juan

@ Juan, 나는 Perl에서 그것을 시작했고 float 대신 정수 나누기를 강요해야했습니다. 어쨌든 나는 배쉬를 잘 알고 있으므로 벽에 머리를 두드리는 것이 적습니다.
피터 테일러

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

골프 스크립트 -52 46 (67)

46 자의 모듈 식 역수에 대한 무차별 대입 방식. 임의의 정밀 정수로 a ^ (N-2)를 반복적으로 계산합니다.

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

확장 된 유클리드 알고리즘을 구현하는 데 추가 15 자만 소요됩니다.

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

이 코드는 모듈 식 곱셈 역을 계산하기위한 몇 가지 대안을 포함하여 내 블로그 게시물 에 자세히 설명되어 있습니다.


1
좋았지 만 여전히 최소 2 개의 문자를 저장해야한다고 생각합니다. 교체 {*N%2<}{*N%1=}블로그와 같이 당신은 도랑 수 있습니다 (;후를 N,. 그러나 성능이 중요하지 않은 항목의 경우 지수의 모듈 측면에 신경 쓰지 않고 Fermat의 작은 정리를 사용할 수 있습니다. 마지막 정리를 위해 그대로 두십시오 N((?.
피터 테일러

1
@Peter : {*N%1=}+분모가 0 인 경우를 놓치면 처리하는 데 3 자 이상이 필요합니다. x ^ (N-2)를하는 것만으로도 잘 잡히지 만 실제로 이것을 사용하여 46자를 얻을 수 있습니다.
Nabb

2

루아 444 Chars

위키 페이지의 예제에서 작동합니다.

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

골프 (유한 필드를 사용하지 않음), 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))

Wikipedia 예제는 유한 필드를 사용하지 않습니다. 유한 필드는 실제로 수치 스럽습니다. 그것은 오류의 원인 일 가능성이 높습니다.
aaaaaaaaaaaa

2

자바, 435407

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

언 골프 드 :

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

하스켈, 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.