Shamir'in Gizli Paylaşım rekonstrüksiyonunu uygulayın


11

Shamir'in gizli paylaşım şeması , bir sırrı, yeniden yapılandırmak için gereken birkaç parçaya bölerek korumanın basit bir yoludur.

Göreviniz, Shamir'in Gizli Paylaşım rekonstrüksiyonunu asal tarafından tanımlanan Sonlu Alan üzerinde uygulamaktır 1928049029. Bunun ne anlama geldiği konusunda herhangi bir şüpheniz varsa , wikipedia'da Sonlu Alan ve Sonlu Alan Aritmetiği'ni sorun veya bakın (daha fazla kaynak aşağıdadır).

Giriş

Giriş stdin kullanılarak yapılır. Önce bir tamsayı gelir k, ardından k çizgileri gelir . Bu satırların her biri x ybir sırrı temsil eden bir çift tamsayı içerir . Diğer bir deyişle f(x) = y, sırları oluşturmak için kullanılan orijinal polinomda.

Verilen sırların sayısı her zaman ilgili sırrı oluşturmak için yeterlidir.

Çıktı

Çıktı yeniden yapılandırılmış sır stdout.

Örnekler

Giriş:

5         
1 564797566
2 804114535
4 1354242660
6 1818201132
7 503769263

Çıktı:

1234

Giriş:

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

Çıktı:

456457856

kaynaklar

Wikipedia makalesi

kâğıt

Sonlu alan Kaynak: Wikipedia

Sonlu alan aritmetiği Kaynak: Wikipedia

Lagrange polinomu Kaynak: Wikipedia

Sonlu Alan Aritmetiği Bölümü

Yanıtlar:


4

bash, 271 karakter

R () {
[$ {1/0 /}] && {r $ (($ 2% 1 $)) $ 1; ((t = u, u = v- $ 2 / $ 1 * u, v = t));}
}
okumak
((N = 1928049029, n = 0))
okunurken x [$ n] y [$ n]
((N ++)) do
tamam
do, - (z = (Z + l), N% i) (I, n =) için
do, - (j) [i] (i = n, l = y) için
((U = 0, v = 1, D = x [j] -x [i], E = K + d))
r MN
[$ {d / 0 /}] && ((l = l * x [j]% N * (u + N)% N))
tamam
tamam
echo $ z

Yeni satırlar çoğu durumda noktalı virgülle değiştirilebilir, ancak gereksiz bir boşluk olduğunu düşünmüyorum.

(Bugün daha önce bash tamsayılarının 64 bit olduğunu fark etmemiştim - çok yararlı).

Bash için özyinelemeli GCD (küresel devleti sömüren) yinelemeli olandan daha kompakt görünmektedir. Bu çoğunlukla basittir; ilginç hiledir [ ${d/0/} ]&&fooetkin bir olanif [ $d -ne 0 ];then foo;fi


Güzel! Bu soruna bir bash cevabı görmeyi hiç beklemiyordum. +1
Juan

@Juan, Perl'de yapmaya başladım ve yüzmek yerine tamsayı bölmesi yapmaya zorlamak zorunda kaldım. Ve yine de bash'ı daha iyi biliyorum, bu yüzden kafayı duvara daha az atmayı içeriyor.
Peter Taylor

3

Oktav'da 199 karakter:

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 111 ve 112 110 109 65 (86) karakter

Bu hafta sonuç almayı umursamıyorsanız, 65 karakter yeterlidir:

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

Ancak verimlilik arıyorsanız, 86 karakterden biraz daha uzun:

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

Bu, blogumda tekrarlamak istediğimden çok daha ayrıntılı bir şekilde incelendi .


Temelde benim işim değil, Nabb'dan ağır bir şekilde beşiklemek 47 karakter veriyor:

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

Not: Ben sadece bu kod hakkında mantıklı: çalıştırmak için kullanacağınız bellek uzunluğu ve zaman miktarı göz önüne alındığında anlamsız olurdu.


3

Golf Yazıları - 52 46 (67)

46 karakterde modüler tersler için kaba kuvvet yaklaşımı. Bir ^ (N-2) 'yi rasgele hassasiyet tamsayılarıyla tekrar tekrar hesaplar.

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

Genişletilmiş Öklid algoritmasını uygulamak bize sadece 15 karakter daha ekler.

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

Bu kod, modüler çarpım tersini hesaplamak için bazı alternatifler de dahil olmak üzere blog yayınımda tamamen ayrıntılı .


1
Güzel, ama bence hala kurtarılacak en az iki karakter var. Blogdaki {*N%2<}ile değiştirin {*N%1=}ve (;sonradan vazgeçebilirsiniz N,. Ama sonra performansla alakasız giriş için, Fermat'ın küçük teoremini üssün modüler tarafı hakkında rahatsız etmeden kullanabilirsiniz - sadece son derleme için bırakın - böylece recip olur N((?.
Peter Taylor

1
@Peter: İşlenecek {*N%1=}+en az 3 karakter alacak olan payda sıfır ile davayı özleyecek. Sadece x ^ (N-2) yaparken iyi bir yakalama, aslında bunu kullanarak 46 karakter alabiliriz.
Nabb

2

Lua 444 Karakterleri

Wiki sayfasındaki örnek için çalışır

3
2 1942
4 3402
5 4414

Ancak bir şekilde bu sayfadaki örnekler için çalışmaz. Birisi hatayı bulabilirse?

Golfsiz sürüm:

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

Golf (sonlu alan kullanmıyor), 444 karakter:

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 örneği, gerçekten çok utanç verici olan çok daha öğretici olan sınırlı bir alan kullanmaz. Büyük olasılıkla hatanızın kaynağı budur.
aaaaaaaaaaaa

2

Java, 435407 karakter

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.