├── BigInt.js ├── LICENSE ├── README.md ├── index.html └── threshold.js /BigInt.js: -------------------------------------------------------------------------------- 1 | // cho45: Wrap all functions to OO-style and close the scope 2 | // karlgluck: Fixed bug with int2BigInt that causes mod(smaller, bigger) to always return 0 3 | // karlgluck: passed JSLint 4 | // karlgluck: fixed OO-syle functions to consistently return new objects 5 | // karlgluck: fixed OO declaration to be 'use strict' compliant 6 | // karlgluck: declare functions in order 7 | // karlgluck: prevent global variable clobbering 8 | (function (Global) { 9 | 10 | // http://www.leemon.com/crypto/BigInt.js 11 | 12 | //////////////////////////////////////////////////////////////////////////////////////// 13 | // Big Integer Library v. 5.5 14 | // Created 2000, last modified 2013 15 | // Leemon Baird 16 | // www.leemon.com 17 | // 18 | // Version history: 19 | // v 5.5 17 Mar 2013 20 | // - two lines of a form like "if (x<0) x+=n" had the "if" changed to "while" to 21 | // handle the case when x<-n. (Thanks to James Ansell for finding that bug) 22 | // v 5.4 3 Oct 2009 23 | // - added "var i" to greaterShift() so i is not global. (Thanks to PŽter Szab— for finding that bug) 24 | // 25 | // v 5.3 21 Sep 2009 26 | // - added randProbPrime(k) for probable primes 27 | // - unrolled loop in mont_ (slightly faster) 28 | // - millerRabin now takes a bigInt parameter rather than an int 29 | // 30 | // v 5.2 15 Sep 2009 31 | // - fixed capitalization in call to int2bigInt in randBigInt 32 | // (thanks to Emili Evripidou, Reinhold Behringer, and Samuel Macaleese for finding that bug) 33 | // 34 | // v 5.1 8 Oct 2007 35 | // - renamed inverseModInt_ to inverseModInt since it doesn't change its parameters 36 | // - added functions GCD and randBigInt, which call GCD_ and randBigInt_ 37 | // - fixed a bug found by Rob Visser (see comment with his name below) 38 | // - improved comments 39 | // 40 | // This file is public domain. You can use it for any purpose without restriction. 41 | // I do not guarantee that it is correct, so use it at your own risk. If you use 42 | // it for something interesting, I'd appreciate hearing about it. If you find 43 | // any bugs or make any improvements, I'd appreciate hearing about those too. 44 | // It would also be nice if my name and URL were left in the comments. But none 45 | // of that is required. 46 | // 47 | // This code defines a bigInt library for arbitrary-precision integers. 48 | // A bigInt is an array of integers storing the value in chunks of bpe bits, 49 | // little endian (buff[0] is the least significant word). 50 | // Negative bigInts are stored two's complement. Almost all the functions treat 51 | // bigInts as nonnegative. The few that view them as two's complement say so 52 | // in their comments. Some functions assume their parameters have at least one 53 | // leading zero element. Functions with an underscore at the end of the name put 54 | // their answer into one of the arrays passed in, and have unpredictable behavior 55 | // in case of overflow, so the caller must make sure the arrays are big enough to 56 | // hold the answer. But the average user should never have to call any of the 57 | // underscored functions. Each important underscored function has a wrapper function 58 | // of the same name without the underscore that takes care of the details for you. 59 | // For each underscored function where a parameter is modified, that same variable 60 | // must not be used as another argument too. So, you cannot square x by doing 61 | // multMod_(x,x,n). You must use squareMod_(x,n) instead, or do y=dup(x); multMod_(x,y,n). 62 | // Or simply use the multMod(x,x,n) function without the underscore, where 63 | // such issues never arise, because non-underscored functions never change 64 | // their parameters; they always allocate new memory for the answer that is returned. 65 | // 66 | // These functions are designed to avoid frequent dynamic memory allocation in the inner loop. 67 | // For most functions, if it needs a BigInt as a local variable it will actually use 68 | // a global, and will only allocate to it only when it's not the right size. This ensures 69 | // that when a function is called repeatedly with same-sized parameters, it only allocates 70 | // memory on the first call. 71 | // 72 | // The calls to Math.random() have been replaced with calls to the cryptographic PRNG 73 | // 74 | // 75 | // In the following, "bigInt" means a bigInt with at least one leading zero element, 76 | // and "integer" means a nonnegative integer less than radix. In some cases, integer 77 | // can be negative. Negative bigInts are 2s complement. 78 | // 79 | // The following functions do not modify their inputs. 80 | // Those returning a bigInt, string, or Array will dynamically allocate memory for that value. 81 | // Those returning a boolean will return the integer 0 (false) or 1 (true). 82 | // Those returning boolean or int will not allocate memory except possibly on the first 83 | // time they're called with a given parameter size. 84 | // 85 | // bigInt add(x,y) //return (x+y) for bigInts x and y. 86 | // bigInt addInt(x,n) //return (x+n) where x is a bigInt and n is an integer. 87 | // string bigInt2str(x,base) //return a string form of bigInt x in a given base, with 2 <= base <= 95 88 | // int bitSize(x) //return how many bits long the bigInt x is, not counting leading zeros 89 | // bigInt dup(x) //return a copy of bigInt x 90 | // boolean equals(x,y) //is the bigInt x equal to the bigint y? 91 | // boolean equalsInt(x,y) //is bigint x equal to integer y? 92 | // bigInt expand(x,n) //return a copy of x with at least n elements, adding leading zeros if needed 93 | // Array findPrimes(n) //return array of all primes less than integer n 94 | // bigInt GCD(x,y) //return greatest common divisor of bigInts x and y (each with same number of elements). 95 | // boolean greater(x,y) //is x>y? (x and y are nonnegative bigInts) 96 | // boolean greaterShift(x,y,shift)//is (x <<(shift*bpe)) > y? 97 | // bigInt int2bigInt(t,n,m) //return a bigInt equal to integer t, with at least n bits and m array elements 98 | // bigInt inverseMod(x,n) //return (x**(-1) mod n) for bigInts x and n. If no inverse exists, it returns null 99 | // int inverseModInt(x,n) //return x**(-1) mod n, for integers x and n. Return 0 if there is no inverse 100 | // boolean isZero(x) //is the bigInt x equal to zero? 101 | // boolean millerRabin(x,b) //does one round of Miller-Rabin base integer b say that bigInt x is possibly prime? (b is bigInt, 1=1). If s=1, then the most significant of those n bits is set to 1. 110 | // bigInt randTruePrime(k) //return a new, random, k-bit, true prime bigInt using Maurer's algorithm. 111 | // bigInt randProbPrime(k) //return a new, random, k-bit, probable prime bigInt (probability it's composite less than 2^-80). 112 | // bigInt str2bigInt(s,b,n,m) //return a bigInt for number represented in string s in base b with at least n bits and m array elements 113 | // bigInt sub(x,y) //return (x-y) for bigInts x and y. Negative answers will be 2s complement 114 | // bigInt trim(x,k) //return a copy of x with exactly k leading zero elements 115 | // 116 | // 117 | // The following functions each have a non-underscored version, which most users should call instead. 118 | // These functions each write to a single parameter, and the caller is responsible for ensuring the array 119 | // passed in is large enough to hold the result. 120 | // 121 | // void addInt_(x,n) //do x=x+n where x is a bigInt and n is an integer 122 | // void add_(x,y) //do x=x+y for bigInts x and y 123 | // void copy_(x,y) //do x=y on bigInts x and y 124 | // void copyInt_(x,n) //do x=n on bigInt x and integer n 125 | // void GCD_(x,y) //set x to the greatest common divisor of bigInts x and y, (y is destroyed). (This never overflows its array). 126 | // boolean inverseMod_(x,n) //do x=x**(-1) mod n, for bigInts x and n. Returns 1 (0) if inverse does (doesn't) exist 127 | // void mod_(x,n) //do x=x mod n for bigInts x and n. (This never overflows its array). 128 | // void mult_(x,y) //do x=x*y for bigInts x and y. 129 | // void multMod_(x,y,n) //do x=x*y mod n for bigInts x,y,n. 130 | // void powMod_(x,y,n) //do x=x**y mod n, where x,y,n are bigInts (n is odd) and ** is exponentiation. 0**0=1. 131 | // void randBigInt_(b,n,s) //do b = an n-bit random BigInt. if s=1, then nth bit (most significant bit) is set to 1. n>=1. 132 | // void randTruePrime_(ans,k) //do ans = a random k-bit true random prime (not just probable prime) with 1 in the msb. 133 | // void sub_(x,y) //do x=x-y for bigInts x and y. Negative answers will be 2s complement. 134 | // 135 | // The following functions do NOT have a non-underscored version. 136 | // They each write a bigInt result to one or more parameters. The caller is responsible for 137 | // ensuring the arrays passed in are large enough to hold the results. 138 | // 139 | // void addShift_(x,y,ys) //do x=x+(y<<(ys*bpe)) 140 | // void carry_(x) //do carries and borrows so each element of the bigInt x fits in bpe bits. 141 | // void divide_(x,y,q,r) //divide x by y giving quotient q and remainder r 142 | // int divInt_(x,n) //do x=floor(x/n) for bigInt x and integer n, and return the remainder. (This never overflows its array). 143 | // int eGCD_(x,y,d,a,b) //sets a,b,d to positive bigInts such that d = GCD_(x,y) = a*x-b*y 144 | // void halve_(x) //do x=floor(|x|/2)*sgn(x) for bigInt x in 2's complement. (This never overflows its array). 145 | // void leftShift_(x,n) //left shift bigInt x by n bits. n64 multiplier, but not with JavaScript's 32*32->32) 184 | // - speeding up mont_(x,y,n,np) when x==y by doing a non-modular, non-Montgomery square 185 | // followed by a Montgomery reduction. The intermediate answer will be twice as long as x, so that 186 | // method would be slower. This is unfortunate because the code currently spends almost all of its time 187 | // doing mont_(x,x,...), both for randTruePrime_() and powMod_(). A faster method for Montgomery squaring 188 | // would have a large impact on the speed of randTruePrime_() and powMod_(). HAC has a couple of poorly-worded 189 | // sentences that seem to imply it's faster to do a non-modular square followed by a single 190 | // Montgomery reduction, but that's obviously wrong. 191 | //////////////////////////////////////////////////////////////////////////////////////// 192 | 193 | 'use strict'; 194 | 195 | var bpe = 0, // bits stored per array element 196 | mask = 0, // AND this with an array element to chop it down to bpe bits 197 | radix = mask + 1, // equals 2^bpe. A single 1 bit to the left of the last bit of mask. 198 | one = [1, 0], // constant used in powMod_() 199 | 200 | // the digits for converting to different bases 201 | digitsStr = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_=!@#$%^&*()[]{}|;:,.<>/?`~ \\\'\"+-'; 202 | 203 | // the following global variables are scratchpad memory to 204 | // reduce dynamic memory allocation in the inner loop 205 | var t = new Array(0); 206 | var ss = t, // used in mult_() 207 | s0 = t, // used in multMod_(), squareMod_() 208 | s1 = t, // used in powMod_(), multMod_(), squareMod_() 209 | s2 = t, // used in powMod_(), multMod_() 210 | s3 = t, // used in powMod_() 211 | s4 = t, 212 | s5 = t, // used in mod_() 213 | s6 = t, // used in bigInt2str() 214 | s7 = t, // used in powMod_() 215 | T = t, // used in GCD_() 216 | sa = t, // used in mont_() 217 | mr_x1 = t, mr_r = t, mr_a = t, // used in millerRabin() 218 | eg_v = t, eg_u = t, eg_A = t, eg_B = t, eg_C = t, eg_D = t, // used in eGCD_(), inverseMod_() 219 | md_q1 = t, md_q2 = t, md_q3 = t, md_r = t, md_r1 = t, md_r2 = t, md_tt = t, // used in mod_() 220 | 221 | primes = t, pows = t, s_i = t, s_i2 = t, s_R = t, s_rm = t, s_q = t, s_n1 = t, 222 | s_a = t, s_r2 = t, s_n = t, s_b = t, s_d = t, s_x1 = t, s_x2 = t, s_aa = t, // used in randTruePrime_() 223 | 224 | rpprb = t; // used in randProbPrimeRounds() (which also uses "primes") 225 | 226 | for (bpe = 0; (1 << (bpe + 1)) > (1 << bpe); bpe++) { } // bpe=number of bits in the mantissa on this platform 227 | bpe >>= 1; // bpe=number of bits in one element of the array representing the bigInt 228 | mask = (1 << bpe) - 1; // AND the mask with an integer to get its bpe least significant bits 229 | radix = mask + 1; // 2^bpe. a single 1 bit to the left of the first bit of mask 230 | 231 | //////////////////////////////////////////////////////////////////////////////////////// 232 | 233 | //do x=y on bigInts x and y. x must be an array at least as big as y (not counting the leading zeros in y). 234 | function copy_(x, y) { 235 | var i; 236 | var k = x.length < y.length ? x.length : y.length; 237 | for (i = 0; i < k; i++) 238 | x[i] = y[i]; 239 | for (i = k; i < x.length; i++) 240 | x[i] = 0; 241 | } 242 | 243 | //do x=y on bigInt x and integer y. 244 | function copyInt_(x, n) { 245 | var i, c; 246 | for (c = n, i = 0; i < x.length; i++) { 247 | x[i] = c & mask; 248 | c >>= bpe; 249 | } 250 | } 251 | 252 | //returns a duplicate of bigInt x 253 | function dup(x) { 254 | var buff = new Array(x.length); 255 | copy_(buff, x); 256 | return buff; 257 | } 258 | 259 | 260 | //do x=x+n where x is a bigInt and n is an integer. 261 | //x must be large enough to hold the result. 262 | function addInt_(x, n) { 263 | var i, k, c, b; 264 | x[0] += n; 265 | k = x.length; 266 | c = 0; 267 | for (i = 0; i < k; i++) { 268 | c += x[i]; 269 | b = 0; 270 | if (c < 0) { 271 | b = -(c >> bpe); 272 | c += b * radix; 273 | } 274 | x[i] = c & mask; 275 | c = (c >> bpe) - b; 276 | if (!c) return; //stop carrying as soon as the carry is zero 277 | } 278 | } 279 | 280 | //right shift bigInt x by n bits. 0 <= n < bpe. 281 | function rightShift_(x, n) { 282 | var i; 283 | var k = Math.floor(n / bpe); 284 | if (k) { 285 | for (i = 0; i < x.length - k; i++) //right shift x by k elements 286 | x[i] = x[i + k]; 287 | for (; i < x.length; i++) 288 | x[i] = 0; 289 | n %= bpe; 290 | } 291 | for (i = 0; i < x.length - 1; i++) { 292 | x[i] = mask & ((x[i + 1] << (bpe - n)) | (x[i] >> n)); 293 | } 294 | x[i] >>= n; 295 | } 296 | 297 | //do x=floor(|x|/2)*sgn(x) for bigInt x in 2's complement 298 | function halve_(x) { 299 | var i; 300 | for (i = 0; i < x.length - 1; i++) { 301 | x[i] = mask & ((x[i + 1] << (bpe - 1)) | (x[i] >> 1)); 302 | } 303 | x[i] = (x[i] >> 1) | (x[i] & (radix >> 1)); //most significant bit stays the same 304 | } 305 | 306 | //left shift bigInt x by n bits. 307 | function leftShift_(x, n) { 308 | var i; 309 | var k = Math.floor(n / bpe); 310 | if (k) { 311 | for (i = x.length; i >= k; i--) //left shift x by k elements 312 | x[i] = x[i - k]; 313 | for (; i >= 0; i--) 314 | x[i] = 0; 315 | n %= bpe; 316 | } 317 | if (!n) 318 | return; 319 | for (i = x.length - 1; i > 0; i--) { 320 | x[i] = mask & ((x[i] << n) | (x[i - 1] >> (bpe - n))); 321 | } 322 | x[i] = mask & (x[i] << n); 323 | } 324 | 325 | //do x=x*n where x is a bigInt and n is an integer. 326 | //x must be large enough to hold the result. 327 | function multInt_(x, n) { 328 | var i, k, c, b; 329 | if (!n) 330 | return; 331 | k = x.length; 332 | c = 0; 333 | for (i = 0; i < k; i++) { 334 | c += x[i] * n; 335 | b = 0; 336 | if (c < 0) { 337 | b = -(c >> bpe); 338 | c += b * radix; 339 | } 340 | x[i] = c & mask; 341 | c = (c >> bpe) - b; 342 | } 343 | } 344 | 345 | //do x=floor(x/n) for bigInt x and integer n, and return the remainder 346 | function divInt_(x, n) { 347 | var i, r = 0, s; 348 | for (i = x.length - 1; i >= 0; i--) { 349 | s = r * radix + x[i]; 350 | x[i] = Math.floor(s / n); 351 | r = s % n; 352 | } 353 | return r; 354 | } 355 | 356 | //do the linear combination x=a*x+b*y for bigInts x and y, and integers a and b. 357 | //x must be large enough to hold the answer. 358 | function linComb_(x, y, a, b) { 359 | var i, c, k, kk; 360 | k = x.length < y.length ? x.length : y.length; 361 | kk = x.length; 362 | for (c = 0, i = 0; i < k; i++) { 363 | c += a * x[i] + b * y[i]; 364 | x[i] = c & mask; 365 | c >>= bpe; 366 | } 367 | for (i = k; i < kk; i++) { 368 | c += a * x[i]; 369 | x[i] = c & mask; 370 | c >>= bpe; 371 | } 372 | } 373 | 374 | //do the linear combination x=a*x+b*(y<<(ys*bpe)) for bigInts x and y, and integers a, b and ys. 375 | //x must be large enough to hold the answer. 376 | function linCombShift_(x, y, b, ys) { 377 | var i, c, k, kk; 378 | k = x.length < ys + y.length ? x.length : ys + y.length; 379 | kk = x.length; 380 | for (c = 0, i = ys; i < k; i++) { 381 | c += x[i] + b * y[i - ys]; 382 | x[i] = c & mask; 383 | c >>= bpe; 384 | } 385 | for (i = k; c && i < kk; i++) { 386 | c += x[i]; 387 | x[i] = c & mask; 388 | c >>= bpe; 389 | } 390 | } 391 | 392 | //do x=x+(y<<(ys*bpe)) for bigInts x and y, and integers a,b and ys. 393 | //x must be large enough to hold the answer. 394 | function addShift_(x, y, ys) { 395 | var i, c, k, kk; 396 | k = x.length < ys + y.length ? x.length : ys + y.length; 397 | kk = x.length; 398 | for (c = 0, i = ys; i < k; i++) { 399 | c += x[i] + y[i - ys]; 400 | x[i] = c & mask; 401 | c >>= bpe; 402 | } 403 | for (i = k; c && i < kk; i++) { 404 | c += x[i]; 405 | x[i] = c & mask; 406 | c >>= bpe; 407 | } 408 | } 409 | 410 | //do x=x-(y<<(ys*bpe)) for bigInts x and y, and integers a,b and ys. 411 | //x must be large enough to hold the answer. 412 | function subShift_(x, y, ys) { 413 | var i, c, k, kk; 414 | k = x.length < ys + y.length ? x.length : ys + y.length; 415 | kk = x.length; 416 | for (c = 0, i = ys; i < k; i++) { 417 | c += x[i] - y[i - ys]; 418 | x[i] = c & mask; 419 | c >>= bpe; 420 | } 421 | for (i = k; c && i < kk; i++) { 422 | c += x[i]; 423 | x[i] = c & mask; 424 | c >>= bpe; 425 | } 426 | } 427 | 428 | //do x=x-y for bigInts x and y. 429 | //x must be large enough to hold the answer. 430 | //negative answers will be 2s complement 431 | function sub_(x, y) { 432 | var i, c, k, kk; 433 | k = x.length < y.length ? x.length : y.length; 434 | for (c = 0, i = 0; i < k; i++) { 435 | c += x[i] - y[i]; 436 | x[i] = c & mask; 437 | c >>= bpe; 438 | } 439 | for (i = k; c && i < x.length; i++) { 440 | c += x[i]; 441 | x[i] = c & mask; 442 | c >>= bpe; 443 | } 444 | } 445 | 446 | //do x=x+y for bigInts x and y. 447 | //x must be large enough to hold the answer. 448 | function add_(x, y) { 449 | var i, c, k, kk; 450 | k = x.length < y.length ? x.length : y.length; 451 | for (c = 0, i = 0; i < k; i++) { 452 | c += x[i] + y[i]; 453 | x[i] = c & mask; 454 | c >>= bpe; 455 | } 456 | for (i = k; c && i < x.length; i++) { 457 | c += x[i]; 458 | x[i] = c & mask; 459 | c >>= bpe; 460 | } 461 | } 462 | 463 | //do x=x*y for bigInts x and y. This is faster when y 0 && !x[kx - 1]; kx--); //ignore leading zeros in x 504 | k = kx > n.length ? 2 * kx : 2 * n.length; //k=# elements in the product, which is twice the elements in the larger of x and n 505 | if (s0.length != k) 506 | s0 = new Array(k); 507 | copyInt_(s0, 0); 508 | for (i = 0; i < kx; i++) { 509 | c = s0[2 * i] + x[i] * x[i]; 510 | s0[2 * i] = c & mask; 511 | c >>= bpe; 512 | for (j = i + 1; j < kx; j++) { 513 | c = s0[i + j] + 2 * x[i] * x[j] + c; 514 | s0[i + j] = (c & mask); 515 | c >>= bpe; 516 | } 517 | s0[i + kx] = c; 518 | } 519 | mod_(s0, n); 520 | copy_(x, s0); 521 | } 522 | 523 | //return x with exactly k leading zero elements 524 | function trim(x, k) { 525 | var i, y; 526 | for (i = x.length; i > 0 && !x[i - 1]; i--); 527 | y = new Array(i + k); 528 | copy_(y, x); 529 | return y; 530 | } 531 | 532 | //do x=x**y mod n, where x,y,n are bigInts and ** is exponentiation. 0**0=1. 533 | //this is faster when n is odd. x usually needs to have as many elements as n. 534 | function powMod_(x, y, n) { 535 | var k1, k2, kn, np; 536 | if (s7.length != n.length) 537 | s7 = dup(n); 538 | 539 | //for even modulus, use a simple square-and-multiply algorithm, 540 | //rather than using the more complex Montgomery algorithm. 541 | if ((n[0] & 1) == 0) { 542 | copy_(s7, x); 543 | copyInt_(x, 1); 544 | while (!equalsInt(y, 0)) { 545 | if (y[0] & 1) 546 | multMod_(x, s7, n); 547 | divInt_(y, 2); 548 | squareMod_(s7, n); 549 | } 550 | return; 551 | } 552 | 553 | //calculate np from n for the Montgomery multiplications 554 | copyInt_(s7, 0); 555 | for (kn = n.length; kn > 0 && !n[kn - 1]; kn--); 556 | np = radix - inverseModInt(modInt(n, radix), radix); 557 | s7[kn] = 1; 558 | multMod_(x, s7, n); // x = x * 2**(kn*bp) mod n 559 | 560 | if (s3.length != x.length) 561 | s3 = dup(x); 562 | else 563 | copy_(s3, x); 564 | 565 | for (k1 = y.length - 1; k1 > 0 & !y[k1]; k1--); //k1=first nonzero element of y 566 | if (y[k1] == 0) { //anything to the 0th power is 1 567 | copyInt_(x, 1); 568 | return; 569 | } 570 | for (k2 = 1 << (bpe - 1); k2 && !(y[k1] & k2); k2 >>= 1); //k2=position of first 1 bit in y[k1] 571 | for (; ; ) { 572 | if (!(k2 >>= 1)) { //look at next bit of y 573 | k1--; 574 | if (k1 < 0) { 575 | mont_(x, one, n, np); 576 | return; 577 | } 578 | k2 = 1 << (bpe - 1); 579 | } 580 | mont_(x, x, n, np); 581 | 582 | if (k2 & y[k1]) //if next bit is a 1 583 | mont_(x, s3, n, np); 584 | } 585 | } 586 | 587 | 588 | //do x=x*y*Ri mod n for bigInts x,y,n, 589 | // where Ri = 2**(-kn*bpe) mod n, and kn is the 590 | // number of elements in the n array, not 591 | // counting leading zeros. 592 | //x array must have at least as many elemnts as the n array 593 | //It's OK if x and y are the same variable. 594 | //must have: 595 | // x,y < n 596 | // n is odd 597 | // np = -(n^(-1)) mod radix 598 | function mont_(x, y, n, np) { 599 | var i, j, c, ui, t, ks; 600 | var kn = n.length; 601 | var ky = y.length; 602 | 603 | if (sa.length != kn) 604 | sa = new Array(kn); 605 | 606 | copyInt_(sa, 0); 607 | 608 | for (; kn > 0 && n[kn - 1] == 0; kn--); //ignore leading zeros of n 609 | for (; ky > 0 && y[ky - 1] == 0; ky--); //ignore leading zeros of y 610 | ks = sa.length - 1; //sa will never have more than this many nonzero elements. 611 | 612 | //the following loop consumes 95% of the runtime for randTruePrime_() and powMod_() for large numbers 613 | for (i = 0; i < kn; i++) { 614 | t = sa[0] + x[i] * y[0]; 615 | ui = ((t & mask) * np) & mask; //the inner "& mask" was needed on Safari (but not MSIE) at one time 616 | c = (t + ui * n[0]) >> bpe; 617 | t = x[i]; 618 | 619 | //do sa=(sa+x[i]*y+ui*n)/b where b=2**bpe. Loop is unrolled 5-fold for speed 620 | j = 1; 621 | for (; j < ky - 4; ) { 622 | c += sa[j] + ui * n[j] + t * y[j]; sa[j - 1] = c & mask; c >>= bpe; j++; 623 | c += sa[j] + ui * n[j] + t * y[j]; sa[j - 1] = c & mask; c >>= bpe; j++; 624 | c += sa[j] + ui * n[j] + t * y[j]; sa[j - 1] = c & mask; c >>= bpe; j++; 625 | c += sa[j] + ui * n[j] + t * y[j]; sa[j - 1] = c & mask; c >>= bpe; j++; 626 | c += sa[j] + ui * n[j] + t * y[j]; sa[j - 1] = c & mask; c >>= bpe; j++; 627 | } 628 | for (; j < ky; ) { c += sa[j] + ui * n[j] + t * y[j]; sa[j - 1] = c & mask; c >>= bpe; j++; } 629 | for (; j < kn - 4; ) { 630 | c += sa[j] + ui * n[j]; sa[j - 1] = c & mask; c >>= bpe; j++; 631 | c += sa[j] + ui * n[j]; sa[j - 1] = c & mask; c >>= bpe; j++; 632 | c += sa[j] + ui * n[j]; sa[j - 1] = c & mask; c >>= bpe; j++; 633 | c += sa[j] + ui * n[j]; sa[j - 1] = c & mask; c >>= bpe; j++; 634 | c += sa[j] + ui * n[j]; sa[j - 1] = c & mask; c >>= bpe; j++; 635 | } 636 | for (; j < kn; ) { c += sa[j] + ui * n[j]; sa[j - 1] = c & mask; c >>= bpe; j++; } 637 | for (; j < ks; ) { c += sa[j]; sa[j - 1] = c & mask; c >>= bpe; j++; } 638 | sa[j - 1] = c & mask; 639 | } 640 | 641 | if (!greater(n, sa)) 642 | sub_(sa, n); 643 | copy_(x, sa); 644 | } 645 | 646 | //return array of all primes less than integer n 647 | function findPrimes(n) { 648 | var i, s, p, ans; 649 | s = new Array(n); 650 | for (i = 0; i < n; i++) 651 | s[i] = 0; 652 | s[0] = 2; 653 | p = 0; //first p elements of s are primes, the rest are a sieve 654 | for (; s[p] < n; ) { //s[p] is the pth prime 655 | for (i = s[p] * s[p]; i < n; i += s[p]) //mark multiples of s[p] 656 | s[i] = 1; 657 | p++; 658 | s[p] = s[p - 1] + 1; 659 | for (; s[p] < n && s[s[p]]; s[p]++); //find next prime (where s[p]==0) 660 | } 661 | ans = new Array(p); 662 | for (i = 0; i < p; i++) 663 | ans[i] = s[i]; 664 | return ans; 665 | } 666 | 667 | 668 | //does a single round of Miller-Rabin base b consider x to be a possible prime? 669 | //x and b are bigInts with b 0); j--); 735 | for (z = 0, w = x[j]; w; (w >>= 1), z++); 736 | z += bpe * j; 737 | return z; 738 | } 739 | 740 | //return a copy of x with at least n elements, adding leading zeros if needed 741 | function expand(x, n) { 742 | var ans = int2bigInt(0, (x.length > n ? x.length : n) * bpe, 0); 743 | copy_(ans, x); 744 | return ans; 745 | } 746 | 747 | //return a k-bit true random prime using Maurer's algorithm. 748 | function randTruePrime(k) { 749 | var ans = int2bigInt(0, k, 0); 750 | randTruePrime_(ans, k); 751 | return trim(ans, 1); 752 | } 753 | 754 | //return a k-bit random probable prime with probability of error < 2^-80 755 | function randProbPrime(k) { 756 | if (k >= 600) return randProbPrimeRounds(k, 2); //numbers from HAC table 4.3 757 | if (k >= 550) return randProbPrimeRounds(k, 4); 758 | if (k >= 500) return randProbPrimeRounds(k, 5); 759 | if (k >= 400) return randProbPrimeRounds(k, 6); 760 | if (k >= 350) return randProbPrimeRounds(k, 7); 761 | if (k >= 300) return randProbPrimeRounds(k, 9); 762 | if (k >= 250) return randProbPrimeRounds(k, 12); //numbers from HAC table 4.4 763 | if (k >= 200) return randProbPrimeRounds(k, 15); 764 | if (k >= 150) return randProbPrimeRounds(k, 18); 765 | if (k >= 100) return randProbPrimeRounds(k, 27); 766 | return randProbPrimeRounds(k, 40); //number from HAC remark 4.26 (only an estimate) 767 | } 768 | 769 | //return a k-bit probable random prime using n rounds of Miller Rabin (after trial division with small primes) 770 | function randProbPrimeRounds(k, n) { 771 | var ans, i, divisible, B; 772 | B = 30000; //B is largest prime to use in trial division 773 | ans = int2bigInt(0, k, 0); 774 | 775 | //optimization: try larger and smaller B to find the best limit. 776 | 777 | if (primes.length == 0) 778 | primes = findPrimes(30000); //check for divisibility by primes <=30000 779 | 780 | if (rpprb.length != ans.length) 781 | rpprb = dup(ans); 782 | 783 | for (; ; ) { //keep trying random values for ans until one appears to be prime 784 | //optimization: pick a random number times L=2*3*5*...*p, plus a 785 | // random element of the list of all numbers in [0,L) not divisible by any prime up to p. 786 | // This can reduce the amount of random number generation. 787 | 788 | randBigInt_(ans, k, 0); //ans = a random odd number to check 789 | ans[0] |= 1; 790 | divisible = 0; 791 | 792 | //check ans for divisibility by small primes up to B 793 | for (i = 0; (i < primes.length) && (primes[i] <= B); i++) 794 | if (modInt(ans, primes[i]) == 0 && !equalsInt(ans, primes[i])) { 795 | divisible = 1; 796 | break; 797 | } 798 | 799 | //optimization: change millerRabin so the base can be bigger than the number being checked, then eliminate the while here. 800 | 801 | //do n rounds of Miller Rabin, with random bases less than ans 802 | for (i = 0; i < n && !divisible; i++) { 803 | randBigInt_(rpprb, k, 0); 804 | while (!greater(ans, rpprb)) //pick a random rpprb that's < ans 805 | randBigInt_(rpprb, k, 0); 806 | if (!millerRabin(ans, rpprb)) 807 | divisible = 1; 808 | } 809 | 810 | if (!divisible) 811 | return ans; 812 | } 813 | } 814 | 815 | //return a new bigInt equal to (x mod n) for bigInts x and n. 816 | function mod(x, n) { 817 | var ans = dup(x); 818 | mod_(ans, n); 819 | return trim(ans, 1); 820 | } 821 | 822 | //return (x+n) where x is a bigInt and n is an integer. 823 | function addInt(x, n) { 824 | var ans = expand(x, x.length + 1); 825 | addInt_(ans, n); 826 | return trim(ans, 1); 827 | } 828 | 829 | //return x*y for bigInts x and y. This is faster when y y.length ? x.length + 1 : y.length + 1)); 846 | sub_(ans, y); 847 | return trim(ans, 1); 848 | } 849 | 850 | //return (x+y) for bigInts x and y. 851 | function add(x, y) { 852 | var ans = expand(x, (x.length > y.length ? x.length + 1 : y.length + 1)); 853 | add_(ans, y); 854 | return trim(ans, 1); 855 | } 856 | 857 | //return (x**(-1) mod n) for bigInts x and n. If no inverse exists, it returns null 858 | function inverseMod(x, n) { 859 | var ans = expand(x, n.length); 860 | var s; 861 | s = inverseMod_(ans, n); 862 | return s ? trim(ans, 1) : null; 863 | } 864 | 865 | //return (x*y mod n) for bigInts x,y,n. For greater speed, let y= 2 891 | 892 | if (s_i2.length != ans.length) { 893 | s_i2 = dup(ans); 894 | s_R = dup(ans); 895 | s_n1 = dup(ans); 896 | s_r2 = dup(ans); 897 | s_d = dup(ans); 898 | s_x1 = dup(ans); 899 | s_x2 = dup(ans); 900 | s_b = dup(ans); 901 | s_n = dup(ans); 902 | s_i = dup(ans); 903 | s_rm = dup(ans); 904 | s_q = dup(ans); 905 | s_a = dup(ans); 906 | s_aa = dup(ans); 907 | } 908 | 909 | if (k <= recLimit) { //generate small random primes by trial division up to its square root 910 | pm = (1 << ((k + 2) >> 1)) - 1; //pm is binary number with all ones, just over sqrt(2^k) 911 | copyInt_(ans, 0); 912 | for (dd = 1; dd; ) { 913 | dd = 0; 914 | ans[0] = 1 | (1 << (k - 1)) | Math.floor(Math.random() * (1 << k)); //random, k-bit, odd integer, with msb 1 915 | for (j = 1; (j < primes.length) && ((primes[j] & pm) == primes[j]); j++) { //trial division by all primes 3...sqrt(2^k) 916 | if (0 == (ans[0] % primes[j])) { 917 | dd = 1; 918 | break; 919 | } 920 | } 921 | } 922 | carry_(ans); 923 | return; 924 | } 925 | 926 | B = c * k * k; //try small primes up to B (or all the primes[] array if the largest is less than B). 927 | if (k > 2 * m) //generate this k-bit number by first recursively generating a number that has between k/2 and k-m bits 928 | for (r = 1; k - k * r <= m; ) 929 | r = pows[Math.floor(Math.random() * 512)]; //r=Math.pow(2,Math.random()-1); 930 | else 931 | r = .5; 932 | 933 | //simulation suggests the more complex algorithm using r=.333 is only slightly faster. 934 | 935 | recSize = Math.floor(r * k) + 1; 936 | 937 | randTruePrime_(s_q, recSize); 938 | copyInt_(s_i2, 0); 939 | s_i2[Math.floor((k - 2) / bpe)] |= (1 << ((k - 2) % bpe)); //s_i2=2^(k-2) 940 | divide_(s_i2, s_q, s_i, s_rm); //s_i=floor((2^(k-1))/(2q)) 941 | 942 | z = bitSize(s_i); 943 | 944 | for (; ; ) { 945 | for (; ; ) { //generate z-bit numbers until one falls in the range [0,s_i-1] 946 | randBigInt_(s_R, z, 0); 947 | if (greater(s_i, s_R)) 948 | break; 949 | } //now s_R is in the range [0,s_i-1] 950 | addInt_(s_R, 1); //now s_R is in the range [1,s_i] 951 | add_(s_R, s_i); //now s_R is in the range [s_i+1,2*s_i] 952 | 953 | copy_(s_n, s_q); 954 | mult_(s_n, s_R); 955 | multInt_(s_n, 2); 956 | addInt_(s_n, 1); //s_n=2*s_R*s_q+1 957 | 958 | copy_(s_r2, s_R); 959 | multInt_(s_r2, 2); //s_r2=2*s_R 960 | 961 | //check s_n for divisibility by small primes up to B 962 | for (divisible = 0, j = 0; (j < primes.length) && (primes[j] < B); j++) 963 | if (modInt(s_n, primes[j]) == 0 && !equalsInt(s_n, primes[j])) { 964 | divisible = 1; 965 | break; 966 | } 967 | 968 | if (!divisible) //if it passes small primes check, then try a single Miller-Rabin base 2 969 | if (!millerRabinInt(s_n, 2)) //this line represents 75% of the total runtime for randTruePrime_ 970 | divisible = 1; 971 | 972 | if (!divisible) { //if it passes that test, continue checking s_n 973 | addInt_(s_n, -3); 974 | for (j = s_n.length - 1; (s_n[j] == 0) && (j > 0); j--); //strip leading zeros 975 | for (zz = 0, w = s_n[j]; w; (w >>= 1), zz++); 976 | zz += bpe * j; //zz=number of bits in s_n, ignoring leading zeros 977 | for (; ; ) { //generate z-bit numbers until one falls in the range [0,s_n-1] 978 | randBigInt_(s_a, zz, 0); 979 | if (greater(s_n, s_a)) 980 | break; 981 | } //now s_a is in the range [0,s_n-1] 982 | addInt_(s_n, 3); //now s_a is in the range [0,s_n-4] 983 | addInt_(s_a, 2); //now s_a is in the range [2,s_n-2] 984 | copy_(s_b, s_a); 985 | copy_(s_n1, s_n); 986 | addInt_(s_n1, -1); 987 | powMod_(s_b, s_n1, s_n); //s_b=s_a^(s_n-1) modulo s_n 988 | addInt_(s_b, -1); 989 | if (isZero(s_b)) { 990 | copy_(s_b, s_a); 991 | powMod_(s_b, s_r2, s_n); 992 | addInt_(s_b, -1); 993 | copy_(s_aa, s_n); 994 | copy_(s_d, s_b); 995 | GCD_(s_d, s_n); //if s_b and s_n are relatively prime, then s_n is a prime 996 | if (equalsInt(s_d, 1)) { 997 | copy_(ans, s_aa); 998 | return; //if we've made it this far, then s_n is absolutely guaranteed to be prime 999 | } 1000 | } 1001 | } 1002 | } 1003 | } 1004 | 1005 | //Set b to an n-bit random BigInt. If s=1, then the most significant of those n bits is set to 1. 1006 | //Array b must be big enough to hold the result. Must have n>=1 1007 | function randBigInt_(b, n, s) { 1008 | var i, a; 1009 | for (i = 0; i < b.length; i++) 1010 | b[i] = 0; 1011 | a = Math.floor((n - 1) / bpe) + 1; //# array elements to hold the BigInt 1012 | for (i = 0; i < a; i++) { 1013 | b[i] = Math.floor(Math.random() * (1 << (bpe - 1))); 1014 | } 1015 | b[a - 1] &= (2 << ((n - 1) % bpe)) - 1; 1016 | if (s == 1) 1017 | b[a - 1] |= (1 << ((n - 1) % bpe)); 1018 | } 1019 | 1020 | //Return an n-bit random BigInt (n>=1). If s=1, then the most significant of those n bits is set to 1. 1021 | function randBigInt(n, s) { 1022 | var a, b; 1023 | a = Math.floor((n - 1) / bpe) + 2; //# array elements to hold the BigInt with a leading 0 element 1024 | b = int2bigInt(0, 0, a); 1025 | randBigInt_(b, n, s); 1026 | return b; 1027 | } 1028 | 1029 | //set x to the greatest common divisor of bigInts x and y (each with same number of elements). 1030 | //y is destroyed. 1031 | function GCD_(x, y) { 1032 | var i, xp, yp, A, B, C, D, q, sing; 1033 | if (T.length != x.length) 1034 | T = dup(x); 1035 | 1036 | sing = 1; 1037 | while (sing) { //while y has nonzero elements other than y[0] 1038 | sing = 0; 1039 | for (i = 1; i < y.length; i++) //check if y has nonzero elements other than 0 1040 | if (y[i]) { 1041 | sing = 1; 1042 | break; 1043 | } 1044 | if (!sing) break; //quit when y all zero elements except possibly y[0] 1045 | 1046 | for (i = x.length; !x[i] && i >= 0; i--); //find most significant element of x 1047 | xp = x[i]; 1048 | yp = y[i]; 1049 | A = 1; B = 0; C = 0; D = 1; 1050 | while ((yp + C) && (yp + D)) { 1051 | q = Math.floor((xp + A) / (yp + C)); 1052 | qp = Math.floor((xp + B) / (yp + D)); 1053 | if (q != qp) 1054 | break; 1055 | t = A - q * C; A = C; C = t; // do (A,B,xp, C,D,yp) = (C,D,yp, A,B,xp) - q*(0,0,0, C,D,yp) 1056 | t = B - q * D; B = D; D = t; 1057 | t = xp - q * yp; xp = yp; yp = t; 1058 | } 1059 | if (B) { 1060 | copy_(T, x); 1061 | linComb_(x, y, A, B); //x=A*x+B*y 1062 | linComb_(y, T, D, C); //y=D*y+C*T 1063 | } else { 1064 | mod_(x, y); 1065 | copy_(T, x); 1066 | copy_(x, y); 1067 | copy_(y, T); 1068 | } 1069 | } 1070 | if (y[0] == 0) 1071 | return; 1072 | t = modInt(x, y[0]); 1073 | copyInt_(x, y[0]); 1074 | y[0] = t; 1075 | while (y[0]) { 1076 | x[0] %= y[0]; 1077 | t = x[0]; x[0] = y[0]; y[0] = t; 1078 | } 1079 | } 1080 | 1081 | //Return the greatest common divisor of bigInts x and y (each with same number of elements). 1082 | function GCD(x, y) { 1083 | var xc, yc; 1084 | xc = dup(x); 1085 | yc = dup(y); 1086 | GCD_(xc, yc); 1087 | return xc; 1088 | } 1089 | 1090 | //this deprecated function is for backward compatibility only. 1091 | function inverseModInt_(x, n) { 1092 | return inverseModInt(x, n); 1093 | } 1094 | 1095 | //do x=x**(-1) mod n, for bigInts x and n. 1096 | //If no inverse exists, it sets x to zero and returns 0, else it returns 1. 1097 | //The x array must be at least as large as the n array. 1098 | function inverseMod_(x, n) { 1099 | var k = 1 + 2 * Math.max(x.length, n.length); 1100 | 1101 | if (!(x[0] & 1) && !(n[0] & 1)) { //if both inputs are even, then inverse doesn't exist 1102 | copyInt_(x, 0); 1103 | return 0; 1104 | } 1105 | 1106 | if (eg_u.length != k) { 1107 | eg_u = new Array(k); 1108 | eg_v = new Array(k); 1109 | eg_A = new Array(k); 1110 | eg_B = new Array(k); 1111 | eg_C = new Array(k); 1112 | eg_D = new Array(k); 1113 | } 1114 | 1115 | copy_(eg_u, x); 1116 | copy_(eg_v, n); 1117 | copyInt_(eg_A, 1); 1118 | copyInt_(eg_B, 0); 1119 | copyInt_(eg_C, 0); 1120 | copyInt_(eg_D, 1); 1121 | for (; ; ) { 1122 | while (!(eg_u[0] & 1)) { //while eg_u is even 1123 | halve_(eg_u); 1124 | if (!(eg_A[0] & 1) && !(eg_B[0] & 1)) { //if eg_A==eg_B==0 mod 2 1125 | halve_(eg_A); 1126 | halve_(eg_B); 1127 | } else { 1128 | add_(eg_A, n); halve_(eg_A); 1129 | sub_(eg_B, x); halve_(eg_B); 1130 | } 1131 | } 1132 | 1133 | while (!(eg_v[0] & 1)) { //while eg_v is even 1134 | halve_(eg_v); 1135 | if (!(eg_C[0] & 1) && !(eg_D[0] & 1)) { //if eg_C==eg_D==0 mod 2 1136 | halve_(eg_C); 1137 | halve_(eg_D); 1138 | } else { 1139 | add_(eg_C, n); halve_(eg_C); 1140 | sub_(eg_D, x); halve_(eg_D); 1141 | } 1142 | } 1143 | 1144 | if (!greater(eg_v, eg_u)) { //eg_v <= eg_u 1145 | sub_(eg_u, eg_v); 1146 | sub_(eg_A, eg_C); 1147 | sub_(eg_B, eg_D); 1148 | } else { //eg_v > eg_u 1149 | sub_(eg_v, eg_u); 1150 | sub_(eg_C, eg_A); 1151 | sub_(eg_D, eg_B); 1152 | } 1153 | 1154 | if (equalsInt(eg_u, 0)) { 1155 | while (negative(eg_C)) //make sure answer is nonnegative 1156 | add_(eg_C, n); 1157 | copy_(x, eg_C); 1158 | 1159 | if (!equalsInt(eg_v, 1)) { //if GCD_(x,n)!=1, then there is no inverse 1160 | copyInt_(x, 0); 1161 | return 0; 1162 | } 1163 | return 1; 1164 | } 1165 | } 1166 | } 1167 | 1168 | //return x**(-1) mod n, for integers x and n. Return 0 if there is no inverse 1169 | function inverseModInt(x, n) { 1170 | var a = 1, b = 0, t; 1171 | for (; ; ) { 1172 | if (x == 1) return a; 1173 | if (x == 0) return 0; 1174 | b -= a * Math.floor(n / x); 1175 | n %= x; 1176 | 1177 | if (n == 1) return b; //to avoid negatives, change this b to n-b, and each -= to += 1178 | if (n == 0) return 0; 1179 | a -= b * Math.floor(x / n); 1180 | x %= n; 1181 | } 1182 | } 1183 | 1184 | //Given positive bigInts x and y, change the bigints v, a, and b to positive bigInts such that: 1185 | // v = GCD_(x,y) = a*x-b*y 1186 | //The bigInts v, a, b, must have exactly as many elements as the larger of x and y. 1187 | function eGCD_(x, y, v, a, b) { 1188 | var g = 0; 1189 | var k = Math.max(x.length, y.length); 1190 | if (eg_u.length != k) { 1191 | eg_u = new Array(k); 1192 | eg_A = new Array(k); 1193 | eg_B = new Array(k); 1194 | eg_C = new Array(k); 1195 | eg_D = new Array(k); 1196 | } 1197 | while (!(x[0] & 1) && !(y[0] & 1)) { //while x and y both even 1198 | halve_(x); 1199 | halve_(y); 1200 | g++; 1201 | } 1202 | copy_(eg_u, x); 1203 | copy_(v, y); 1204 | copyInt_(eg_A, 1); 1205 | copyInt_(eg_B, 0); 1206 | copyInt_(eg_C, 0); 1207 | copyInt_(eg_D, 1); 1208 | for (; ; ) { 1209 | while (!(eg_u[0] & 1)) { //while u is even 1210 | halve_(eg_u); 1211 | if (!(eg_A[0] & 1) && !(eg_B[0] & 1)) { //if A==B==0 mod 2 1212 | halve_(eg_A); 1213 | halve_(eg_B); 1214 | } else { 1215 | add_(eg_A, y); halve_(eg_A); 1216 | sub_(eg_B, x); halve_(eg_B); 1217 | } 1218 | } 1219 | 1220 | while (!(v[0] & 1)) { //while v is even 1221 | halve_(v); 1222 | if (!(eg_C[0] & 1) && !(eg_D[0] & 1)) { //if C==D==0 mod 2 1223 | halve_(eg_C); 1224 | halve_(eg_D); 1225 | } else { 1226 | add_(eg_C, y); halve_(eg_C); 1227 | sub_(eg_D, x); halve_(eg_D); 1228 | } 1229 | } 1230 | 1231 | if (!greater(v, eg_u)) { //v<=u 1232 | sub_(eg_u, v); 1233 | sub_(eg_A, eg_C); 1234 | sub_(eg_B, eg_D); 1235 | } else { //v>u 1236 | sub_(v, eg_u); 1237 | sub_(eg_C, eg_A); 1238 | sub_(eg_D, eg_B); 1239 | } 1240 | if (equalsInt(eg_u, 0)) { 1241 | while (negative(eg_C)) { //make sure a (C) is nonnegative 1242 | add_(eg_C, y); 1243 | sub_(eg_D, x); 1244 | } 1245 | multInt_(eg_D, -1); ///make sure b (D) is nonnegative 1246 | copy_(a, eg_C); 1247 | copy_(b, eg_D); 1248 | leftShift_(v, g); 1249 | return; 1250 | } 1251 | } 1252 | } 1253 | 1254 | 1255 | //is bigInt x negative? 1256 | function negative(x) { 1257 | return ((x[x.length - 1] >> (bpe - 1)) & 1); 1258 | } 1259 | 1260 | 1261 | //is (x << (shift*bpe)) > y? 1262 | //x and y are nonnegative bigInts 1263 | //shift is a nonnegative integer 1264 | function greaterShift(x, y, shift) { 1265 | var i, kx = x.length, ky = y.length, k; 1266 | k = ((kx + shift) < ky) ? (kx + shift) : ky; // : this is using a global variable in the original version 1267 | for (i = ky - 1 - shift; i < kx && i >= 0; i++) 1268 | if (x[i] > 0) 1269 | return 1; //if there are nonzeros in x to the left of the first column of y, then x is bigger 1270 | for (i = kx - 1 + shift; i < ky; i++) 1271 | if (y[i] > 0) 1272 | return 0; //if there are nonzeros in y to the left of the first column of x, then x is not bigger 1273 | for (i = k - 1; i >= shift; i--) 1274 | if (x[i - shift] > y[i]) return 1; 1275 | else if (x[i - shift] < y[i]) return 0; 1276 | return 0; 1277 | } 1278 | 1279 | //is x > y? (x and y both nonnegative) 1280 | function greater(x, y) { 1281 | var i; 1282 | var k = (x.length < y.length) ? x.length : y.length; 1283 | 1284 | for (i = x.length; i < y.length; i++) 1285 | if (y[i]) 1286 | return 0; //y has more digits 1287 | 1288 | for (i = y.length; i < x.length; i++) 1289 | if (x[i]) 1290 | return 1; //x has more digits 1291 | 1292 | for (i = k - 1; i >= 0; i--) 1293 | if (x[i] > y[i]) 1294 | return 1; 1295 | else if (x[i] < y[i]) 1296 | return 0; 1297 | return 0; 1298 | } 1299 | 1300 | //divide x by y giving quotient q and remainder r. (q=floor(x/y), r=x mod y). All 4 are bigints. 1301 | //x must have at least one leading zero element. 1302 | //y must be nonzero. 1303 | //q and r must be arrays that are exactly the same length as x. (Or q can have more). 1304 | //Must have x.length >= y.length >= 2. 1305 | function divide_(x, y, q, r) { 1306 | var kx, ky; 1307 | var i, j, y1, y2, c, a, b; 1308 | copy_(r, x); 1309 | for (ky = y.length; y[ky - 1] == 0; ky--); //ky is number of elements in y, not including leading zeros 1310 | 1311 | //normalize: ensure the most significant element of y has its highest bit set 1312 | b = y[ky - 1]; 1313 | for (a = 0; b; a++) 1314 | b >>= 1; 1315 | a = bpe - a; //a is how many bits to shift so that the high order bit of y is leftmost in its array element 1316 | leftShift_(y, a); //multiply both by 1< ky; kx--); //kx is number of elements in normalized x, not including leading zeros 1321 | 1322 | copyInt_(q, 0); // q=0 1323 | while (!greaterShift(y, r, kx - ky)) { // while (leftShift_(y,kx-ky) <= r) { 1324 | subShift_(r, y, kx - ky); // r=r-leftShift_(y,kx-ky) 1325 | q[kx - ky]++; // q[kx-ky]++; 1326 | } // } 1327 | 1328 | for (i = kx - 1; i >= ky; i--) { 1329 | if (r[i] == y[ky - 1]) 1330 | q[i - ky] = mask; 1331 | else 1332 | q[i - ky] = Math.floor((r[i] * radix + r[i - 1]) / y[ky - 1]); 1333 | 1334 | //The following for(;;) loop is equivalent to the commented while loop, 1335 | //except that the uncommented version avoids overflow. 1336 | //The commented loop comes from HAC, which assumes r[-1]==y[-1]==0 1337 | // while (q[i-ky]*(y[ky-1]*radix+y[ky-2]) > r[i]*radix*radix+r[i-1]*radix+r[i-2]) 1338 | // q[i-ky]--; 1339 | for (; ; ) { 1340 | y2 = (ky > 1 ? y[ky - 2] : 0) * q[i - ky]; 1341 | c = y2 >> bpe; 1342 | y2 = y2 & mask; 1343 | y1 = c + q[i - ky] * y[ky - 1]; 1344 | c = y1 >> bpe; 1345 | y1 = y1 & mask; 1346 | 1347 | if (c == r[i] ? y1 == r[i - 1] ? y2 > (i > 1 ? r[i - 2] : 0) : y1 > r[i - 1] : c > r[i]) 1348 | q[i - ky]--; 1349 | else 1350 | break; 1351 | } 1352 | 1353 | linCombShift_(r, y, -q[i - ky], i - ky); //r=r-q[i-ky]*leftShift_(y,i-ky) 1354 | if (negative(r)) { 1355 | addShift_(r, y, i - ky); //r=r+leftShift_(y,i-ky) 1356 | q[i - ky]--; 1357 | } 1358 | } 1359 | 1360 | rightShift_(y, a); //undo the normalization step 1361 | rightShift_(r, a); //undo the normalization step 1362 | } 1363 | 1364 | //do carries and borrows so each element of the bigInt x fits in bpe bits. 1365 | function carry_(x) { 1366 | var i, k, c, b; 1367 | k = x.length; 1368 | c = 0; 1369 | for (i = 0; i < k; i++) { 1370 | c += x[i]; 1371 | b = 0; 1372 | if (c < 0) { 1373 | b = -(c >> bpe); 1374 | c += b * radix; 1375 | } 1376 | x[i] = c & mask; 1377 | c = (c >> bpe) - b; 1378 | } 1379 | } 1380 | 1381 | //return x mod n for bigInt x and integer n. 1382 | function modInt(x, n) { 1383 | var i, c = 0; 1384 | for (i = x.length - 1; i >= 0; i--) 1385 | c = (c * radix + x[i]) % n; 1386 | return c; 1387 | } 1388 | 1389 | //convert the integer t into a bigInt with at least the given number of bits. 1390 | //the returned array stores the bigInt in bpe-bit chunks, little endian (buff[0] is least significant word) 1391 | //Pad the array with leading zeros so that it has at least minSize elements. 1392 | //There will always be at least one leading 0 element. 1393 | function int2bigInt(t, bits, minSize) { 1394 | // : there is a problem with this code. It fails to add a leading [0] in cases 1395 | // where the minimum size / bits is not large enough to contain the int. For 1396 | // example: 1397 | // int2bigInt(17, 0, 0) ===> [17] 1398 | // str2bigInt(17, 10, 0) ===> [17, 0] 1399 | // I've fixed this by converting to string and calling str2bigInt. 1400 | var i, k; 1401 | k = Math.ceil(bits / bpe) + 1; 1402 | k = minSize > k ? minSize : k; 1403 | return str2bigInt(t.toString(), 10, k); 1404 | // Old code 1405 | //var i, k; 1406 | //k = Math.ceil(bits / bpe) + 1; 1407 | //k = minSize > k ? minSize : k; 1408 | //buff = new Array(k); 1409 | //copyInt_(buff, t); 1410 | //return buff; 1411 | } 1412 | 1413 | //return the bigInt given a string representation in a given base. 1414 | //Pad the array with leading zeros so that it has at least minSize elements. 1415 | //If base=-1, then it reads in a space-separated list of array elements in decimal. 1416 | //The array will always have at least one leading zero, unless base=-1. 1417 | function str2bigInt(s, base, minSize) { 1418 | var d, i, j, x, y, kk; 1419 | var k = s.length; 1420 | if (base == -1) { //comma-separated list of array elements in decimal 1421 | x = new Array(0); 1422 | for (; ; ) { 1423 | y = new Array(x.length + 1); 1424 | for (i = 0; i < x.length; i++) 1425 | y[i + 1] = x[i]; 1426 | y[0] = parseInt(s, 10); 1427 | x = y; 1428 | d = s.indexOf(',', 0); 1429 | if (d < 1) 1430 | break; 1431 | s = s.substring(d + 1); 1432 | if (s.length == 0) 1433 | break; 1434 | } 1435 | if (x.length < minSize) { 1436 | y = new Array(minSize); 1437 | copy_(y, x); 1438 | return y; 1439 | } 1440 | return x; 1441 | } 1442 | 1443 | //x = int2bigInt(0, base * k, 0); // : had to remove this to fix recursion 1444 | x = new Array(Math.ceil(base * k / bpe)); copyInt_(x, 0); // : using this instead 1445 | 1446 | for (i = 0; i < k; i++) { 1447 | d = digitsStr.indexOf(s.substring(i, i + 1), 0); 1448 | if (base <= 36 && d >= 36) //convert lowercase to uppercase if base<=36 1449 | d -= 26; 1450 | if (d >= base || d < 0) { //stop at first illegal character 1451 | break; 1452 | } 1453 | multInt_(x, base); 1454 | addInt_(x, d); 1455 | } 1456 | 1457 | for (k = x.length; k > 0 && !x[k - 1]; k--); //strip off leading zeros 1458 | k = minSize > k + 1 ? minSize : k + 1; 1459 | y = new Array(k); 1460 | kk = k < x.length ? k : x.length; 1461 | for (i = 0; i < kk; i++) 1462 | y[i] = x[i]; 1463 | for (; i < k; i++) 1464 | y[i] = 0; 1465 | return y; 1466 | } 1467 | 1468 | //is bigint x equal to integer y? 1469 | //y must have less than bpe bits 1470 | function equalsInt(x, y) { 1471 | var i; 1472 | if (x[0] != y) 1473 | return 0; 1474 | for (i = 1; i < x.length; i++) 1475 | if (x[i]) 1476 | return 0; 1477 | return 1; 1478 | } 1479 | 1480 | //are bigints x and y equal? 1481 | //this works even if x and y are different lengths and have arbitrarily many leading zeros 1482 | function equals(x, y) { 1483 | var i; 1484 | var k = x.length < y.length ? x.length : y.length; 1485 | for (i = 0; i < k; i++) 1486 | if (x[i] != y[i]) 1487 | return 0; 1488 | if (x.length > y.length) { 1489 | for (; i < x.length; i++) 1490 | if (x[i]) 1491 | return 0; 1492 | } else { 1493 | for (; i < y.length; i++) 1494 | if (y[i]) 1495 | return 0; 1496 | } 1497 | return 1; 1498 | } 1499 | 1500 | //is the bigInt x equal to zero? 1501 | function isZero(x) { 1502 | var i; 1503 | for (i = 0; i < x.length; i++) 1504 | if (x[i]) 1505 | return 0; 1506 | return 1; 1507 | } 1508 | 1509 | //convert a bigInt into a string in a given base, from base 2 up to base 95. 1510 | //Base -1 prints the contents of the array representing the number. 1511 | function bigInt2str(x, base) { 1512 | var i, t, s = ""; 1513 | 1514 | if (s6.length != x.length) 1515 | s6 = dup(x); 1516 | else 1517 | copy_(s6, x); 1518 | 1519 | if (base == -1) { //return the list of array contents 1520 | for (i = x.length - 1; i > 0; i--) 1521 | s += x[i] + ','; 1522 | s += x[0]; 1523 | } 1524 | else { //return it in the given base 1525 | while (!isZero(s6)) { 1526 | t = divInt_(s6, base); //t=s6 % base; s6=floor(s6/base); 1527 | s = digitsStr.substring(t, t + 1) + s; 1528 | } 1529 | } 1530 | if (s.length == 0) 1531 | s = "0"; 1532 | return s; 1533 | } 1534 | 1535 | //------------------------------------------------------------------------------------------------// 1536 | // Global OO-style interface to the BigInt library 1537 | //------------------------------------------------------------------------------------------------// 1538 | function BigInt() { this.init.apply(this, arguments) }; 1539 | 1540 | BigInt.prototype = { 1541 | init: function (o, base) { 1542 | var neg, qua; 1543 | if (typeof (base) === 'number') { 1544 | // Use the explicit base if it is provided. Otherwise, 1545 | // fall back on pattern recognition. 1546 | o = o.replace(/^(-)/, ''); 1547 | neg = RegExp.$1; 1548 | this.bigInt = str2bigInt(o, base, 0); 1549 | this.bigInt = str2bigInt(o, base, 0); 1550 | if (neg) this.mul(-1); 1551 | } else if (typeof (o) === 'string') { 1552 | o = o.replace(/^(-)?(0x|0b|0o|0|)/, ''); 1553 | neg = RegExp.$1; 1554 | qua = RegExp.$2; 1555 | base = { '0x': 16, '0b': 2, '0o': 8, '0': 8}[qua] || 10; 1556 | this.bigInt = str2bigInt(o, base, 0); 1557 | if (neg) this.mul(-1); 1558 | } else if (typeof (o) === 'number') { 1559 | this.bigInt = int2bigInt(o, 0, 0); 1560 | } else if (o instanceof BigInt) { 1561 | this.bigInt = o.clone().bigInt; 1562 | } else if (o instanceof Array) { 1563 | this.bigInt = o; 1564 | } else { 1565 | throw "Unrecognized argument type: " + typeof (o) + " (" + o + ")"; 1566 | } 1567 | }, 1568 | 1569 | add: function (other) { 1570 | if (other instanceof BigInt) { 1571 | return new BigInt(add(this.bigInt, other.bigInt)); 1572 | } else { 1573 | throw "Unsupported"; 1574 | } 1575 | }, 1576 | 1577 | sub: function (other) { 1578 | if (other instanceof BigInt) { 1579 | return new BigInt(sub(this.bigInt, other.bigInt)); 1580 | } else { 1581 | throw "Unsupported"; 1582 | } 1583 | }, 1584 | 1585 | mod: function (other) { 1586 | if (other instanceof BigInt) { 1587 | return new BigInt(mod(this.bigInt, other.bigInt)); 1588 | } else { 1589 | throw "Unsupported"; 1590 | } 1591 | }, 1592 | 1593 | mul: function (other) { 1594 | if (other instanceof BigInt) { 1595 | return new BigInt(mult(this.bigInt, other.bigInt)); 1596 | } else { 1597 | throw "Unsupported"; 1598 | } 1599 | }, 1600 | 1601 | mulMod: function (other, n) { 1602 | if (other instanceof BigInt && n instanceof BigInt) { 1603 | return new BigInt(multMod(this.bigInt, other.bigInt, n.bigInt)); 1604 | } else { 1605 | throw "Unsupported"; 1606 | } 1607 | }, 1608 | 1609 | powMod: function (other, n) { 1610 | if (other instanceof BigInt && n instanceof BigInt) { 1611 | return new BigInt(powMod(this.bigInt, other.bigInt, n.bigInt)); 1612 | } else { 1613 | throw "Unsupported"; 1614 | } 1615 | }, 1616 | 1617 | div: function (other) { 1618 | if (other instanceof BigInt) { 1619 | var q = new Array(0); 1620 | var r = new Array(0); 1621 | divide_(this.bigInt, new BigInt(other).bigInt, q, r); 1622 | return new Array(q, r); 1623 | } else { 1624 | throw "Unsupported"; 1625 | } 1626 | }, 1627 | 1628 | inverseMod: function (other) { 1629 | if (other instanceof BigInt) { 1630 | return new BigInt(inverseMod(this.bigInt, other.bigInt)); 1631 | } else { 1632 | throw "Unsupported"; 1633 | } 1634 | }, 1635 | 1636 | equals: function (other) { 1637 | if (other instanceof BigInt) { 1638 | return equals(this.bigInt, other.bigInt); 1639 | } else { 1640 | throw "Unsupported"; 1641 | } 1642 | }, 1643 | 1644 | isZero: function () { 1645 | return isZero(this.bigInt); 1646 | }, 1647 | 1648 | isNegative: function () { 1649 | return !!negative(this.bigInt); 1650 | }, 1651 | 1652 | isPositive: function () { 1653 | return !isZero(this.bigInt) && !negative(this.bigInt); 1654 | }, 1655 | 1656 | millerRabin: function (other) { 1657 | if (other instanceof BigInt) { 1658 | return new BigInt(millerRabin(this.bigInt, other)); 1659 | } else { 1660 | throw "Unsupported"; 1661 | } 1662 | }, 1663 | 1664 | gcd: function (other) { 1665 | if (other instanceof BigInt) { 1666 | return new BigInt(GCD(this.bigInt, other.bigInt)); 1667 | } else { 1668 | throw "Unsupported"; 1669 | } 1670 | }, 1671 | 1672 | greaterThan: function (other) { 1673 | return greater(this.bigInt, new BigInt(other).bigInt); 1674 | }, 1675 | 1676 | lessThan: function (other) { 1677 | return !greater(this.bigInt, new BigInt(other).bigInt); 1678 | }, 1679 | 1680 | bitSize: function () { 1681 | return bitSize(this.bigInt); 1682 | }, 1683 | 1684 | clone: function () { 1685 | return new BigInt(dup(this.bigInt)); 1686 | }, 1687 | 1688 | dup: function () { 1689 | return new BigInt(dup(this.bigInt)); 1690 | }, 1691 | 1692 | rightShift: function (n) { 1693 | if (typeof (n) === 'number') { 1694 | var i = dup(this.bigInt); 1695 | rightShift_(i, n); 1696 | return new BigInt(i); 1697 | } else { 1698 | throw "Unsupported"; 1699 | } 1700 | }, 1701 | 1702 | isBit0Set: function (n) { 1703 | return (this.bigInt[0] & 1) === 1; 1704 | }, 1705 | 1706 | toString: function (base) { 1707 | return bigInt2str(this.bigInt, base || 10); 1708 | }, 1709 | 1710 | valueOf: function () { 1711 | throw "You must use bigint functions instead of native operators"; 1712 | } 1713 | }; 1714 | 1715 | Global.BigInt = BigInt; 1716 | Global.BigInt.randBigInt = function () { return new BigInt(randBigInt.apply(this, arguments)) }; 1717 | Global.BigInt.random = BigInt.randBigInt; 1718 | 1719 | })(window); 1720 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 karlgluck 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### [See the Demo!](http://karlgluck.github.io/ThresholdJS) 2 | 3 | What is ThresholdJS? 4 | ==================== 5 | 6 | ThresholdJS implements [Shamir's Secret Sharing](http://en.wikipedia.org/wiki/Shamir's_Secret_Sharing) algorithm with no frills. Given a secret number S, a prime number p > S, a number of shares n and a threshold k, it returns n (x,y) coordinates such that one can recover S given p, n, k and any k of those coordinates. 7 | 8 | It is a direct translation of the [C implementation](https://gist.github.com/genos/1313643) posted by [GitHub user Genos](https://github.com/genos) cross-referenced with the original paper "How to Share a Secret" published in 1979. 9 | 10 | This code was created with the intent to split Bitcoin private keys into many parts so that the key can be safely stored in a distributed fashion. One could print some out and give them to friends, hide others in pictures uploaded to image-sharing websites ([steganography](http://en.wikipedia.org/wiki/Steganography">)) and secure some in safety deposit boxes. The more places the better! 11 | 12 | I wrote this because I was interested in the math behind the algorithm and wanted to create an implementation that I had confidence in. 13 | 14 | What's Unique? 15 | ============== 16 | 17 | [Other](https://github.com/amper5and/secrets.js) [implementations](http://rosick.com/crypto/sss.html) are long and opaque. This one is short and simple, which makes it easy to verify. 18 | 19 | Its simplicity comes from one key point: it makes use of a large integer object. 20 | 21 | Shamir's Secret Sharing algorithm relies on a large prime number. It must be bigger than any number you wish to split, so others usually split the secret into 32-bit chunks and use a hard-coded 33-bit prime in the algorithm. The secret is padded to a 32-bit boundary, each chunk is split individually, and the i'th piece from each is concatenated to make the i'th share of the secret. The parameters n and k are then tacked on and whole thing is hex encoded. 22 | 23 | Since I know I'm encoding a single 256-bit number, this code does not do that. Instead, it just use a prime large enough to encode the entire secret: [2^257-93](http://primes.utm.edu/lists/2small/200bit.html). This number was chosen because it is easily remembered or looked up since it's the largest 257-bit prime. 24 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ThresholdJS - Shamir's Secret Sharing in Javascript 5 | 6 | 7 | 8 | 12 | 13 | 14 | 15 | 16 | Fork me on GitHub 17 |
18 |
19 | 30 |

