61 static int prime = 257;
72 unsigned long mix(
unsigned long a,
unsigned long b,
unsigned long c)
74 a=a-b; a=a-c; a=a^(c >> 13);
75 b=b-c; b=b-a; b=b^(a << 8);
76 c=c-a; c=c-b; c=c^(b >> 13);
77 a=a-b; a=a-c; a=a^(c >> 12);
78 b=b-c; b=b-a; b=b^(a << 16);
79 c=c-a; c=c-b; c=c^(b >> 5);
80 a=a-b; a=a-c; a=a^(c >> 3);
81 b=b-c; b=b-a; b=b^(a << 10);
82 c=c-a; c=c-b; c=c^(b >> 15);
87 unsigned long seed = mix(clock(), time(NULL), getpid());
91 int nonzero_random(
int modulo) {
92 int range = modulo - 1;
94 #if defined (HAVE_ARC4RANDOM)
95 return arc4random_uniform(range) + 1;
97 return rand() % range + 1;
107 int modular_exponentiation(
int base,
int exp,
int mod)
111 else if (exp%2 == 0) {
112 int mysqrt = modular_exponentiation(base, exp/2, mod);
113 return (mysqrt*mysqrt)%mod;
116 return (base * modular_exponentiation(base, exp-1, mod))%mod;
127 int * split_number(
int number,
int n,
int t) {
128 int * shares = malloc(
sizeof(
int)*n);
136 for (i = 1; i < t; ++i)
139 coef[i] = nonzero_random(prime - 1);
142 for (x = 0; x < n; ++x)
147 for (i = 1; i < t; ++i)
149 int temp = modular_exponentiation(x+1, i, prime);
151 y = (y + (coef[i] * temp % prime)) % prime;
155 y = (y + prime) % prime;
164 void Test_split_number(CuTest* tc) {
168 int * test = split_number(1234, 50, 20);
175 CuAssertIntEquals(tc, 0, 0);
184 int * gcdD(
int a,
int b) {
185 int * xyz = malloc(
sizeof(
int) * 3);
198 xyz[2] = r[1]-r[2]*n;
211 int modInverse(
int k) {
218 xyz = gcdD(prime,-k);
221 xyz = gcdD(prime, k);
227 return (prime + r) % prime;
237 int join_shares(
int *xy_pairs,
int n) {
247 for (i = 0; i < n; ++i)
251 for (j = 0; j < n; ++j)
254 startposition = xy_pairs[i*2];
255 nextposition = xy_pairs[j*2];
256 numerator = (numerator * -nextposition) % prime;
257 denominator = (denominator * (startposition - nextposition)) % prime;
262 value = xy_pairs[i * 2 + 1];
264 secret = (secret + (value * numerator * modInverse(denominator))) % prime;
268 secret = (secret + prime) % prime;
275 void Test_join_shares(CuTest* tc) {
284 for (j = 0; j < count; ++j)
286 int * test = split_number(j, n, t);
289 for (i = 0; i < n; ++i)
292 shares[i*2 + 1] = test[i];
296 int result = join_shares(shares, n);
300 CuAssertIntEquals(tc, j, result);
311 char ** split_string(
char * secret,
int n,
int t) {
312 int len = strlen(secret);
314 char ** shares = malloc (
sizeof(
char *) * n);
317 for (i = 0; i < n; ++i)
325 shares[i] = (
char *) malloc(2*len + 6 + 1);
327 sprintf(shares[i],
"%02X%02XAA",(i+1),t);
332 for (i = 0; i < len; ++i)
335 int letter = secret[i];
338 letter = 256 + letter;
342 int * chunks = split_number(letter, n, t);
345 for (j = 0; j < n; ++j)
347 if (chunks[j] == 256) {
348 sprintf(shares[j] + 6+ i * 2,
"G0");
350 sprintf(shares[j] + 6 + i * 2,
"%02X", chunks[j]);
363 void free_string_shares(
char ** shares,
int n) {
366 for (i = 0; i < n; ++i)
375 char * join_strings(
char ** shares,
int n) {
381 int len = (strlen(shares[0]) - 6) / 2;
383 char * result = malloc(len + 1);
391 for (i = 0; i < n; ++i)
393 codon[0] = shares[i][0];
394 codon[1] = shares[i][1];
396 x[i] = strtol(codon, NULL, 16);
399 for (i = 0; i < len; ++i)
401 int *chunks = malloc(
sizeof(
int) * n * 2);
403 for (j = 0; j < n; ++j)
407 codon[0] = shares[j][6 + i * 2];
408 codon[1] = shares[j][6 + i * 2 + 1];
410 if (memcmp(codon,
"G0",2) == 0) {
411 chunks[j*2 + 1] = 256;
413 chunks[j*2 + 1] = strtol(codon, NULL, 16);
418 char letter = join_shares(chunks, n);
424 sprintf(result + i,
"%c",letter);
432 void Test_split_string(CuTest* tc) {
436 char * phrase =
"This is a test of Bücher and Später.";
441 for (i = 0; i < count; ++i)
443 char ** result = split_string(phrase, n, t);
446 char * answer = join_strings(result, t);
447 CuAssertStrEquals(tc, phrase, answer);
451 answer = join_strings(result, n);
452 CuAssertStrEquals(tc, phrase, answer);
455 free_string_shares(result, n);
467 char ** result = split_string(secret, n, t);
469 int len = strlen(secret);
470 int key_len = 6 + 2 * len + 1;
473 char * shares = malloc(key_len * n + 1);
475 for (i = 0; i < n; ++i)
477 sprintf(shares + i * key_len,
"%s\n", result[i]);
480 free_string_shares(result, n);
487 void trim_trailing_whitespace(
char *str) {
498 while ( (l > 0) && (( str[l - 1] ==
' ' ) ||
499 ( str[l - 1] ==
'\n' ) ||
500 ( str[l - 1] ==
'\r' ) ||
501 ( str[l - 1] ==
'\t' )) ) {
514 char ** shares = malloc(
sizeof(
char *) * 255);
517 char * saveptr = NULL;
521 char * temp_string = strdup(
string);
524 share = strtok_rr(temp_string,
"\n", &saveptr);
526 shares[i] = strdup(share);
527 trim_trailing_whitespace(shares[i]);
529 while ( (share = strtok_rr(NULL,
"\n", &saveptr))) {
532 shares[i] = strdup(share);
534 trim_trailing_whitespace(shares[i]);
536 if ((shares[i] != NULL) && (strlen(shares[i]) == 0)) {
545 char * secret = join_strings(shares, i);
557 free_string_shares(shares, i);
char * extract_secret_from_share_strings(const char *string)
Given a list of shares (\n separated without leading whitespace), recreate the original secret...
char * generate_share_strings(char *secret, int n, int t)
Given a secret, n, and t, create a list of shares (\n separated).
void seed_random(void)
Seed the random number generator. MUST BE CALLED before using the library (unless on arc4random() sys...
Simple library for providing SSS functionality.