我的大学有一个与Shamir Secret Sharing有关的学期项目。我的任务是实现一个代码,该代码可以将文件分成几部分然后重新构建。实际上,我已经实现了我的Shamir Secret Sharing代码,但我是在主要领域实现的。我的主管告诉我,我必须为扩展字段做。对于素数字段,我使用了BigInteger构造函数
final BigInteger prime = new BigInteger(secret.bitLength() + 1, CERTAINTY, random);
我将非常感谢能够帮助我弄清楚如何修改扩展字段代码的人。我使用这个构造函数生成256(2pow8)
String val="256";
final BigInteger prime = new BigInteger(String val);
我可以生成一个2的幂,但重建和生成股票的工作不正常。有什么建议吗?
我的代码是:
Shamir.java
import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.Random;
// final class means we can not extend class Shamir
public final class Shamir
{
//because of our shamir class is final and can not be instantiated we need static methods to this class which can..
// directly be accessed by shamir class without having to create a new object
public static SecretShare[] ndarje(int k, int n,final BigInteger secret, BigInteger prime, Random random)
{
// parameters of the method which are going to take the arguments from the static main method
// variable int n is the number of all users which will receive the secret
// variable int k is the number of participants needed to...
System.out.println("Prime Number: " + prime); // generation of prime number. We use BigInteger to generate it
// a vector of type BigInteger named coeff of size n which will hold the coefficients of the polynom
// construction of the polynom
//the code from line 41 to 76 generate random number which will stay close to variable x of the polynom
// for example f(x)= 120 + 123x + 13 xpow2 ; 120 , 123 and 13 are creating below till line 66 of code
final BigInteger[] coeff = new BigInteger[n];
coeff[0] = secret; // the first coefficient of polynom the one which is free is the secret
for (int i = 1; i < n; i++) // we start from 1 because f(0) iis the secret information
{
// BigInteger b = new BigInteger(something here that can be match with BigInteger constructor) this create new reference
BigInteger b ;
//boolean isin=true;
while (true) // go to an endless loop
{
// prime.bitLength() return number of bits in the minimal two's-complement representation of this BigInteger
// also instances of the class can access methods ***
// the constructor Constructs a randomly generated BigInteger,
//uniformly distributed over the range 0 to (2numBits - 1), inclusive
b = new BigInteger(prime.bitLength(), random);
// b can be any number from 1 till p-1
// compareTo is one of the method of BigInteger class
// it Compares this BigInteger with the specified BigInteger.
// Zero is the field of the BigInteger class and also an instance of this class which is accessed by operator .
// its value is 0
// this comparison means that if our b is bigger than this BigInteger.Zero
// the second comparison means that our r should be smaller than prime number
if (b.compareTo(BigInteger.ZERO) > 0 && b.compareTo(prime) < 0)
{
// isin=false;
break; // we need it to stop the endless loop if our condition upper are fulfilled
} // close if
} // close while
coeff[i] = b; //pass this value to the vector which hold coeff
} // close for loop
// share the secret to the all participants each point of the polynom will go to one of them
// create an array of type SecretShare of size n which will contain all pair of shares
final SecretShare[] shares = new SecretShare[n];
for (int x = 1; x <=n; x++) // loop till x=n , it will start from 1
{
// a0 which means the free variable of polynomial
BigInteger a0= secret;
for (int j = 1; j< k; j++) // loop till exp<k
{
// add method of BigInteger public BigInteger add(BigInteger val)
// Returns a BigInteger whose value is (this + val) where this is value of secret = a0
// polynom is in our case a0 + a1x+a2xpow2+...+a(k-1)pow(k-1) mod p where coeff[j]..
// is the coeffiecent of x of our polynom
// multiply method will Returns a BigInteger whose value is (this * val).
// .valueof(x) method will return the value of x=(1,2,3...p-1)
// pow(j) will return the value of k (1,2,3...k-1)
// mod method will return a BigInteger whose value is (this mod prime).
// in other words the statement below will compute polynom a0+a1x+a2xpow2+...+a(k-1)pow(k-1)
a0= a0.add(coeff[j].multiply(BigInteger.valueOf(x).pow(j).mod(prime))).mod(prime);
}
shares[x-1] = new SecretShare(x, a0);
System.out.println(shares[x-1]);
}
return shares; // return shares which must match with return type of the vector which is a array
} // close ndarje (name of my method) method
// interpolation
// second method
public static BigInteger kombinimi(final SecretShare[] shares, final BigInteger prime)
{
// interpolation
// new instance variables of this second method which its name is a0 and its value is zero
BigInteger a0= BigInteger.ZERO;
for(int i= 0; i < shares.length; i++)
{
BigInteger numerator = BigInteger.ONE;
BigInteger denominator = BigInteger.ONE;
for(int j = 0; j< shares.length; j++)
{
if(i != j) {
//if(i != j) { } has the same function as we can write
// if (i==j) continue;
// the meaning to both of them is :If not the same value
// it is calling getNumber method which assign to int startposition value which is returned by getNumber method
// so it will return numbers [1,2,3,4,5..,n]
// one example a0=sum{(yi)product(xj/xj-xi)} for i=1 to number of needed client to reconstruct secret out of..
// total number of clients. and i and j should not be the same to the production
// so this will take xi
int startposition = shares[i].getNumber();
// this will take xj
int nextposition = shares[j].getNumber();
// so the steps now we need to do are.. After we take the values of xi [1,2,3,4..]
// we need to calculate xj which below i called it numerator
//and we also need to calculate xj-xi
//negate and mod are also methods of Big Integer we need to use here
numerator = numerator.multiply(BigInteger.valueOf(nextposition)).mod(prime);
// (numerator * nextposition) % prime;
denominator = denominator.multiply(BigInteger.valueOf( nextposition - startposition)).mod(prime);
// (denominator * ( nextposition-startposition)) % prime;
} // close if
} // close for
// it is calling getShare method which assign to BigInteger value value which is returned by getShare method
// so it will return yi
BigInteger value = shares[i].getShare();
// tmp will take lets say y1*[ x2*x3/(x2-x1)(x3-x1)]
BigInteger tmp = value.multiply(numerator) . multiply(inv(denominator, prime));
a0 = prime.add(a0).add(tmp) . mod(prime);
// (prime + a+ (value * numerator * inv(denominator))) % prime;
}
System.out.println("The secret is: " + a0+ "\n");
return a0;
}
// method gcdD
private static BigInteger[] gcdD(BigInteger a, BigInteger b)
{
if (b.compareTo(BigInteger.ZERO) == 0)
return new BigInteger[] {a, BigInteger.ONE, BigInteger.ZERO};
else
{
BigInteger n = a.divide(b);
BigInteger c = a.mod(b);
BigInteger[] r = gcdD(b, c);
return new BigInteger[] {r[0], r[2], r[1].subtract(r[2].multiply(n))};
} // close else
} // close method
// this method is called to - multiply(modInverse(denominator, prime)) where denominator=k and prime=simplenumber
private static BigInteger inv(BigInteger d, BigInteger simplenumber)
{
d = d.mod(simplenumber);
BigInteger r = (d.compareTo(BigInteger.ZERO) == -1) ? (gcdD(simplenumber, d.negate())[2]).negate() : gcdD(simplenumber,d)[2];
return simplenumber.add(r).mod(simplenumber);
} // close method
public static void main(final String[] args)
{
// main method
// its static method so we can access directly our static methods above by using name of the class
//use this BigInteger constructor - BigInteger(String val) which..
//Translates the decimal String representation of a BigInteger ("140") into a BigInteger.
// so our secret number is 140
// this is the way if we do not want to get secret from command line
// final BigInteger secret = new BigInteger("140");
// take the argument from command line
if (args.length < 3) {
System.out.println("Dont forget to put k-number of clients needed to reconstruct the polynom");
System.out.println("n-number of total clients ");
System.out.println("And the third number is secret you want to deliver in this distributed system");
System.out.println("first number you will put is k , second is n and third is secret");
} else {
// final int CERTAINTY = 256;
final int numBits = 10;
// SecureRandom class which is child of java.lang.Object , its constructor Constructs a secure random number generator
// (RNG) implementing the default random number algorithm.
final SecureRandom random = new SecureRandom();
BigInteger secret=new BigInteger(args[2] );
int k=Integer.parseInt(args[0] );
int n=Integer.parseInt(args[1] );
final BigInteger prime= new BigInteger(numBits, random);
// -----------------------------------------------------------------------------------------------------------------------------------------
//Use BigInteger constructor-BigInteger(int bitLength, int certainty, Random rnd) which..
//Constructs a randomly generated positive BigInteger that is probably prime, with the specified bitLength.
// prime number must be longer then secret number
//final BigInteger prime = new BigInteger(secret.bitLength() + 1, CERTAINTY, random);
// -----------------------------------------------------------------------------------------------------------------------------------------
// k- at least k secret parts are needed to reconstruct the polynom
// n- there are n persons that get secret parts
// the order matters so we must write them (parameters) in order like the order of ndarje method
final SecretShare[] s = Shamir.ndarje(k, n,secret, prime, random);
//when use any combination of 2 parts of secret we will not get back our secret number we delivered to all participants
SecretShare[] sharesToViewSecret = new SecretShare[] {s[2],s[1]}; // 0 & 1
BigInteger result = Shamir.kombinimi(sharesToViewSecret, prime);
//when use any combination of 2 parts of secret we will not get back our secret number(140) we delivered to all participants
sharesToViewSecret = new SecretShare[] {s[0],s[1],s[2]}; // 1 & 4
result = Shamir.kombinimi(sharesToViewSecret, prime);
// here also
sharesToViewSecret = new SecretShare[] {s[5],s[1],s[3],s[4]}; // 0 & 1 & 3 & 4
result = Shamir.kombinimi(sharesToViewSecret, prime);
// but here we can get back our secret because the number of participants which reconstruct the polynom is >=6 , exactly 6
sharesToViewSecret = new SecretShare[] {s[2],s[1],s[3],s[4],s[6],s[10]}; // 0 & 1 & 3 & 4& 6 & 10
result = Shamir.kombinimi(sharesToViewSecret, prime);
// but here we can get back our secret because the number of participants which reconstruct the polynom is >=6 , exactly 7
sharesToViewSecret = new SecretShare[] {s[7],s[2],s[11],s[9],s[6],s[10],s[8]}; // 7 & 2 & 11 & 9 & 6 & 10 & 8
result = Shamir.kombinimi(sharesToViewSecret, prime);
}
}
}
SecretShare.java
import java.math.BigInteger;
public class SecretShare
{
// instances
private final int number;
private final BigInteger share;
// the constructor of the class
public SecretShare(final int numri, final BigInteger shperndaje)
{
this.number = numri;
this.share = shperndaje;
}
// getter methods
public int getNumber()
{
return number;
}
// getter methods return share
public BigInteger getShare()
{
return share;
}
@Override
public String toString()
{
// String concatenation
return "Secret which will share to all client is : [num=" + number + ", share=" + share +"]";
}
}