Quickstart

31 |
    32 |
  1. Click "Random" to generate a secret 256-bit integer
  2. 33 |
  3. Click "Generate" to run the algorithm
  4. 34 |
  5. Copy any 4 rows from the "Generated Pieces" text area. These are the pieces of your number.
  6. 35 |
  7. Paste them in the "Pieces for Recovery" text area
  8. 36 |
  9. Hit "Recover Secret" and watch your original number reappear. Try it with 4 different rows. Magic!
  10. 37 |
38 |
39 |

Splitting the Secret

40 |
41 |
42 |
43 | 44 |
45 |
46 | 47 |
48 | 49 |
50 |
51 |
52 |
53 |
54 | 55 |
56 | 57 |
58 |
59 |
60 | 61 |
62 | 63 |
64 |
65 |
66 |
67 | 68 |
69 |
70 |
71 |
72 |

Generated Pieces of the Secret

73 |

These are the n pieces that were created from the integer above. Pick any k 74 | and enter them into the recovery section to test it out.

75 | 76 | 77 |
78 | 79 |

Recovering the Secret

80 |
81 |
82 |
83 | 84 |
85 | 86 |
87 |
88 |
89 |
90 | 91 |
92 |
93 |
94 | 95 |
96 | 97 |
98 |
99 |
100 |
101 | 102 | Implemented by Karl Gluck 103 | 104 |
105 |
106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 194 | 195 | -------------------------------------------------------------------------------- /threshold.js: -------------------------------------------------------------------------------- 1 | // Implementation based on shamir_threshold_scheme.c from https://gist.github.com/genos/1313643 2 | // Translated to Javascript by Karl Gluck 3 | // Requires BigInt.js 4 | 5 | // Wrap all functions 6 | (function () { 7 | 8 | // Modular exponentiation, via Wikipedia and Schneier's "Applied Cryptography" 9 | function expt_mod(/*BigInt*/ b, /*BigInt*/ e, /*BigInt*/ m) { 10 | var r = new BigInt(1); 11 | while (!e.isZero()) { 12 | if (e.isBit0Set()) { // if (e & 1) 13 | r = r.mulMod(b, m); // r = (r * b) % m; 14 | } 15 | e = e.rightShift(1); // e >>= 1; 16 | b = b.mulMod(b, m); // b = (b * b) % m; 17 | } 18 | return r; 19 | } 20 | 21 | 22 | // Modular inverse; x^{phi(p) - 1} = 1 mod p, and p prime => phi(p) = p - 1 23 | function mod_inv(/*BigInt*/x, /*BigInt*/ p) { 24 | return expt_mod(x, p.sub(new BigInt(2)), p); 25 | } 26 | 27 | 28 | // Horner's method to evaluate polynomial given by coeffs[] modulo `mod` 29 | function horner_mod(/*BigInt*/ x, /*BigInt[]*/ coeffs, /*uint*/ k, /*BigInt*/ mod) { 30 | /*BigInt*/ var i; 31 | /*BigInt*/ var y = new BigInt(0); 32 | 33 | for (i = k - 1; i > 0; i--) { 34 | y = y.add(coeffs[i]).mod(mod); // y = (y + coeffs[i]) % mod; 35 | y = y.mulMod(x, mod); // y = (y * x) % mod; 36 | } 37 | y = y.add(coeffs[0]).mod(mod); // y = (y + coeffs[0]) % mod; 38 | 39 | return y; 40 | } 41 | 42 | // Shamir (k, n) threshold scheme 43 | // s - the secret you're saving 44 | // k - the minimum number to reconstruct the secret 45 | // n - the number of participants 46 | // p - a prime number > max(s, n) 47 | // returns an array of {x:<>, y:<>} objects with the encoding points 48 | function shamir_threshold(bits, /*BigInt*/ s, /*ulong*/ k, /*ulong*/ n, /*BigInt*/ p){ 49 | var i, j; 50 | var unique; 51 | var x, coeffs = new Array(k); 52 | var xy_pairs = new Array(n); 53 | var psub2 = new BigInt(p).sub(new BigInt(2)); 54 | 55 | if (!p.greaterThan(s) || !p.greaterThan(n)) { throw "p <= max(s,n)"; } 56 | 57 | coeffs[0] = s; 58 | for (i = 1; i < k; i++) { 59 | coeffs[i] = BigInt.random(bits,0).mod(psub2).add(new BigInt(1)); // coeffs[i] = (ulong)(1 + (rand() % (p - 2))); 60 | } 61 | 62 | for (i = 0; i < n; i++) { 63 | unique = 0; 64 | while (!unique) { 65 | unique = 1; 66 | x = BigInt.random(bits,0).mod(psub2).add(new BigInt(1)); // x = (ulong)(1 + (rand() % (p - 2))); 67 | for (j = 0; j < i; j++) { 68 | if (xy_pairs[j].x.equals(x)) { 69 | unique = 0; 70 | break; 71 | } 72 | } 73 | } 74 | 75 | xy_pairs[i] = { 76 | x: x, 77 | y: horner_mod(x, coeffs, k, p) 78 | } 79 | } 80 | 81 | return xy_pairs; 82 | } 83 | 84 | 85 | // Lagrange interpolation to recover the constant term 86 | // xy_pairs - an array of {x:<>, y:<>} objects with the encoding points 87 | // k - the minimum number to reconstruct the secret 88 | // p - a prime number > max(s, n) 89 | function interp_const(/*point[]*/ xy_pairs, /*ulong*/ k, /*BigInt*/ p){ 90 | var i, j; 91 | var c; 92 | var s = new BigInt(0); 93 | 94 | for (i = 0; i < k; i++) { 95 | c = new BigInt(1); 96 | for (j = 0; j < k; j++) { 97 | if (xy_pairs[i].x.greaterThan(xy_pairs[j].x)) { 98 | // c = (c * xy_pairs[j].x * mod_inv(p - (xy_pairs[i].x - xy_pairs[j].x), p)) % p; 99 | c = c.mul(xy_pairs[j].x).mulMod(mod_inv(p.sub(xy_pairs[i].x.sub(xy_pairs[j].x)), p), p); 100 | } 101 | else if (xy_pairs[j].x.greaterThan(xy_pairs[i].x)) { 102 | // c = (c * xy_pairs[j].x * mod_inv(xy_pairs[j].x - xy_pairs[i].x, p)) % p; 103 | c = c.mul(xy_pairs[j].x).mulMod(mod_inv(xy_pairs[j].x.sub(xy_pairs[i].x), p), p); 104 | } 105 | else { 106 | continue; 107 | } 108 | } 109 | s = s.add(xy_pairs[i].y.mul(c)).mod(p); //s = (s + xy_pairs[i].y * c) % p; 110 | } 111 | return s; 112 | } 113 | 114 | function ThresholdCrypto() { this.init.apply(this, arguments) }; 115 | ThresholdCrypto.prototype = { 116 | 117 | init: function (bits, n, k, p) { 118 | this.bits = bits; 119 | this.n = n; 120 | this.k = k; 121 | this.p = p; // the prime number 122 | }, 123 | 124 | encrypt: function (s) { 125 | return shamir_threshold(this.bits, s, this.k, this.n, this.p); 126 | }, 127 | 128 | decrypt: function (xy_pairs) { 129 | return interp_const(xy_pairs, this.k, this.p); 130 | }, 131 | 132 | valueOf: function () { 133 | throw ""; 134 | } 135 | }; 136 | 137 | var Global = (function () { return this })(); 138 | Global.ThresholdCrypto = ThresholdCrypto; 139 | 140 | })(); 141 | --------------------------------------------------------------------------------