Initial commit

This commit is contained in:
Marko Zivanovic
2014-11-30 20:21:32 +01:00
commit 6e603c1f55
10 changed files with 809 additions and 0 deletions
+2
View File
@@ -0,0 +1,2 @@
nb-configuration.xml
target
+1
View File
@@ -0,0 +1 @@
language: java
+22
View File
@@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2014 Marko Zivanovic
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
View File
+111
View File
@@ -0,0 +1,111 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>rs.in.zivanovic</groupId>
<artifactId>sss</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>${project.groupId}:${project.artifactId}</name>
<description>Implementation of the Shamir's Secret Sharing algorithm.</description>
<url>https://github.com/zmarko/sss</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<licenses>
<license>
<name>MIT license</name>
<url>http://opensource.org/licenses/MIT</url>
<distribution>repo</distribution>
</license>
</licenses>
<developers>
<developer>
<id>marko</id>
<name>Marko Zivanovic</name>
<email>marko@zivanovic.in.rs</email>
<url>http://marko.zivanovic.in.rs</url>
<roles>
<role>developer</role>
</roles>
<timezone>+1</timezone>
</developer>
</developers>
<scm>
<connection>scm:git:git@github.com:zmarko/sss.git</connection>
<developerConnection>scm:git:git@github.com:zmarko/sss.git</developerConnection>
<url>git@github.com:zmarko/sss.git</url>
</scm>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.1</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<autoVersionSubmodules>true</autoVersionSubmodules>
<useReleaseProfile>false</useReleaseProfile>
<releaseProfiles>release</releaseProfiles>
<goals>deploy</goals>
</configuration>
</plugin>
</plugins>
</build>
</project>
@@ -0,0 +1,215 @@
/*
* The MIT License
*
* Copyright 2014 Marko Zivanovic.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package rs.in.zivanovic.sss;
import java.math.BigInteger;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.Random;
/**
* Utility methods for generating, transforming, encoding and decoding input data into format that we can do the math
* with.
*/
public final class SasUtils {
private static final Random RANDOM = new SecureRandom();
private static final byte[] SIGNATURE = "SS".getBytes(StandardCharsets.UTF_8);
/**
* Encode any valid Unicode string to integer.
*
* @param str string to encode as integer.
* @return integer representation of the secret string.
*/
public static BigInteger encodeStringToInteger(String str) {
byte[] bytes = str.getBytes(StandardCharsets.UTF_8);
byte[] res;
if ((bytes[0] & 0b10000000) >> 7 == 1) {
res = new byte[bytes.length + 1];
res[0] = 0;
System.arraycopy(bytes, 0, res, 1, bytes.length);
} else {
res = bytes;
}
BigInteger r = new BigInteger(res);
assert r.compareTo(BigInteger.ZERO) > 0;
return r;
}
/**
* Decode integer encoded with {@link #encodeStringToInteger(java.lang.String) } back to Unicode string form.
*
* @param num integer to decode back to string.
* @return decoded string.
*/
@SuppressWarnings("empty-statement")
public static String decodeIntegerToString(BigInteger num) {
byte[] bytes = num.toByteArray();
int count;
for (count = 0; count < bytes.length && bytes[count] == 0; count++);
byte[] trimmed = new byte[bytes.length - count];
System.arraycopy(bytes, count, trimmed, 0, trimmed.length);
return new String(trimmed, StandardCharsets.UTF_8);
}
/**
* Generate first probable prime greater than the number specified.
*
* @param num lower bound for the generated probable prime
* @return probable prime greater than the specified number
*/
public static BigInteger generateFirstPrimeGreaterThan(BigInteger num) {
return num.nextProbablePrime();
}
/**
* Generate random probable prime guaranteed to be greater than the number specified.
*
* @param num lower bound for the generated probable prime
* @return random probable prime greater than the specified number
*/
public static BigInteger generateRandomPrimeGreaterThan(BigInteger num) {
BigInteger res = BigInteger.ZERO;
while (res.compareTo(num) <= 0) {
res = BigInteger.probablePrime(num.bitLength(), RANDOM);
}
return res;
}
/**
* Generate random number guaranteed to be less than the number specified.
*
* @param num upper bound of the generated random number
* @return random number guaranteed to be less than the specified number
*/
public static BigInteger generateRandomIntegerLessThan(BigInteger num) {
BigInteger r = null;
while (r == null || r.compareTo(num) >= 0) {
r = new BigInteger(num.bitLength(), RANDOM);
}
return r;
}
/**
* Generate random coefficients for the Shamir's Secret Sharing algorithm. First coefficient is filled with a known
* value and the rest of the coefficients are randomly generated, keeping them less than the specified prime.
*
* @param n number of coefficients to generate
* @param elementZero value of the first coefficient
* @param prime upper bound for randomly generated coefficients
* @return array of generated coefficients
*/
public static BigInteger[] generateRandomCoefficients(int n, BigInteger elementZero, BigInteger prime) {
BigInteger[] res = new BigInteger[n];
res[0] = elementZero;
for (int i = 1; i < n; i++) {
res[i] = SasUtils.generateRandomIntegerLessThan(prime);
}
return res;
}
/**
* Serialize secret share to binary message format. The message consists of the following fields:
* <ul>
* <li>header (ASCII string "SS")</li>
* <li>single byte indicating the ordinal number of this specific share in the series</li>
* <li>single integer (four bytes) indicating the length of the share data</li>
* <li>variable number of bytes (see previous item) representing share data</li>
* <li>single integer (four bytes) indicating the length of the prime data</li>
* <li>variable number of bytes (see previous item) representing prime data</li>
* </ul>
*
* @param share secret share to serialize
* @return byte array representing serialized secret share
*/
public static byte[] encodeToBinary(SecretShare share) {
if (share.getN() < 0 || share.getN() > 255) {
throw new IllegalArgumentException("Invalid share number, must be between 0 and 255");
}
byte[] shareData = share.getShare().toByteArray();
byte[] primeData = share.getPrime().toByteArray();
byte n = new Integer(share.getN()).byteValue();
int len = 9 + SIGNATURE.length + shareData.length + primeData.length;
ByteBuffer bb = ByteBuffer.allocate(len);
bb.put(SIGNATURE);
bb.put(n);
bb.putInt(shareData.length);
bb.put(shareData);
bb.putInt(primeData.length);
bb.put(primeData);
assert bb.position() == bb.capacity();
assert bb.hasArray();
return bb.array();
}
/**
* De-serialize secret share from binary message data. Serialization mechanism is detailed in {@link #encodeToBinary(rs.in.zivanovic.sss.SecretShare)
* }
*
* @param data binary data to de-serialize
* @return secret share data
*/
public static SecretShare decodeFromBinary(byte[] data) {
ByteBuffer bb = ByteBuffer.wrap(data);
try {
byte[] signature = new byte[SIGNATURE.length];
bb.get(signature);
if (!Arrays.equals(SIGNATURE, signature)) {
throw new IllegalArgumentException("signature missing");
}
byte n = bb.get();
int shareDataLen = bb.getInt();
byte[] shareData = new byte[shareDataLen];
bb.get(shareData);
int primeDataLen = bb.getInt();
byte[] primeData = new byte[primeDataLen];
bb.get(primeData);
BigInteger share = new BigInteger(shareData);
BigInteger prime = new BigInteger(primeData);
if (share.compareTo(BigInteger.ZERO) <= 0) {
throw new IllegalArgumentException("invalid share number");
}
if (prime.compareTo(BigInteger.ZERO) <= 0) {
throw new IllegalArgumentException("invalid prime");
}
return new SecretShare(n, share, prime);
} catch (BufferUnderflowException ex) {
throw new IllegalArgumentException(ex);
}
}
private SasUtils() {
}
}
@@ -0,0 +1,98 @@
/*
* The MIT License
*
* Copyright 2014 Marko Zivanovic.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package rs.in.zivanovic.sss;
import java.math.BigInteger;
import java.util.Objects;
/**
* Value class containing data necessary to fully describe single secret share in the series.
*/
public final class SecretShare {
private final int n;
private final BigInteger share;
private final BigInteger prime;
/**
* Construct secret share object with the specified data.
*
* @param n ordinal number of this specific share in the series
* @param share specific share data
* @param prime prime number used for the series
*/
public SecretShare(int n, BigInteger share, BigInteger prime) {
this.n = n;
this.share = share;
this.prime = prime;
}
public int getN() {
return n;
}
public BigInteger getShare() {
return share;
}
public BigInteger getPrime() {
return prime;
}
@Override
public int hashCode() {
int hash = 7;
hash = 79 * hash + this.n;
hash = 79 * hash + Objects.hashCode(this.share);
hash = 79 * hash + Objects.hashCode(this.prime);
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final SecretShare other = (SecretShare) obj;
if (this.n != other.n) {
return false;
}
if (!Objects.equals(this.share, other.share)) {
return false;
}
if (!Objects.equals(this.prime, other.prime)) {
return false;
}
return true;
}
@Override
public String toString() {
return "SecretShare{" + "n=" + n + ", share=" + share + ", prime=" + prime + '}';
}
}
@@ -0,0 +1,176 @@
/*
* The MIT License
*
* Copyright 2014 Marko Zivanovic.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package rs.in.zivanovic.sss;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
/**
* Implementation of the Shamir's Secret Sharing algorithm. Both splitting the secret into shares and joining the shares
* back into the secret are supported. Since arbitrary-precision integers are used, there is, effectively, no limit on
* the length of the secret data.
*
*/
public final class ShamirSecretSharing {
/**
* Split the secret into the specified total number of shares. Specified minimum threshold of shares will need to be
* present in order to join them back into the secret. Polynomial coefficients and prime modulo will be randomly
* chosen.
*
* @param secretString string to convert into number and split into shares
* @param total number of shares to generate
* @param threshold minimum number of shares required to successfully join back the secret
* @return list of shares
*/
public static List<SecretShare> split(String secretString, int total, int threshold) {
BigInteger secret = SasUtils.encodeStringToInteger(secretString);
return split(secret, total, threshold);
}
/**
* Split the secret into the specified total number of shares. Specified minimum threshold of shares will need to be
* present in order to join them back into the secret. Polynomial coefficients and prime modulo will be randomly
* chosen.
*
* @param secret number to split into shares
* @param total number of shares to generate
* @param threshold minimum number of shares required to successfully join back the secret
* @return list of shares
*/
public static List<SecretShare> split(BigInteger secret, int total, int threshold) {
BigInteger prime = SasUtils.generateFirstPrimeGreaterThan(secret);
BigInteger[] coeffs = SasUtils.generateRandomCoefficients(total, secret, prime);
return split(secret, coeffs, total, threshold, prime);
}
/**
* Split the secret into the specified total number of shares. Specified minimum threshold of shares will need to be
* present in order to join them back into the secret.
*
* @param secret number to split into shares
* @param coefficients random coefficients of the underlying polynomial
* @param total number of shares to generate
* @param threshold minimum number of shares required to successfully join back the secret
* @param prime to be used for finite field arithmetic
* @return list of shares
*/
public static List<SecretShare> split(BigInteger secret, BigInteger[] coefficients, int total, int threshold,
BigInteger prime) {
if (secret.compareTo(BigInteger.ZERO) <= 0) {
throw new IllegalArgumentException("secret must be positive integer");
}
if (prime.compareTo(secret) <= 0) {
throw new IllegalArgumentException("prime must be greater than secret");
}
if (coefficients.length < threshold) {
throw new IllegalArgumentException("not enough coefficients, need " + threshold + ", have " +
coefficients.length);
}
if (total < threshold) {
throw new IllegalArgumentException("total number of shares must be greater than or equal threshold");
}
List<SecretShare> shares = new ArrayList<>();
for (int i = 1; i <= total; i++) {
BigInteger x = BigInteger.valueOf(i);
BigInteger v = coefficients[0];
for (int c = 1; c < threshold; c++) {
v = v.add(x.modPow(BigInteger.valueOf(c), prime).multiply(coefficients[c]).mod(prime)).mod(prime);
}
shares.add(new SecretShare(i, v, prime));
}
return shares;
}
/**
* Join shares back into the secret.
*
* @param shares to join
* @return secret string
*/
public static String joinToUtf8String(List<SecretShare> shares) {
return SasUtils.decodeIntegerToString(join(shares));
}
/**
* Join shares back into the secret.
*
* @param shares to join
* @return secret number
*/
public static BigInteger join(List<SecretShare> shares) {
if (!checkSamePrimes(shares)) {
throw new IllegalArgumentException("shares not from the same series");
}
BigInteger res = BigInteger.ZERO;
for (int i = 0; i < shares.size(); i++) {
BigInteger n = BigInteger.ONE;
BigInteger d = BigInteger.ONE;
BigInteger prime = shares.get(i).getPrime();
for (int j = 0; j < shares.size(); j++) {
if (i != j) {
BigInteger sp = BigInteger.valueOf(shares.get(i).getN());
BigInteger np = BigInteger.valueOf(shares.get(j).getN());
n = n.multiply(np.negate()).mod(prime);
d = d.multiply(sp.subtract(np)).mod(prime);
}
}
BigInteger v = shares.get(i).getShare();
res = res.add(prime).add(v.multiply(n).multiply(d.modInverse(prime))).mod(prime);
}
return res;
}
/**
* Verify if all shares have the same prime. If they do not, then they are not from the same series and cannot
* possibly be joined.
*
* @param shares to check
* @return true if all shares have the same prime, false if not.
*/
private static boolean checkSamePrimes(List<SecretShare> shares) {
boolean ret = true;
BigInteger prime = null;
for (SecretShare share : shares) {
if (prime == null) {
prime = share.getPrime();
} else if (!prime.equals(share.getPrime())) {
ret = false;
break;
}
}
return ret;
}
private ShamirSecretSharing() {
}
}
@@ -0,0 +1,107 @@
/*
* The MIT License
*
* Copyright 2014 Marko Zivanovic.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package rs.in.zivanovic.sss;
import java.math.BigInteger;
import static org.junit.Assert.*;
import org.junit.Test;
public class SasUtilsTest {
private static final String s1 = "Hello World!";
public SasUtilsTest() {
}
@Test
public void testGenerateFirstPrimeGreaterThan() {
System.out.println("generateFirstPrimeGreaterThan");
BigInteger si1 = SasUtils.encodeStringToInteger(s1);
BigInteger p1 = SasUtils.generateFirstPrimeGreaterThan(si1);
assertTrue(p1.compareTo(si1) > 0);
}
@Test
public void testGenerateRandomPrimeGreaterThan() {
System.out.println("generateRandomPrimeGreaterThan");
BigInteger si1 = SasUtils.encodeStringToInteger(s1);
BigInteger p1 = SasUtils.generateRandomPrimeGreaterThan(si1);
assertTrue(p1.compareTo(si1) > 0);
}
@Test
public void testGenerateRandomIntegerLessThan() {
System.out.println("generateRandomIntegerLessThan");
BigInteger i = BigInteger.valueOf(100);
BigInteger r = SasUtils.generateRandomIntegerLessThan(i);
assertTrue(r.compareTo(i) < 0);
i = BigInteger.valueOf(100_000_000);
r = SasUtils.generateRandomIntegerLessThan(i);
assertTrue(r.compareTo(i) < 0);
}
@Test
public void testBinaryCodec() {
System.out.println("binaryCodec");
SecretShare src = new SecretShare(3, new BigInteger("100"), new BigInteger("200"));
byte[] data = SasUtils.encodeToBinary(src);
SecretShare dst = SasUtils.decodeFromBinary(data);
assertTrue(src.equals(dst));
}
@Test
public void testSecretCodec() {
System.out.println("secretCodec");
BigInteger bi = SasUtils.encodeStringToInteger(s1);
String d = SasUtils.decodeIntegerToString(bi);
assertTrue(s1.equals(d));
}
@Test(expected = java.lang.IllegalArgumentException.class)
public void testDecodeEmptyMessage() {
System.out.println("decodeEmptyMessage");
byte[] b = new byte[0];
SecretShare ss = SasUtils.decodeFromBinary(b);
}
@Test(expected = java.lang.IllegalArgumentException.class)
public void testDecodePartialMessage() {
System.out.println("decodePartialMessage");
SecretShare src = new SecretShare(3, new BigInteger("100"), new BigInteger("200"));
byte[] buff = SasUtils.encodeToBinary(src);
byte[] partial = new byte[buff.length / 2];
System.arraycopy(buff, 0, partial, 0, partial.length);
SecretShare ss = SasUtils.decodeFromBinary(partial);
}
@Test(expected = java.lang.IllegalArgumentException.class)
public void testDecodeDamagedHeaderMessage() {
System.out.println("decodeDamagedHeader");
SecretShare src = new SecretShare(3, new BigInteger("100"), new BigInteger("200"));
byte[] buff = SasUtils.encodeToBinary(src);
buff[0] = 'X';
SecretShare ss = SasUtils.decodeFromBinary(buff);
}
}
@@ -0,0 +1,77 @@
/*
* The MIT License
*
* Copyright 2014 Marko Zivanovic.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package rs.in.zivanovic.sss;
import java.math.BigInteger;
import java.util.*;
import static org.junit.Assert.*;
import org.junit.Test;
public class ShamirSecretSharingTest {
private static final BigInteger[] TEST_COEFFICIENTS = new BigInteger[3];
private static final BigInteger TEST_PRIME = BigInteger.valueOf(1613);
private static final BigInteger TEST_SECRET = BigInteger.valueOf(1234);
private static final List<SecretShare> SHARES;
static {
TEST_COEFFICIENTS[0] = TEST_SECRET;
TEST_COEFFICIENTS[1] = BigInteger.valueOf(166);
TEST_COEFFICIENTS[2] = BigInteger.valueOf(94);
SHARES = ShamirSecretSharing.split(TEST_SECRET, TEST_COEFFICIENTS, 6, 3, TEST_PRIME);
}
@Test
public void testSplit() {
System.out.println("split");
assertTrue(SHARES.get(0).getShare().compareTo(BigInteger.valueOf(1494)) == 0);
assertTrue(SHARES.get(1).getShare().compareTo(BigInteger.valueOf(329)) == 0);
assertTrue(SHARES.get(2).getShare().compareTo(BigInteger.valueOf(965)) == 0);
assertTrue(SHARES.get(3).getShare().compareTo(BigInteger.valueOf(176)) == 0);
assertTrue(SHARES.get(4).getShare().compareTo(BigInteger.valueOf(1188)) == 0);
assertTrue(SHARES.get(5).getShare().compareTo(BigInteger.valueOf(775)) == 0);
}
@Test
public void testJoinInsufficientShares() {
System.out.println("joinInsufficientShares");
List<SecretShare> shares = new ArrayList<>();
shares.add(SHARES.get(0));
shares.add(SHARES.get(5));
BigInteger joined = ShamirSecretSharing.join(shares);
assertTrue(joined.compareTo(TEST_SECRET) != 0);
}
@Test
public void testJoinSufficientShares() {
System.out.println("joinSufficientShares");
List<SecretShare> shares = new ArrayList<>();
shares.add(SHARES.get(3));
shares.add(SHARES.get(5));
shares.add(SHARES.get(1));
BigInteger joined = ShamirSecretSharing.join(shares);
assertTrue(joined.compareTo(TEST_SECRET) == 0);
}
}