package meerkat.crypto.secretsharing.shamir;

import meerkat.crypto.utils.concrete.Fp;
import meerkat.crypto.utils.GenerateRandomPrime;
import org.factcenter.qilin.primitives.CyclicGroup;
import org.factcenter.qilin.primitives.concrete.Zn;
import org.junit.Before;
import org.junit.Test;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * Created by Tzlil on 1/29/2016.
 */
public class SecretSharingTest {

    SecretSharing[] secretSharingArray;
    BigInteger[] secrets;
    CyclicGroup<BigInteger> group;
    int tests = 1 << 10;
    Random random;
    BigInteger p = GenerateRandomPrime.SafePrime100Bits;
    BigInteger q = p.subtract(BigInteger.ONE).divide(BigInteger.valueOf(2));

    @Before
    public void settings(){
        group = new Zn(q);
        int t = 9;
        int n = 20;
        random = new Random();
        secretSharingArray = new SecretSharing[tests];
        secrets = new BigInteger[tests];

        for (int i = 0; i < secretSharingArray.length; i++){
            secrets[i] = group.sample(random);
            secretSharingArray[i] = new SecretSharing(t,n,secrets[i],random,q);
        }
    }

    public void oneTest(SecretSharing secretSharing, BigInteger secret) throws Exception {
        int t = secretSharing.getT();
        int n = secretSharing.getN();
        Polynomial.Point[] shares = new Polynomial.Point[t + 1];
        List<Integer> indexes = new ArrayList<Integer>(n);
        for (int i = 1 ; i <= n; i ++){
            indexes.add(i);
        }
        for (int i = 0 ; i < shares.length ; i++){
            shares[i] = secretSharing.getShare(indexes.remove(random.nextInt(indexes.size())));
        }
        BigInteger calculated = SecretSharing.recoverSecret(shares,new Fp(q));
        assert (secret.equals(calculated));
    }

    @Test
    public void secretSharingTest() throws Exception {
        for (int i = 0 ; i < secretSharingArray.length; i ++){
            oneTest(secretSharingArray[i],secrets[i]);
        }
    }
}
