├── .gitignore ├── .travis.yml ├── Contributors.md ├── LICENSE ├── README.md ├── docs ├── safeprime.txt └── sssa.md ├── package.json ├── sssa-min.js ├── sssa.js └── test ├── all.js ├── sssa.js └── testing.html /.gitignore: -------------------------------------------------------------------------------- 1 | # ---> Node 2 | # Logs 3 | logs 4 | *.log 5 | npm-debug.log* 6 | 7 | # Runtime data 8 | pids 9 | *.pid 10 | *.seed 11 | 12 | # Directory for instrumented libs generated by jscoverage/JSCover 13 | lib-cov 14 | 15 | # Coverage directory used by tools like istanbul 16 | coverage 17 | 18 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 19 | .grunt 20 | 21 | # node-waf configuration 22 | .lock-wscript 23 | 24 | # Compiled binary addons (http://nodejs.org/api/addons.html) 25 | build/Release 26 | 27 | # Dependency directory 28 | # https://docs.npmjs.com/misc/faq#should-i-check-my-node-modules-folder-into-git 29 | node_modules 30 | 31 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "4.1" 4 | - "4.0" 5 | - "0.12" 6 | - "0.11" 7 | 8 | script: 9 | - node ./test/sssa.js 10 | -------------------------------------------------------------------------------- /Contributors.md: -------------------------------------------------------------------------------- 1 | Contributors: 2 | Alexander Scheel - alexander.m.scheel@gmail.com 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 Alexander Scheel, Joel May, Matthew Burket 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # sssa-js 2 | [![Build Status](https://travis-ci.org/SSSaaS/sssa-js.svg?branch=master)](https://travis-ci.org/SSSaaS/sssa-js) 3 | 4 | An implementation of Shamir's Secret Sharing Algorithm in JavaScript 5 | Currently working in Firefox, Chrome, Safari, Opera, Edge, 6 | and Node.js v0.11 or later. 7 | 8 | Copyright (C) 2015 Alexander Scheel, Joel May, Matthew Burket 9 | See Contributors.md for a complete list of contributors. 10 | Licensed under the MIT License. 11 | 12 | ## Usage 13 | Note: this library is for a pure implementation of SSS in JavaScript; 14 | if you are looking for the API Library for SSSaaS, look [here](https://github.com/SSSAAS/sssaas-js). 15 | 16 | sssa.create(minimum, shares, raw) - creates a set of shares 17 | 18 | sssa.combine(shares) - combines shares into secret 19 | 20 | For more detailed documentation, check out docs/sssa.md. 21 | 22 | To use in a browser, use either `sssa.js` with browserify or use the pre-built 23 | `sssa-min.js`. 24 | 25 | ## Contributing 26 | We welcome pull requests, issues, security advice on this library, or other contributions you feel are necessary. Feel free to open an issue to discuss any questions you have about this library. 27 | 28 | To develop; `npm install` will install the necessary dependencies. After making 29 | changes, please update the minified and testing bundles: 30 | 31 | browserify ./sssa.js > sssa-base.js && uglifyjs --compress -- ./sssa-base.js > sssa-min.js && rm ./sssa-base.js && browserify ./test/sssa.js > ./test/all.js 32 | 33 | The reference implementation for this cross-language project was written in Go, [here](https://github.com/SSSAAS/sssa-golang). 34 | Please make sure all tests pass before submitting a pull request. In particular, 35 | `node ./tests/sssa.js` and loading `tests/testing.html` in available browsers 36 | after rebuilding all.js with browserify via `browserify ./tests/sssa.js > ./tests/all.js` 37 | will run all internal tests and the [go-libtest](https://github.com/SSSAAS/go-libtest) suite's 38 | tests should be run against the changes before submission. 39 | 40 | For security issues, send a GPG-encrypted email to with public key [0xBDC5F518A973035E](https://pgp.mit.edu/pks/lookup?op=vindex&search=0xBDC5F518A973035E). 41 | -------------------------------------------------------------------------------- /docs/safeprime.txt: -------------------------------------------------------------------------------- 1 | 2^256 - 189: 2 | 115792089237316195423570985008687907853269984665640564039457584007913129639747 3 | -------------------------------------------------------------------------------- /docs/sssa.md: -------------------------------------------------------------------------------- 1 | # SSSA - JavaScript 2 | ## Constants 3 | prime = 115792089237316195423570985008687907853269984665640564039457584007913129639747 4 | Safe Prime; [bigInt](https://github.com/peterolson/BigInteger.js); not exported 5 | 6 | ## Functions 7 | create(minimum, number, raw) 8 | minimum - number of shares required to recreate the secret 9 | number - total number of shares to generate 10 | raw - secret to protect, as a string 11 | 12 | returns shares as an array of base64 strings of variable length 13 | dependent on the size of the raw secret 14 | 15 | combine(shares) 16 | shares - array of base64 strings returned by create function 17 | 18 | returns a string of secret 19 | note: this string can be ill-formatted utf8 potentially, if the 20 | minimum number of shares was not met 21 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sssa-js", 3 | "version": "0.0.1", 4 | "description": "Helper cryptography module for JavaScript", 5 | "main": "sssa.js", 6 | "scripts": { 7 | "test": "node ./test/sssa.js" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/SSSaaS/sssa-js.git" 12 | }, 13 | "keywords": [ 14 | "javascript", 15 | "sssa", 16 | "shamir", 17 | "secret", 18 | "sharing", 19 | "crypto" 20 | ], 21 | "author": "Alexander Scheel", 22 | "license": "MIT", 23 | "bugs": { 24 | "url": "https://github.com/SSSaaS/sssa-js/issues" 25 | }, 26 | "homepage": "https://github.com/SSSaaS/sssa-js#readme", 27 | "devDependencies": { 28 | "browserify": "^12.0.1", 29 | "uglify-js": "^2.6.0" 30 | }, 31 | "dependencies": { 32 | "big-integer": "^1.6.5", 33 | "get-random-values": "^1.1.1", 34 | "global": "^4.3.0", 35 | "utf-8": "^1.0.0" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /sssa-min.js: -------------------------------------------------------------------------------- 1 | !function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a="function"==typeof require&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}for(var i="function"==typeof require&&require,o=0;ovalue,this.isSmall=!0}function isPrecise(n){return n>-MAX_INT&&MAX_INT>n}function smallToArray(n){return 1e7>n?[n]:1e14>n?[n%1e7,Math.floor(n/1e7)]:[n%1e7,Math.floor(n/1e7)%1e7,Math.floor(n/1e14)]}function arrayToSmall(arr){trim(arr);var length=arr.length;if(4>length&&compareAbs(arr,MAX_INT_ARR)<0)switch(length){case 0:return 0;case 1:return arr[0];case 2:return arr[0]+arr[1]*BASE;default:return arr[0]+(arr[1]+arr[2]*BASE)*BASE}return arr}function trim(v){for(var i=v.length;0===v[--i];);v.length=i+1}function createArray(length){for(var x=new Array(length),i=-1;++i0?Math.floor(n):Math.ceil(n)}function add(a,b){var sum,i,l_a=a.length,l_b=b.length,r=new Array(l_a),carry=0,base=BASE;for(i=0;l_b>i;i++)sum=a[i]+b[i]+carry,carry=sum>=base?1:0,r[i]=sum-carry*base;for(;l_a>i;)sum=a[i]+carry,carry=sum===base?1:0,r[i++]=sum-carry*base;return carry>0&&r.push(carry),r}function addAny(a,b){return a.length>=b.length?add(a,b):add(b,a)}function addSmall(a,carry){var sum,i,l=a.length,r=new Array(l),base=BASE;for(i=0;l>i;i++)sum=a[i]-base+carry,carry=Math.floor(sum/base),r[i]=sum-carry*base,carry+=1;for(;carry>0;)r[i++]=carry%base,carry=Math.floor(carry/base);return r}function subtract(a,b){var i,difference,a_l=a.length,b_l=b.length,r=new Array(a_l),borrow=0,base=BASE;for(i=0;b_l>i;i++)difference=a[i]-borrow-b[i],0>difference?(difference+=base,borrow=1):borrow=0,r[i]=difference;for(i=b_l;a_l>i;i++){if(difference=a[i]-borrow,!(0>difference)){r[i++]=difference;break}difference+=base,r[i]=difference}for(;a_l>i;i++)r[i]=a[i];return trim(r),r}function subtractAny(a,b,sign){var value;return compareAbs(a,b)>=0?value=subtract(a,b):(value=subtract(b,a),sign=!sign),value=arrayToSmall(value),"number"==typeof value?(sign&&(value=-value),new SmallInteger(value)):new BigInteger(value,sign)}function subtractSmall(a,b,sign){var i,difference,l=a.length,r=new Array(l),carry=-b,base=BASE;for(i=0;l>i;i++)difference=a[i]+carry,carry=Math.floor(difference/base),difference%=base,r[i]=0>difference?difference+base:difference;return r=arrayToSmall(r),"number"==typeof r?(sign&&(r=-r),new SmallInteger(r)):new BigInteger(r,sign)}function multiplyLong(a,b){var product,carry,i,a_i,b_j,a_l=a.length,b_l=b.length,l=a_l+b_l,r=createArray(l),base=BASE;for(i=0;a_l>i;++i){a_i=a[i];for(var j=0;b_l>j;++j)b_j=b[j],product=a_i*b_j+r[i+j],carry=Math.floor(product/base),r[i+j]=product-carry*base,r[i+j+1]+=carry}return trim(r),r}function multiplySmall(a,b){var product,i,l=a.length,r=new Array(l),base=BASE,carry=0;for(i=0;l>i;i++)product=a[i]*b+carry,carry=Math.floor(product/base),r[i]=product-carry*base;for(;carry>0;)r[i++]=carry%base,carry=Math.floor(carry/base);return r}function shiftLeft(x,n){for(var r=[];n-- >0;)r.push(0);return r.concat(x)}function multiplyKaratsuba(x,y){var n=Math.max(x.length,y.length);if(400>=n)return multiplyLong(x,y);n=Math.ceil(n/2);var b=x.slice(n),a=x.slice(0,n),d=y.slice(n),c=y.slice(0,n),ac=multiplyKaratsuba(a,c),bd=multiplyKaratsuba(b,d),abcd=multiplyKaratsuba(addAny(a,b),addAny(c,d));return addAny(addAny(ac,shiftLeft(subtract(subtract(abcd,ac),bd),n)),shiftLeft(bd,2*n))}function multiplySmallAndArray(a,b,sign){return BASE>a?new BigInteger(multiplySmall(b,a),sign):new BigInteger(multiplyLong(b,smallToArray(a)),sign)}function square(a){var product,carry,i,a_i,a_j,l=a.length,r=createArray(l+l),base=BASE;for(i=0;l>i;i++){a_i=a[i];for(var j=0;l>j;j++)a_j=a[j],product=a_i*a_j+r[i+j],carry=Math.floor(product/base),r[i+j]=product-carry*base,r[i+j+1]+=carry}return trim(r),r}function divMod1(a,b){var quotientDigit,shift,carry,borrow,i,l,q,a_l=a.length,b_l=b.length,base=BASE,result=createArray(b.length),divisorMostSignificantDigit=b[b_l-1],lambda=Math.ceil(base/(2*divisorMostSignificantDigit)),remainder=multiplySmall(a,lambda),divisor=multiplySmall(b,lambda);for(remainder.length<=a_l&&remainder.push(0),divisor.push(0),divisorMostSignificantDigit=divisor[b_l-1],shift=a_l-b_l;shift>=0;shift--){for(quotientDigit=base-1,remainder[shift+b_l]!==divisorMostSignificantDigit&&(quotientDigit=Math.floor((remainder[shift+b_l]*base+remainder[shift+b_l-1])/divisorMostSignificantDigit)),carry=0,borrow=0,l=divisor.length,i=0;l>i;i++)carry+=quotientDigit*divisor[i],q=Math.floor(carry/base),borrow+=remainder[shift+i]-(carry-q*base),carry=q,0>borrow?(remainder[shift+i]=borrow+base,borrow=-1):(remainder[shift+i]=borrow,borrow=0);for(;0!==borrow;){for(quotientDigit-=1,carry=0,i=0;l>i;i++)carry+=remainder[shift+i]-base+divisor[i],0>carry?(remainder[shift+i]=carry+base,carry=0):(remainder[shift+i]=carry,carry=1);borrow+=carry}result[shift]=quotientDigit}return remainder=divModSmall(remainder,lambda)[0],[arrayToSmall(result),arrayToSmall(remainder)]}function divMod2(a,b){for(var guess,xlen,highx,highy,check,a_l=a.length,b_l=b.length,result=[],part=[],base=BASE;a_l;)if(part.unshift(a[--a_l]),compareAbs(part,b)<0)result.push(0);else{xlen=part.length,highx=part[xlen-1]*base+part[xlen-2],highy=b[b_l-1]*base+b[b_l-2],xlen>b_l&&(highx=(highx+1)*base),guess=Math.ceil(highx/highy);do{if(check=multiplySmall(b,guess),compareAbs(check,part)<=0)break;guess--}while(guess);result.push(guess),part=subtract(part,check)}return result.reverse(),[arrayToSmall(result),arrayToSmall(part)]}function divModSmall(value,lambda){var i,q,remainder,divisor,length=value.length,quotient=createArray(length),base=BASE;for(remainder=0,i=length-1;i>=0;--i)divisor=remainder*base+value[i],q=truncate(divisor/lambda),remainder=divisor-q*lambda,quotient[i]=0|q;return[quotient,0|remainder]}function divModAny(self,v){var value,quotient,n=parseValue(v),a=self.value,b=n.value;if(0===b)throw new Error("Cannot divide by zero");if(self.isSmall)return n.isSmall?[new SmallInteger(truncate(a/b)),new SmallInteger(a%b)]:[CACHE[0],self];if(n.isSmall){if(1===b)return[self,CACHE[0]];if(-1==b)return[self.negate(),CACHE[0]];var abs=Math.abs(b);if(BASE>abs){value=divModSmall(a,abs),quotient=arrayToSmall(value[0]);var remainder=value[1];return self.sign&&(remainder=-remainder),"number"==typeof quotient?(self.sign!==n.sign&&(quotient=-quotient),[new SmallInteger(quotient),new SmallInteger(remainder)]):[new BigInteger(quotient,self.sign!==n.sign),new SmallInteger(remainder)]}b=smallToArray(abs)}var comparison=compareAbs(a,b);if(-1===comparison)return[CACHE[0],self];if(0===comparison)return[CACHE[self.sign===n.sign?1:-1],CACHE[0]];value=a.length+b.length<=200?divMod1(a,b):divMod2(a,b),quotient=value[0];var qSign=self.sign!==n.sign,mod=value[1],mSign=self.sign;return"number"==typeof quotient?(qSign&&(quotient=-quotient),quotient=new SmallInteger(quotient)):quotient=new BigInteger(quotient,qSign),"number"==typeof mod?(mSign&&(mod=-mod),mod=new SmallInteger(mod)):mod=new BigInteger(mod,mSign),[quotient,mod]}function compareAbs(a,b){if(a.length!==b.length)return a.length>b.length?1:-1;for(var i=a.length-1;i>=0;i--)if(a[i]!==b[i])return a[i]>b[i]?1:-1;return 0}function isBasicPrime(v){var n=v.abs();return n.isUnit()?!1:n.equals(2)||n.equals(3)||n.equals(5)?!0:n.isEven()||n.isDivisibleBy(3)||n.isDivisibleBy(5)?!1:n.lesser(25)?!0:void 0}function shift_isSmall(n){return("number"==typeof n||"string"==typeof n)&&+Math.abs(n)<=BASE||n instanceof BigInteger&&n.value.length<=1}function bitwise(x,y,fn){y=parseValue(y);for(var xSign=x.isNegative(),ySign=y.isNegative(),xRem=xSign?x.not():x,yRem=ySign?y.not():y,xBits=[],yBits=[],xStop=!1,yStop=!1;!xStop||!yStop;)xRem.isZero()?(xStop=!0,xBits.push(xSign?1:0)):xSign?xBits.push(xRem.isEven()?1:0):xBits.push(xRem.isEven()?0:1),yRem.isZero()?(yStop=!0,yBits.push(ySign?1:0)):ySign?yBits.push(yRem.isEven()?1:0):yBits.push(yRem.isEven()?0:1),xRem=xRem.over(2),yRem=yRem.over(2);for(var result=[],i=0;i=0;i--){var top=restricted?range.value[i]:BASE,digit=truncate(Math.random()*top);result.unshift(digit),top>digit&&(restricted=!1)}return result=arrayToSmall(result),low.add("number"==typeof result?new SmallInteger(result):new BigInteger(result,!1))}function stringify(digit){var v=digit.value;return"number"==typeof v&&(v=[v]),1===v.length&&v[0]<=36?"0123456789abcdefghijklmnopqrstuvwxyz".charAt(v[0]):"<"+v+">"}function toBase(n,base){if(base=bigInt(base),base.isZero()){if(n.isZero())return"0";throw new Error("Cannot convert nonzero numbers to base 0.")}if(base.equals(-1))return n.isZero()?"0":n.isNegative()?new Array(1-n).join("10"):"1"+new Array(+n).join("01");var minusSign="";if(n.isNegative()&&base.isPositive()&&(minusSign="-",n=n.abs()),base.equals(1))return n.isZero()?"0":minusSign+new Array(+n+1).join(1);for(var divmod,out=[],left=n;left.isNegative()||left.compareAbs(base)>=0;){divmod=left.divmod(base),left=divmod.quotient;var digit=divmod.remainder;digit.isNegative()&&(digit=base.minus(digit).abs(),left=left.next()),out.push(stringify(digit))}return out.push(stringify(left)),minusSign+out.reverse().join("")}function parseStringValue(v){if(isPrecise(+v)){var x=+v;if(x===truncate(x))return new SmallInteger(x);throw"Invalid integer: "+v}var sign="-"===v[0];sign&&(v=v.slice(1));var split=v.split(/e/i);if(split.length>2)throw new Error("Invalid integer: "+text.join("e"));if(2===split.length){var exp=split[1];if("+"===exp[0]&&(exp=exp.slice(1)),exp=+exp,exp!==truncate(exp)||!isPrecise(exp))throw new Error("Invalid integer: "+exp+" is not a valid exponent.");var text=split[0],decimalPlace=text.indexOf(".");if(decimalPlace>=0&&(exp-=text.length-decimalPlace,text=text.slice(0,decimalPlace)+text.slice(decimalPlace+1)),0>exp)throw new Error("Cannot include negative exponent part for integers");text+=new Array(exp+1).join("0"),v=text}var isValid=/^([0-9][0-9]*)$/.test(v);if(!isValid)throw new Error("Invalid integer: "+v);for(var r=[],max=v.length,l=LOG_BASE,min=max-l;max>0;)r.push(+v.slice(min,max)),min-=l,0>min&&(min=0),max-=l;return trim(r),new BigInteger(r,sign)}function parseNumberValue(v){return isPrecise(v)?new SmallInteger(v):parseStringValue(v.toString())}function parseValue(v){return"number"==typeof v?parseNumberValue(v):"string"==typeof v?parseStringValue(v):v}var BASE=1e7,LOG_BASE=7,MAX_INT=9007199254740992,MAX_INT_ARR=smallToArray(MAX_INT),LOG_MAX_INT=Math.log(MAX_INT);BigInteger.prototype.add=function(v){var n=parseValue(v);if(this.sign!==n.sign)return this.subtract(n.negate());var a=this.value,b=n.value;return n.isSmall?new BigInteger(addSmall(a,Math.abs(b)),this.sign):new BigInteger(addAny(a,b),this.sign)},BigInteger.prototype.plus=BigInteger.prototype.add,SmallInteger.prototype.add=function(v){var n=parseValue(v),a=this.value;if(0>a!==n.sign)return this.subtract(n.negate());var b=n.value;if(n.isSmall){if(isPrecise(a+b))return new SmallInteger(a+b);b=smallToArray(Math.abs(b))}return new BigInteger(addSmall(b,Math.abs(a)),0>a)},SmallInteger.prototype.plus=SmallInteger.prototype.add,BigInteger.prototype.subtract=function(v){var n=parseValue(v);if(this.sign!==n.sign)return this.add(n.negate());var a=this.value,b=n.value;return n.isSmall?subtractSmall(a,Math.abs(b),this.sign):subtractAny(a,b,this.sign)},BigInteger.prototype.minus=BigInteger.prototype.subtract,SmallInteger.prototype.subtract=function(v){var n=parseValue(v),a=this.value;if(0>a!==n.sign)return this.add(n.negate());var b=n.value;return n.isSmall?new SmallInteger(a-b):subtractSmall(b,Math.abs(a),a>=0)},SmallInteger.prototype.minus=SmallInteger.prototype.subtract,BigInteger.prototype.negate=function(){return new BigInteger(this.value,!this.sign)},SmallInteger.prototype.negate=function(){var sign=this.sign,small=new SmallInteger(-this.value);return small.sign=!sign,small},BigInteger.prototype.abs=function(){return new BigInteger(this.value,!1)},SmallInteger.prototype.abs=function(){return new SmallInteger(Math.abs(this.value))},BigInteger.prototype.multiply=function(v){var abs,n=parseValue(v),a=this.value,b=n.value,sign=this.sign!==n.sign;if(n.isSmall){if(0===b)return CACHE[0];if(1===b)return this;if(-1===b)return this.negate();if(abs=Math.abs(b),BASE>abs)return new BigInteger(multiplySmall(a,abs),sign);b=smallToArray(abs)}return a.length+b.length>4e3?new BigInteger(multiplyKaratsuba(a,b),sign):new BigInteger(multiplyLong(a,b),sign)},BigInteger.prototype.times=BigInteger.prototype.multiply,SmallInteger.prototype._multiplyBySmall=function(a){return isPrecise(a.value*this.value)?new SmallInteger(a.value*this.value):multiplySmallAndArray(Math.abs(a.value),smallToArray(Math.abs(this.value)),this.sign!==a.sign)},BigInteger.prototype._multiplyBySmall=function(a){return 0===a.value?CACHE[0]:1===a.value?this:-1===a.value?this.negate():multiplySmallAndArray(Math.abs(a.value),this.value,this.sign!==a.sign)},SmallInteger.prototype.multiply=function(v){return parseValue(v)._multiplyBySmall(this)},SmallInteger.prototype.times=SmallInteger.prototype.multiply,BigInteger.prototype.square=function(){return new BigInteger(square(this.value),!1)},SmallInteger.prototype.square=function(){var value=this.value*this.value;return isPrecise(value)?new SmallInteger(value):new BigInteger(square(smallToArray(Math.abs(this.value))),!1)},BigInteger.prototype.divmod=function(v){var result=divModAny(this,v);return{quotient:result[0],remainder:result[1]}},SmallInteger.prototype.divmod=BigInteger.prototype.divmod,BigInteger.prototype.divide=function(v){return divModAny(this,v)[0]},SmallInteger.prototype.over=SmallInteger.prototype.divide=BigInteger.prototype.over=BigInteger.prototype.divide,BigInteger.prototype.mod=function(v){return divModAny(this,v)[1]},SmallInteger.prototype.remainder=SmallInteger.prototype.mod=BigInteger.prototype.remainder=BigInteger.prototype.mod,BigInteger.prototype.pow=function(v){var value,x,y,n=parseValue(v),a=this.value,b=n.value;if(0===b)return CACHE[1];if(0===a)return CACHE[0];if(1===a)return CACHE[1];if(-1===a)return n.isEven()?CACHE[1]:CACHE[-1];if(n.sign)return CACHE[0];if(!n.isSmall)throw new Error("The exponent "+n.toString()+" is too large.");if(this.isSmall&&isPrecise(value=Math.pow(a,b)))return new SmallInteger(truncate(value));for(x=this,y=CACHE[1];;){if(b&!0&&(y=y.times(x),--b),0===b)break;b/=2,x=x.square()}return y},SmallInteger.prototype.pow=BigInteger.prototype.pow,BigInteger.prototype.modPow=function(exp,mod){if(exp=parseValue(exp),mod=parseValue(mod),mod.isZero())throw new Error("Cannot take modPow with modulus 0");var r=CACHE[1],base=this.mod(mod);if(base.isZero())return CACHE[0];for(;exp.isPositive();)exp.isOdd()&&(r=r.multiply(base).mod(mod)),exp=exp.divide(2),base=base.square().mod(mod);return r},SmallInteger.prototype.modPow=BigInteger.prototype.modPow,BigInteger.prototype.compareAbs=function(v){var n=parseValue(v),a=this.value,b=n.value;return n.isSmall?1:compareAbs(a,b)},SmallInteger.prototype.compareAbs=function(v){var n=parseValue(v),a=Math.abs(this.value),b=n.value;return n.isSmall?(b=Math.abs(b),a===b?0:a>b?1:-1):-1},BigInteger.prototype.compare=function(v){var n=parseValue(v),a=this.value,b=n.value;return this.sign!==n.sign?n.sign?1:-1:n.isSmall?this.sign?-1:1:compareAbs(a,b)*(this.sign?-1:1)},BigInteger.prototype.compareTo=BigInteger.prototype.compare,SmallInteger.prototype.compare=function(v){var n=parseValue(v),a=this.value,b=n.value;return n.isSmall?a==b?0:a>b?1:-1:0>a!==n.sign?0>a?-1:1:0>a?1:-1},SmallInteger.prototype.compareTo=SmallInteger.prototype.compare,BigInteger.prototype.equals=function(v){return 0===this.compare(v)},SmallInteger.prototype.eq=SmallInteger.prototype.equals=BigInteger.prototype.eq=BigInteger.prototype.equals,BigInteger.prototype.notEquals=function(v){return 0!==this.compare(v)},SmallInteger.prototype.neq=SmallInteger.prototype.notEquals=BigInteger.prototype.neq=BigInteger.prototype.notEquals,BigInteger.prototype.greater=function(v){return this.compare(v)>0},SmallInteger.prototype.gt=SmallInteger.prototype.greater=BigInteger.prototype.gt=BigInteger.prototype.greater,BigInteger.prototype.lesser=function(v){return this.compare(v)<0},SmallInteger.prototype.lt=SmallInteger.prototype.lesser=BigInteger.prototype.lt=BigInteger.prototype.lesser,BigInteger.prototype.greaterOrEquals=function(v){return this.compare(v)>=0},SmallInteger.prototype.geq=SmallInteger.prototype.greaterOrEquals=BigInteger.prototype.geq=BigInteger.prototype.greaterOrEquals,BigInteger.prototype.lesserOrEquals=function(v){return this.compare(v)<=0},SmallInteger.prototype.leq=SmallInteger.prototype.lesserOrEquals=BigInteger.prototype.leq=BigInteger.prototype.lesserOrEquals,BigInteger.prototype.isEven=function(){return 0===(1&this.value[0])},SmallInteger.prototype.isEven=function(){return 0===(1&this.value)},BigInteger.prototype.isOdd=function(){return 1===(1&this.value[0])},SmallInteger.prototype.isOdd=function(){return 1===(1&this.value)},BigInteger.prototype.isPositive=function(){return!this.sign},SmallInteger.prototype.isPositive=function(){return this.value>0},BigInteger.prototype.isNegative=function(){return this.sign},SmallInteger.prototype.isNegative=function(){return this.value<0},BigInteger.prototype.isUnit=function(){return!1},SmallInteger.prototype.isUnit=function(){return 1===Math.abs(this.value)},BigInteger.prototype.isZero=function(){return!1},SmallInteger.prototype.isZero=function(){return 0===this.value},BigInteger.prototype.isDivisibleBy=function(v){var n=parseValue(v),value=n.value;return 0===value?!1:1===value?!0:2===value?this.isEven():this.mod(n).equals(CACHE[0])},SmallInteger.prototype.isDivisibleBy=BigInteger.prototype.isDivisibleBy,BigInteger.prototype.isPrime=function(){var isPrime=isBasicPrime(this);if(isPrime!==undefined)return isPrime;for(var d,t,i,x,n=this.abs(),nPrev=n.prev(),a=[2,3,5,7,11,13,17,19],b=nPrev;b.isEven();)b=b.divide(2);for(i=0;ii;i++){var a=bigInt.randBetween(2,n.minus(2));if(!a.modPow(n.prev(),n).isUnit())return!1}return!0},SmallInteger.prototype.isProbablePrime=BigInteger.prototype.isProbablePrime,BigInteger.prototype.next=function(){var value=this.value;return this.sign?subtractSmall(value,1,this.sign):new BigInteger(addSmall(value,1),this.sign)},SmallInteger.prototype.next=function(){var value=this.value;return MAX_INT>value+1?new SmallInteger(value+1):new BigInteger(MAX_INT_ARR,!1)},BigInteger.prototype.prev=function(){var value=this.value;return this.sign?new BigInteger(addSmall(value,1),!0):subtractSmall(value,1,this.sign)},SmallInteger.prototype.prev=function(){var value=this.value;return value-1>-MAX_INT?new SmallInteger(value-1):new BigInteger(MAX_INT_ARR,!0)};for(var powersOfTwo=[1];powersOfTwo[powersOfTwo.length-1]<=BASE;)powersOfTwo.push(2*powersOfTwo[powersOfTwo.length-1]);var powers2Length=powersOfTwo.length,highestPower2=powersOfTwo[powers2Length-1];BigInteger.prototype.shiftLeft=function(n){if(!shift_isSmall(n))return n.isNegative()?this.shiftRight(n.abs()):this.times(CACHE[2].pow(n));if(n=+n,0>n)return this.shiftRight(-n);for(var result=this;n>=powers2Length;)result=result.multiply(highestPower2),n-=powers2Length-1;return result.multiply(powersOfTwo[n])},SmallInteger.prototype.shiftLeft=BigInteger.prototype.shiftLeft,BigInteger.prototype.shiftRight=function(n){var remQuo;if(!shift_isSmall(n))return n.isNegative()?this.shiftLeft(n.abs()):(remQuo=this.divmod(CACHE[2].pow(n)),remQuo.remainder.isNegative()?remQuo.quotient.prev():remQuo.quotient);if(n=+n,0>n)return this.shiftLeft(-n);for(var result=this;n>=powers2Length;){if(result.isZero())return result;remQuo=divModAny(result,highestPower2),result=remQuo[1].isNegative()?remQuo[0].prev():remQuo[0],n-=powers2Length-1}return remQuo=divModAny(result,powersOfTwo[n]),remQuo[1].isNegative()?remQuo[0].prev():remQuo[0]},SmallInteger.prototype.shiftRight=BigInteger.prototype.shiftRight,BigInteger.prototype.not=function(){return this.negate().prev()},SmallInteger.prototype.not=BigInteger.prototype.not,BigInteger.prototype.and=function(n){return bitwise(this,n,function(a,b){return a&b})},SmallInteger.prototype.and=BigInteger.prototype.and,BigInteger.prototype.or=function(n){return bitwise(this,n,function(a,b){return a|b})},SmallInteger.prototype.or=BigInteger.prototype.or,BigInteger.prototype.xor=function(n){return bitwise(this,n,function(a,b){return a^b})},SmallInteger.prototype.xor=BigInteger.prototype.xor;var LOBMASK_I=1<<30,LOBMASK_BI=(BASE&-BASE)*(BASE&-BASE)|LOBMASK_I,parseBase=function(text,base){var val=CACHE[0],pow=CACHE[1],length=text.length;if(base>=2&&36>=base&&length<=LOG_MAX_INT/Math.log(base))return new SmallInteger(parseInt(text,base));base=parseValue(base);var i,digits=[],isNegative="-"===text[0];for(i=isNegative?1:0;i=48&&57>=charCode)digits.push(parseValue(c));else if(charCode>=97&&122>=charCode)digits.push(parseValue(c.charCodeAt(0)-87));else{if("<"!==c)throw new Error(c+" is not a valid character");var start=i;do i++;while(">"!==text[i]);digits.push(parseValue(text.slice(start+1,i)))}}for(digits.reverse(),i=0;i=0;)digit=String(v[l]),str+=zeros.slice(digit.length)+digit;var sign=this.sign?"-":"";return sign+str},SmallInteger.prototype.toString=function(radix){return radix===undefined&&(radix=10),10!=radix?toBase(this,radix):String(this.value)},BigInteger.prototype.valueOf=function(){return+this.toString()},BigInteger.prototype.toJSNumber=BigInteger.prototype.valueOf,SmallInteger.prototype.valueOf=function(){return this.value},SmallInteger.prototype.toJSNumber=SmallInteger.prototype.valueOf;for(var CACHE=function(v,radix){return"undefined"==typeof v?CACHE[0]:"undefined"!=typeof radix?10===+radix?parseValue(v):parseBase(v,radix):parseValue(v)},i=0;1e3>i;i++)CACHE[i]=new SmallInteger(i),i>0&&(CACHE[-i]=new SmallInteger(-i));return CACHE.one=CACHE[1],CACHE.zero=CACHE[0],CACHE.minusOne=CACHE[-1],CACHE.max=max,CACHE.min=min,CACHE.gcd=gcd,CACHE.lcm=lcm,CACHE.isInstance=function(x){return x instanceof BigInteger||x instanceof SmallInteger},CACHE.randBetween=randBetween,CACHE}();"undefined"!=typeof module&&module.hasOwnProperty("exports")&&(module.exports=bigInt)},{}],2:[function(require,module,exports){function getRandomValues(buf){if(window.crypto&&window.crypto.getRandomValues)window.crypto.getRandomValues(buf);else if("object"==typeof window.msCrypto&&"function"==typeof window.msCrypto.getRandomValues)window.msCrypto.getRandomValues(buf);else{if(!nodeCrypto.randomBytes)throw new Error("No secure random number generator available.");if(buf.length>65536){var e=new Error;throw e.code=22,e.message="Failed to execute 'getRandomValues' on 'Crypto': The ArrayBufferView's byte length ("+buf.length+") exceeds the number of bytes of entropy available via this API (65536).",e.name="QuotaExceededError",e}var bytes=nodeCrypto.randomBytes(buf.length);buf.set(bytes)}}var window=require("global/window"),nodeCrypto=require("crypto");module.exports=getRandomValues},{crypto:9,"global/window":3}],3:[function(require,module,exports){(function(global){"undefined"!=typeof window?module.exports=window:"undefined"!=typeof global?module.exports=global:"undefined"!=typeof self?module.exports=self:module.exports={}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],4:[function(require,module,exports){arguments[4][3][0].apply(exports,arguments)},{dup:3}],5:[function(require,module,exports){String.fromCodePoint||!function(){var defineProperty=function(){try{var object={},$defineProperty=Object.defineProperty,result=$defineProperty(object,object,object)&&$defineProperty}catch(error){}return result}(),stringFromCharCode=String.fromCharCode,floor=Math.floor,fromCodePoint=function(_){var highSurrogate,lowSurrogate,MAX_SIZE=16384,codeUnits=[],index=-1,length=arguments.length;if(!length)return"";for(var result="";++indexcodePoint||codePoint>1114111||floor(codePoint)!=codePoint)throw RangeError("Invalid code point: "+codePoint);65535>=codePoint?codeUnits.push(codePoint):(codePoint-=65536,highSurrogate=(codePoint>>10)+55296,lowSurrogate=codePoint%1024+56320,codeUnits.push(highSurrogate,lowSurrogate)),(index+1==length||codeUnits.length>MAX_SIZE)&&(result+=stringFromCharCode.apply(null,codeUnits),codeUnits.length=0)}return result};defineProperty?defineProperty(String,"fromCodePoint",{value:fromCodePoint,configurable:!0,writable:!0}):String.fromCodePoint=fromCodePoint}()},{}],6:[function(require,module,exports){String.prototype.codePointAt||!function(){"use strict";var defineProperty=function(){try{var object={},$defineProperty=Object.defineProperty,result=$defineProperty(object,object,object)&&$defineProperty}catch(error){}return result}(),codePointAt=function(position){if(null==this)throw TypeError();var string=String(this),size=string.length,index=position?Number(position):0;if(index!=index&&(index=0),!(0>index||index>=size)){var second,first=string.charCodeAt(index);return first>=55296&&56319>=first&&size>index+1&&(second=string.charCodeAt(index+1),second>=56320&&57343>=second)?1024*(first-55296)+second-56320+65536:first}};defineProperty?defineProperty(String.prototype,"codePointAt",{value:codePointAt,configurable:!0,writable:!0}):String.prototype.codePointAt=codePointAt}()},{}],7:[function(require,module,exports){module.require&&(require("string.fromcodepoint"),require("string.prototype.codepointat"));var UTF8={isNotUTF8:function(bytes,byteOffset,byteLength){try{UTF8.getStringFromBytes(bytes,byteOffset,byteLength,!0)}catch(e){return!0}return!1},getCharLength:function(theByte){return 240==(240&theByte)?4:224==(224&theByte)?3:192==(192&theByte)?2:theByte==(127&theByte)?1:0},getCharCode:function(bytes,byteOffset,charLength){var charCode=0,mask="";if(byteOffset=byteOffset||0,charLength=charLength||UTF8.getCharLength(bytes[byteOffset]),0==charLength)throw new Error(bytes[byteOffset].toString(2)+" is not a significative byte (offset:"+byteOffset+").");if(1===charLength)return bytes[byteOffset];if(mask="00000000".slice(0,charLength)+1+"00000000".slice(charLength+1),bytes[byteOffset]&parseInt(mask,2))throw Error("Index "+byteOffset+": A "+charLength+" bytes encoded char cannot encode the "+(charLength+1)+"th rank bit to 1.");for(mask="0000".slice(0,charLength+1)+"11111111".slice(charLength+1),charCode+=(bytes[byteOffset]&parseInt(mask,2))<<6*--charLength;charLength;){if(128!==(128&bytes[byteOffset+1])||64===(64&bytes[byteOffset+1]))throw Error("Index "+(byteOffset+1)+': Next bytes of encoded char must begin with a "10" bit sequence.');charCode+=(63&bytes[++byteOffset])<<6*--charLength}return charCode},getStringFromBytes:function(bytes,byteOffset,byteLength,strict){var charLength,chars=[];for(byteOffset=0|byteOffset,byteLength="number"==typeof byteLength?byteLength:bytes.byteLength||bytes.length;byteLength>byteOffset;byteOffset++){if(charLength=UTF8.getCharLength(bytes[byteOffset]),byteOffset+charLength>byteLength){if(strict)throw Error("Index "+byteOffset+": Found a "+charLength+" bytes encoded char declaration but only "+(byteLength-byteOffset)+" bytes are available.")}else chars.push(String.fromCodePoint(UTF8.getCharCode(bytes,byteOffset,charLength,strict)));byteOffset+=charLength-1}return chars.join("")},getBytesForCharCode:function(charCode){if(128>charCode)return 1;if(2048>charCode)return 2;if(65536>charCode)return 3;if(2097152>charCode)return 4;throw new Error("CharCode "+charCode+" cannot be encoded with UTF8.")},setBytesFromCharCode:function(charCode,bytes,byteOffset,neededBytes){if(charCode=0|charCode,bytes=bytes||[],byteOffset=0|byteOffset,neededBytes=neededBytes||UTF8.getBytesForCharCode(charCode),1==neededBytes)bytes[byteOffset]=charCode;else for(bytes[byteOffset++]=(parseInt("1111".slice(0,neededBytes),2)<<8-neededBytes)+(charCode>>>6*--neededBytes);neededBytes>0;)bytes[byteOffset++]=charCode>>>6*--neededBytes&63|128;return bytes},setBytesFromString:function(string,bytes,byteOffset,byteLength,strict){string=string||"",bytes=bytes||[],byteOffset=0|byteOffset,byteLength="number"==typeof byteLength?byteLength:bytes.byteLength||1/0;for(var i=0,j=string.length;j>i;i++){var neededBytes=UTF8.getBytesForCharCode(string[i].codePointAt(0));if(strict&&byteOffset+neededBytes>byteLength)throw new Error('Not enought bytes to encode the char "'+string[i]+'" at the offset "'+byteOffset+'".');UTF8.setBytesFromCharCode(string[i].codePointAt(0),bytes,byteOffset,neededBytes,strict),byteOffset+=neededBytes}return bytes}};"undefined"!=typeof module&&(module.exports=UTF8)},{"string.fromcodepoint":5,"string.prototype.codepointat":6}],8:[function(require,module,exports){(function(global){if("function"==typeof require){var bigInt=require("big-integer"),getRandomValues=require("get-random-values"),UTF8=require("utf-8"),window=require("global/window");window.atob||window.btoa||!function(window){function _getbyte64(s,i){var idx=_ALPHA.indexOf(s.charAt(i));if(-1===idx)throw"Cannot decode base64";return idx}function _decode(s){var i,b10,pads=0,imax=s.length,x=[];if(s=String(s),0===imax)return s;if(imax%4!==0)throw"Cannot decode base64";for(s.charAt(imax-1)===_PADCHAR&&(pads=1,s.charAt(imax-2)===_PADCHAR&&(pads=2),imax-=4),i=0;imax>i;i+=4)b10=_getbyte64(s,i)<<18|_getbyte64(s,i+1)<<12|_getbyte64(s,i+2)<<6|_getbyte64(s,i+3),x.push(String.fromCharCode(b10>>16,b10>>8&255,255&b10));switch(pads){case 1:b10=_getbyte64(s,i)<<18|_getbyte64(s,i+1)<<12|_getbyte64(s,i+2)<<6,x.push(String.fromCharCode(b10>>16,b10>>8&255));break;case 2:b10=_getbyte64(s,i)<<18|_getbyte64(s,i+1)<<12,x.push(String.fromCharCode(b10>>16))}return x.join("")}function _getbyte(s,i){var x=s.charCodeAt(i); 2 | if(x>255)throw"INVALID_CHARACTER_ERR: DOM Exception 5";return x}function _encode(s){if(1!==arguments.length)throw"SyntaxError: exactly one argument required";s=String(s);var i,b10,x=[],imax=s.length-s.length%3;if(0===s.length)return s;for(i=0;imax>i;i+=3)b10=_getbyte(s,i)<<16|_getbyte(s,i+1)<<8|_getbyte(s,i+2),x.push(_ALPHA.charAt(b10>>18)),x.push(_ALPHA.charAt(b10>>12&63)),x.push(_ALPHA.charAt(b10>>6&63)),x.push(_ALPHA.charAt(63&b10));switch(s.length-imax){case 1:b10=_getbyte(s,i)<<16,x.push(_ALPHA.charAt(b10>>18)+_ALPHA.charAt(b10>>12&63)+_PADCHAR+_PADCHAR);break;case 2:b10=_getbyte(s,i)<<16|_getbyte(s,i+1)<<8,x.push(_ALPHA.charAt(b10>>18)+_ALPHA.charAt(b10>>12&63)+_ALPHA.charAt(b10>>6&63)+_PADCHAR)}return x.join("")}var _PADCHAR="=",_ALPHA="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";window.btoa=_encode,window.atob=_decode}(window)}var _sssa_utils=function(root){function random(){var bytes=new Uint8Array(32),string="",i=0;getRandomValues(bytes);for(i in bytes)string+=Array(2-bytes[i].toString(16).length+1).join(0)+bytes[i].toString(16);return bigInt(string,16)}function split_ints(secrets){var result=[],working=[],i=0,hex_data="";working=UTF8.setBytesFromString(secrets);for(i in working)hex_data+=Array(2-working[i].toString(16).length+1).join(0)+working[i].toString(16);for(i=0;ishares)){var secret=utils.split_ints(raw),numbers=[bigInt(0)],polynomial=[],result=[],i=0,j=1;for(i in secret)for(polynomial.push([secret[i]]),j=1;minimum>j;j++){for(value=utils.random();value in numbers;)value=utils.random();numbers.push(value),polynomial[i].push(value)}for(i=0;shares>i;i++)for(j in secret){for(value=utils.random();value in numbers;)value=utils.random();numbers.push(value),"string"!=typeof result[i]&&(result[i]=""),result[i]+=utils.to_base64(value),result[i]+=utils.to_base64(utils.evaluate_polynomial(polynomial[j],value))}return result}}function combine(shares){var secrets=[],share="",count=0,cshare="",secret=[],origin=bigInt(0),originy=bigInt(0),numerator=bigInt(1),denominator=bigInt(1),i=0,j=0,k=0;for(i in shares){if(shares[i].length%88!=0)return;for(share=shares[i],count=share.length/88,secrets[i]=[],j=0;count>j;j++)cshare=share.substring(88*j,88*(j+1)),secrets[i][j]=[utils.from_base64(cshare.substring(0,44)),utils.from_base64(cshare.substring(44))]}for(j=0;j> 16, ( b10 >> 8 ) & 0xff, b10 & 0xff ) ); 63 | } 64 | 65 | switch ( pads ) { 66 | case 1: 67 | b10 = ( _getbyte64( s, i ) << 18 ) | ( _getbyte64( s, i + 1 ) << 12 ) | ( _getbyte64( s, i + 2 ) << 6 ); 68 | x.push( String.fromCharCode( b10 >> 16, ( b10 >> 8 ) & 0xff ) ); 69 | break; 70 | 71 | case 2: 72 | b10 = ( _getbyte64( s, i ) << 18) | ( _getbyte64( s, i + 1 ) << 12 ); 73 | x.push( String.fromCharCode( b10 >> 16 ) ); 74 | break; 75 | } 76 | 77 | return x.join( "" ); 78 | } 79 | 80 | function _getbyte( s, i ) { 81 | var x = s.charCodeAt( i ); 82 | 83 | if ( x > 255 ) { 84 | throw "INVALID_CHARACTER_ERR: DOM Exception 5"; 85 | } 86 | 87 | return x; 88 | } 89 | 90 | function _encode( s ) { 91 | if ( arguments.length !== 1 ) { 92 | throw "SyntaxError: exactly one argument required"; 93 | } 94 | 95 | s = String( s ); 96 | 97 | var i, 98 | b10, 99 | x = [], 100 | imax = s.length - s.length % 3; 101 | 102 | if ( s.length === 0 ) { 103 | return s; 104 | } 105 | 106 | for ( i = 0; i < imax; i += 3 ) { 107 | b10 = ( _getbyte( s, i ) << 16 ) | ( _getbyte( s, i + 1 ) << 8 ) | _getbyte( s, i + 2 ); 108 | x.push( _ALPHA.charAt( b10 >> 18 ) ); 109 | x.push( _ALPHA.charAt( ( b10 >> 12 ) & 0x3F ) ); 110 | x.push( _ALPHA.charAt( ( b10 >> 6 ) & 0x3f ) ); 111 | x.push( _ALPHA.charAt( b10 & 0x3f ) ); 112 | } 113 | 114 | switch ( s.length - imax ) { 115 | case 1: 116 | b10 = _getbyte( s, i ) << 16; 117 | x.push( _ALPHA.charAt( b10 >> 18 ) + _ALPHA.charAt( ( b10 >> 12 ) & 0x3F ) + _PADCHAR + _PADCHAR ); 118 | break; 119 | 120 | case 2: 121 | b10 = ( _getbyte( s, i ) << 16 ) | ( _getbyte( s, i + 1 ) << 8 ); 122 | x.push( _ALPHA.charAt( b10 >> 18 ) + _ALPHA.charAt( ( b10 >> 12 ) & 0x3F ) + _ALPHA.charAt( ( b10 >> 6 ) & 0x3f ) + _PADCHAR ); 123 | break; 124 | } 125 | 126 | return x.join( "" ); 127 | } 128 | 129 | window.btoa = _encode; 130 | window.atob = _decode; 131 | 132 | })( window ); 133 | } 134 | } 135 | 136 | var _sssa_utils = (function (root) { 137 | var prime = bigInt("115792089237316195423570985008687907853269984665640564039457584007913129639747"); 138 | 139 | function random() { 140 | var bytes = new Uint8Array(32), 141 | string = "", 142 | i = 0; 143 | 144 | getRandomValues(bytes) 145 | for (i in bytes) { 146 | string += Array((2 - bytes[i].toString(16).length) + 1).join(0) + bytes[i].toString(16); 147 | } 148 | 149 | return bigInt(string, 16); 150 | } 151 | 152 | function split_ints(secrets) { 153 | var result = [], 154 | working = [], 155 | i = 0, 156 | hex_data = ""; 157 | 158 | working = UTF8.setBytesFromString(secrets); 159 | 160 | for (i in working) { 161 | hex_data += Array((2 - working[i].toString(16).length) + 1).join(0) + working[i].toString(16); 162 | } 163 | 164 | for (i = 0; i < hex_data.length/64; i++) { 165 | if ((i+1)*64 < hex_data.length) { 166 | result[i] = bigInt(hex_data.substring(i*64, (i+1)*64), 16); 167 | } else { 168 | result[i] = bigInt(hex_data.substring(i*64) + Array(((i+1)*64 - hex_data.length)+1).join(0), 16); 169 | } 170 | } 171 | 172 | return result; 173 | } 174 | 175 | function merge_ints(secrets) { 176 | var hex_data = "", 177 | bytes = [], 178 | temp = "", 179 | i = 0; 180 | 181 | for (i in secrets) { 182 | temp = secrets[i].toString(16); 183 | temp = Array(64 - temp.length + 1).join(0) + temp; 184 | hex_data += temp; 185 | } 186 | 187 | hex_data = hex_data.replace(/(00){1,}$/, ''); 188 | 189 | for (i = 0; i < hex_data.length/2; i++) { 190 | bytes.push(parseInt(hex_data.substring(i*2, (i+1)*2), 16)); 191 | } 192 | 193 | return UTF8.getStringFromBytes(bytes); 194 | } 195 | 196 | function evaluate_polynomial(coefficients, value) { 197 | var result = bigInt(coefficients[coefficients.length-1]), 198 | i = coefficients.length-2; 199 | 200 | for (i = coefficients.length-2; i >= 0; i--) { 201 | result = result.multiply(value).add(coefficients[i]).mod(prime).add(prime).mod(prime); 202 | } 203 | 204 | return result; 205 | } 206 | 207 | function to_base64(number) { 208 | var hex_data = number.toString(16), 209 | result = "", 210 | i = 0; 211 | 212 | hex_data = Array(64 - hex_data.length + 1).join('0') + hex_data; 213 | 214 | for (i = 0; i < hex_data.length/2; i++) { 215 | result += String.fromCharCode(parseInt(hex_data.substring(i*2, (i+1)*2), 16)); 216 | } 217 | 218 | return btoa(result).replace(/\//g, '_').replace(/\+/g, '-'); 219 | } 220 | 221 | function from_base64(number) { 222 | var bytes = atob(number.replace(/_/g, '/').replace(/-/g, '+')), 223 | hex_data = "", 224 | temp = "", 225 | i = 0; 226 | 227 | for (i = 0; i < bytes.length; i++) { 228 | temp = bytes.charCodeAt(i).toString(16); 229 | temp = Array(2 - (temp.length % 3) + 1).join(0) + temp; 230 | hex_data += temp; 231 | } 232 | 233 | hex_data = hex_data.replace(/^(00){1,}/, ''); 234 | 235 | return bigInt(hex_data, 16); 236 | } 237 | 238 | function gcd(a, b) { 239 | var n = bigInt(0), 240 | c = bigInt(0), 241 | r = bigInt(0); 242 | 243 | if (b.compare(bigInt(0)) == 0) { 244 | return [a, bigInt(1), bigInt(0)]; 245 | } 246 | 247 | n = a.divmod(b).quotient; 248 | c = a.mod(b).add(b).mod(b); 249 | r = gcd(b, c); 250 | 251 | return [r[0], r[2], r[1].subtract(r[2].multiply(n))]; 252 | } 253 | 254 | function mod_inverse(number) { 255 | var value = gcd(prime, number.mod(prime)); 256 | var remainder = value[2]; 257 | 258 | if (number.compare(0) == -1) { 259 | remainder = remainder.multiply(-1); 260 | } 261 | 262 | return remainder.mod(prime).add(prime).mod(prime); 263 | } 264 | 265 | return { 266 | 'prime': prime, 267 | 'random': random, 268 | 'split_ints': split_ints, 269 | 'merge_ints': merge_ints, 270 | 'evaluate_polynomial': evaluate_polynomial, 271 | 'to_base64': to_base64, 272 | 'from_base64': from_base64, 273 | 'gcd': gcd, 274 | 'mod_inverse': mod_inverse, 275 | } 276 | }(this)); 277 | 278 | var _sssa = (function(root) { 279 | var utils = _sssa_utils; 280 | 281 | function create(minimum, shares, raw) { 282 | if (minimum > shares) { 283 | return; 284 | } 285 | 286 | var secret = utils.split_ints(raw), 287 | numbers = [bigInt(0)], 288 | polynomial = [], 289 | result = [], 290 | i = 0, 291 | j = 1; 292 | 293 | for (i in secret) { 294 | polynomial.push([secret[i]]); 295 | for (j = 1; j < minimum; j++) { 296 | value = utils.random(); 297 | while (value in numbers) { 298 | value = utils.random(); 299 | } 300 | numbers.push(value); 301 | 302 | polynomial[i].push(value); 303 | } 304 | } 305 | 306 | 307 | for (i = 0; i < shares; i++) { 308 | for (j in secret) { 309 | value = utils.random(); 310 | while (value in numbers) { 311 | value = utils.random(); 312 | } 313 | numbers.push(value); 314 | 315 | if (typeof result[i] !== typeof "string") { 316 | result[i] = ""; 317 | } 318 | 319 | result[i] += utils.to_base64(value); 320 | result[i] += utils.to_base64(utils.evaluate_polynomial(polynomial[j], value)); 321 | } 322 | } 323 | 324 | return result; 325 | } 326 | 327 | function combine(shares) { 328 | var secrets = [], 329 | share = "", 330 | count = 0, 331 | cshare = "", 332 | secret = [], 333 | origin = bigInt(0), 334 | originy = bigInt(0), 335 | numerator = bigInt(1), 336 | denominator = bigInt(1), 337 | i = 0, 338 | j = 0, 339 | k = 0; 340 | 341 | for (i in shares) { 342 | if (shares[i].length % 88 != 0) { 343 | return; 344 | } 345 | 346 | share = shares[i]; 347 | count = share.length / 88; 348 | secrets[i] = []; 349 | 350 | for (j = 0; j < count; j++) { 351 | cshare = share.substring(j*88, (j+1)*88); 352 | secrets[i][j] = [utils.from_base64(cshare.substring(0, 44)), utils.from_base64(cshare.substring(44))]; 353 | } 354 | } 355 | 356 | for (j = 0; j < secrets[0].length; j++) { 357 | secret[j] = bigInt(0); 358 | for (i in secrets) { 359 | origin = secrets[i][j][0]; 360 | originy = secrets[i][j][1]; 361 | numerator = bigInt(1); 362 | denominator = bigInt(1); 363 | 364 | for (k in secrets) { 365 | if (k !== i) { 366 | numerator = numerator.multiply(secrets[k][j][0].multiply(-1)).mod(utils.prime).add(utils.prime).mod(utils.prime); 367 | denominator = denominator.multiply(origin.subtract(secrets[k][j][0])).mod(utils.prime).add(utils.prime).mod(utils.prime); 368 | } 369 | } 370 | 371 | secret[j] = secret[j].add(originy.multiply(numerator).mod(utils.prime).add(utils.prime).mod(utils.prime).multiply(utils.mod_inverse(denominator)).mod(utils.prime).add(utils.prime).mod(utils.prime)).mod(utils.prime).add(utils.prime).mod(utils.prime); 372 | } 373 | } 374 | 375 | return utils.merge_ints(secret); 376 | } 377 | 378 | return sssa = { 379 | 'create': create, 380 | 'combine': combine 381 | }; 382 | }(this)); 383 | 384 | var sssa = _sssa; 385 | module.exports = sssa; 386 | 387 | if (typeof global.testing !== "undefined" && global.testing === true) { 388 | global._sssa_utils = _sssa_utils; 389 | global._sssa = _sssa; 390 | } 391 | 392 | _sssa = undefined; 393 | _sssa_utils = undefined; 394 | -------------------------------------------------------------------------------- /test/all.js: -------------------------------------------------------------------------------- 1 | (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 0) return Math.floor(n); 66 | return Math.ceil(n); 67 | } 68 | 69 | function add(a, b) { // assumes a and b are arrays with a.length >= b.length 70 | var l_a = a.length, 71 | l_b = b.length, 72 | r = new Array(l_a), 73 | carry = 0, 74 | base = BASE, 75 | sum, i; 76 | for (i = 0; i < l_b; i++) { 77 | sum = a[i] + b[i] + carry; 78 | carry = sum >= base ? 1 : 0; 79 | r[i] = sum - carry * base; 80 | } 81 | while (i < l_a) { 82 | sum = a[i] + carry; 83 | carry = sum === base ? 1 : 0; 84 | r[i++] = sum - carry * base; 85 | } 86 | if (carry > 0) r.push(carry); 87 | return r; 88 | } 89 | 90 | function addAny(a, b) { 91 | if (a.length >= b.length) return add(a, b); 92 | return add(b, a); 93 | } 94 | 95 | function addSmall(a, carry) { // assumes a is array, carry is number with 0 <= carry < MAX_INT 96 | var l = a.length, 97 | r = new Array(l), 98 | base = BASE, 99 | sum, i; 100 | for (i = 0; i < l; i++) { 101 | sum = a[i] - base + carry; 102 | carry = Math.floor(sum / base); 103 | r[i] = sum - carry * base; 104 | carry += 1; 105 | } 106 | while (carry > 0) { 107 | r[i++] = carry % base; 108 | carry = Math.floor(carry / base); 109 | } 110 | return r; 111 | } 112 | 113 | BigInteger.prototype.add = function (v) { 114 | var value, n = parseValue(v); 115 | if (this.sign !== n.sign) { 116 | return this.subtract(n.negate()); 117 | } 118 | var a = this.value, b = n.value; 119 | if (n.isSmall) { 120 | return new BigInteger(addSmall(a, Math.abs(b)), this.sign); 121 | } 122 | return new BigInteger(addAny(a, b), this.sign); 123 | }; 124 | BigInteger.prototype.plus = BigInteger.prototype.add; 125 | 126 | SmallInteger.prototype.add = function (v) { 127 | var n = parseValue(v); 128 | var a = this.value; 129 | if (a < 0 !== n.sign) { 130 | return this.subtract(n.negate()); 131 | } 132 | var b = n.value; 133 | if (n.isSmall) { 134 | if (isPrecise(a + b)) return new SmallInteger(a + b); 135 | b = smallToArray(Math.abs(b)); 136 | } 137 | return new BigInteger(addSmall(b, Math.abs(a)), a < 0); 138 | }; 139 | SmallInteger.prototype.plus = SmallInteger.prototype.add; 140 | 141 | function subtract(a, b) { // assumes a and b are arrays with a >= b 142 | var a_l = a.length, 143 | b_l = b.length, 144 | r = new Array(a_l), 145 | borrow = 0, 146 | base = BASE, 147 | i, difference; 148 | for (i = 0; i < b_l; i++) { 149 | difference = a[i] - borrow - b[i]; 150 | if (difference < 0) { 151 | difference += base; 152 | borrow = 1; 153 | } else borrow = 0; 154 | r[i] = difference; 155 | } 156 | for (i = b_l; i < a_l; i++) { 157 | difference = a[i] - borrow; 158 | if (difference < 0) difference += base; 159 | else { 160 | r[i++] = difference; 161 | break; 162 | } 163 | r[i] = difference; 164 | } 165 | for (; i < a_l; i++) { 166 | r[i] = a[i]; 167 | } 168 | trim(r); 169 | return r; 170 | } 171 | 172 | function subtractAny(a, b, sign) { 173 | var value, isSmall; 174 | if (compareAbs(a, b) >= 0) { 175 | value = subtract(a,b); 176 | } else { 177 | value = subtract(b, a); 178 | sign = !sign; 179 | } 180 | value = arrayToSmall(value); 181 | if (typeof value === "number") { 182 | if (sign) value = -value; 183 | return new SmallInteger(value); 184 | } 185 | return new BigInteger(value, sign); 186 | } 187 | 188 | function subtractSmall(a, b, sign) { // assumes a is array, b is number with 0 <= b < MAX_INT 189 | var l = a.length, 190 | r = new Array(l), 191 | carry = -b, 192 | base = BASE, 193 | i, difference; 194 | for (i = 0; i < l; i++) { 195 | difference = a[i] + carry; 196 | carry = Math.floor(difference / base); 197 | difference %= base; 198 | r[i] = difference < 0 ? difference + base : difference; 199 | } 200 | r = arrayToSmall(r); 201 | if (typeof r === "number") { 202 | if (sign) r = -r; 203 | return new SmallInteger(r); 204 | } return new BigInteger(r, sign); 205 | } 206 | 207 | BigInteger.prototype.subtract = function (v) { 208 | var n = parseValue(v); 209 | if (this.sign !== n.sign) { 210 | return this.add(n.negate()); 211 | } 212 | var a = this.value, b = n.value; 213 | if (n.isSmall) 214 | return subtractSmall(a, Math.abs(b), this.sign); 215 | return subtractAny(a, b, this.sign); 216 | }; 217 | BigInteger.prototype.minus = BigInteger.prototype.subtract; 218 | 219 | SmallInteger.prototype.subtract = function (v) { 220 | var n = parseValue(v); 221 | var a = this.value; 222 | if (a < 0 !== n.sign) { 223 | return this.add(n.negate()); 224 | } 225 | var b = n.value; 226 | if (n.isSmall) { 227 | return new SmallInteger(a - b); 228 | } 229 | return subtractSmall(b, Math.abs(a), a >= 0); 230 | }; 231 | SmallInteger.prototype.minus = SmallInteger.prototype.subtract; 232 | 233 | BigInteger.prototype.negate = function () { 234 | return new BigInteger(this.value, !this.sign); 235 | }; 236 | SmallInteger.prototype.negate = function () { 237 | var sign = this.sign; 238 | var small = new SmallInteger(-this.value); 239 | small.sign = !sign; 240 | return small; 241 | }; 242 | 243 | BigInteger.prototype.abs = function () { 244 | return new BigInteger(this.value, false); 245 | }; 246 | SmallInteger.prototype.abs = function () { 247 | return new SmallInteger(Math.abs(this.value)); 248 | }; 249 | 250 | function multiplyLong(a, b) { 251 | var a_l = a.length, 252 | b_l = b.length, 253 | l = a_l + b_l, 254 | r = createArray(l), 255 | base = BASE, 256 | product, carry, i, a_i, b_j; 257 | for (i = 0; i < a_l; ++i) { 258 | a_i = a[i]; 259 | for (var j = 0; j < b_l; ++j) { 260 | b_j = b[j]; 261 | product = a_i * b_j + r[i + j]; 262 | carry = Math.floor(product / base); 263 | r[i + j] = product - carry * base; 264 | r[i + j + 1] += carry; 265 | } 266 | } 267 | trim(r); 268 | return r; 269 | } 270 | 271 | function multiplySmall(a, b) { // assumes a is array, b is number with |b| < BASE 272 | var l = a.length, 273 | r = new Array(l), 274 | base = BASE, 275 | carry = 0, 276 | product, i; 277 | for (i = 0; i < l; i++) { 278 | product = a[i] * b + carry; 279 | carry = Math.floor(product / base); 280 | r[i] = product - carry * base; 281 | } 282 | while (carry > 0) { 283 | r[i++] = carry % base; 284 | carry = Math.floor(carry / base); 285 | } 286 | return r; 287 | } 288 | 289 | function shiftLeft(x, n) { 290 | var r = []; 291 | while (n-- > 0) r.push(0); 292 | return r.concat(x); 293 | } 294 | 295 | function multiplyKaratsuba(x, y) { 296 | var n = Math.max(x.length, y.length); 297 | 298 | if (n <= 400) return multiplyLong(x, y); 299 | n = Math.ceil(n / 2); 300 | 301 | var b = x.slice(n), 302 | a = x.slice(0, n), 303 | d = y.slice(n), 304 | c = y.slice(0, n); 305 | 306 | var ac = multiplyKaratsuba(a, c), 307 | bd = multiplyKaratsuba(b, d), 308 | abcd = multiplyKaratsuba(addAny(a, b), addAny(c, d)); 309 | 310 | return addAny(addAny(ac, shiftLeft(subtract(subtract(abcd, ac), bd), n)), shiftLeft(bd, 2 * n)); 311 | } 312 | 313 | BigInteger.prototype.multiply = function (v) { 314 | var value, n = parseValue(v), 315 | a = this.value, b = n.value, 316 | sign = this.sign !== n.sign, 317 | abs; 318 | if (n.isSmall) { 319 | if (b === 0) return CACHE[0]; 320 | if (b === 1) return this; 321 | if (b === -1) return this.negate(); 322 | abs = Math.abs(b); 323 | if (abs < BASE) { 324 | return new BigInteger(multiplySmall(a, abs), sign); 325 | } 326 | b = smallToArray(abs); 327 | } 328 | if (a.length + b.length > 4000) // Karatsuba is only faster for sufficiently large inputs 329 | return new BigInteger(multiplyKaratsuba(a, b), sign); 330 | return new BigInteger(multiplyLong(a, b), sign); 331 | }; 332 | 333 | BigInteger.prototype.times = BigInteger.prototype.multiply; 334 | 335 | function multiplySmallAndArray(a, b, sign) { // a >= 0 336 | if (a < BASE) { 337 | return new BigInteger(multiplySmall(b, a), sign); 338 | } 339 | return new BigInteger(multiplyLong(b, smallToArray(a)), sign); 340 | } 341 | SmallInteger.prototype["_multiplyBySmall"] = function (a) { 342 | if (isPrecise(a.value * this.value)) { 343 | return new SmallInteger(a.value * this.value); 344 | } 345 | return multiplySmallAndArray(Math.abs(a.value), smallToArray(Math.abs(this.value)), this.sign !== a.sign); 346 | }; 347 | BigInteger.prototype["_multiplyBySmall"] = function (a) { 348 | if (a.value === 0) return CACHE[0]; 349 | if (a.value === 1) return this; 350 | if (a.value === -1) return this.negate(); 351 | return multiplySmallAndArray(Math.abs(a.value), this.value, this.sign !== a.sign); 352 | }; 353 | SmallInteger.prototype.multiply = function (v) { 354 | return parseValue(v)["_multiplyBySmall"](this); 355 | }; 356 | SmallInteger.prototype.times = SmallInteger.prototype.multiply; 357 | 358 | function square(a) { 359 | var l = a.length, 360 | r = createArray(l + l), 361 | base = BASE, 362 | product, carry, i, a_i, a_j; 363 | for (i = 0; i < l; i++) { 364 | a_i = a[i]; 365 | for (var j = 0; j < l; j++) { 366 | a_j = a[j]; 367 | product = a_i * a_j + r[i + j]; 368 | carry = Math.floor(product / base); 369 | r[i + j] = product - carry * base; 370 | r[i + j + 1] += carry; 371 | } 372 | } 373 | trim(r); 374 | return r; 375 | } 376 | 377 | BigInteger.prototype.square = function () { 378 | return new BigInteger(square(this.value), false); 379 | }; 380 | 381 | SmallInteger.prototype.square = function () { 382 | var value = this.value * this.value; 383 | if (isPrecise(value)) return new SmallInteger(value); 384 | return new BigInteger(square(smallToArray(Math.abs(this.value))), false); 385 | }; 386 | 387 | function divMod1(a, b) { // Left over from previous version. Performs faster than divMod2 on smaller input sizes. 388 | var a_l = a.length, 389 | b_l = b.length, 390 | base = BASE, 391 | result = createArray(b.length), 392 | divisorMostSignificantDigit = b[b_l - 1], 393 | // normalization 394 | lambda = Math.ceil(base / (2 * divisorMostSignificantDigit)), 395 | remainder = multiplySmall(a, lambda), 396 | divisor = multiplySmall(b, lambda), 397 | quotientDigit, shift, carry, borrow, i, l, q; 398 | if (remainder.length <= a_l) remainder.push(0); 399 | divisor.push(0); 400 | divisorMostSignificantDigit = divisor[b_l - 1]; 401 | for (shift = a_l - b_l; shift >= 0; shift--) { 402 | quotientDigit = base - 1; 403 | if (remainder[shift + b_l] !== divisorMostSignificantDigit) { 404 | quotientDigit = Math.floor((remainder[shift + b_l] * base + remainder[shift + b_l - 1]) / divisorMostSignificantDigit); 405 | } 406 | // quotientDigit <= base - 1 407 | carry = 0; 408 | borrow = 0; 409 | l = divisor.length; 410 | for (i = 0; i < l; i++) { 411 | carry += quotientDigit * divisor[i]; 412 | q = Math.floor(carry / base); 413 | borrow += remainder[shift + i] - (carry - q * base); 414 | carry = q; 415 | if (borrow < 0) { 416 | remainder[shift + i] = borrow + base; 417 | borrow = -1; 418 | } else { 419 | remainder[shift + i] = borrow; 420 | borrow = 0; 421 | } 422 | } 423 | while (borrow !== 0) { 424 | quotientDigit -= 1; 425 | carry = 0; 426 | for (i = 0; i < l; i++) { 427 | carry += remainder[shift + i] - base + divisor[i]; 428 | if (carry < 0) { 429 | remainder[shift + i] = carry + base; 430 | carry = 0; 431 | } else { 432 | remainder[shift + i] = carry; 433 | carry = 1; 434 | } 435 | } 436 | borrow += carry; 437 | } 438 | result[shift] = quotientDigit; 439 | } 440 | // denormalization 441 | remainder = divModSmall(remainder, lambda)[0]; 442 | return [arrayToSmall(result), arrayToSmall(remainder)]; 443 | } 444 | 445 | function divMod2(a, b) { // Implementation idea shamelessly stolen from Silent Matt's library http://silentmatt.com/biginteger/ 446 | // Performs faster than divMod1 on larger input sizes. 447 | var a_l = a.length, 448 | b_l = b.length, 449 | result = [], 450 | part = [], 451 | base = BASE, 452 | guess, xlen, highx, highy, check; 453 | while (a_l) { 454 | part.unshift(a[--a_l]); 455 | if (compareAbs(part, b) < 0) { 456 | result.push(0); 457 | continue; 458 | } 459 | xlen = part.length; 460 | highx = part[xlen - 1] * base + part[xlen - 2]; 461 | highy = b[b_l - 1] * base + b[b_l - 2]; 462 | if (xlen > b_l) { 463 | highx = (highx + 1) * base; 464 | } 465 | guess = Math.ceil(highx / highy); 466 | do { 467 | check = multiplySmall(b, guess); 468 | if (compareAbs(check, part) <= 0) break; 469 | guess--; 470 | } while (guess); 471 | result.push(guess); 472 | part = subtract(part, check); 473 | } 474 | result.reverse(); 475 | return [arrayToSmall(result), arrayToSmall(part)]; 476 | } 477 | 478 | function divModSmall(value, lambda) { 479 | var length = value.length, 480 | quotient = createArray(length), 481 | base = BASE, 482 | i, q, remainder, divisor; 483 | remainder = 0; 484 | for (i = length - 1; i >= 0; --i) { 485 | divisor = remainder * base + value[i]; 486 | q = truncate(divisor / lambda); 487 | remainder = divisor - q * lambda; 488 | quotient[i] = q | 0; 489 | } 490 | return [quotient, remainder | 0]; 491 | } 492 | 493 | function divModAny(self, v) { 494 | var value, n = parseValue(v); 495 | var a = self.value, b = n.value; 496 | var quotient; 497 | if (b === 0) throw new Error("Cannot divide by zero"); 498 | if (self.isSmall) { 499 | if (n.isSmall) { 500 | return [new SmallInteger(truncate(a / b)), new SmallInteger(a % b)]; 501 | } 502 | return [CACHE[0], self]; 503 | } 504 | if (n.isSmall) { 505 | if (b === 1) return [self, CACHE[0]]; 506 | if (b == -1) return [self.negate(), CACHE[0]]; 507 | var abs = Math.abs(b); 508 | if (abs < BASE) { 509 | value = divModSmall(a, abs); 510 | quotient = arrayToSmall(value[0]); 511 | var remainder = value[1]; 512 | if (self.sign) remainder = -remainder; 513 | if (typeof quotient === "number") { 514 | if (self.sign !== n.sign) quotient = -quotient; 515 | return [new SmallInteger(quotient), new SmallInteger(remainder)]; 516 | } 517 | return [new BigInteger(quotient, self.sign !== n.sign), new SmallInteger(remainder)]; 518 | } 519 | b = smallToArray(abs); 520 | } 521 | var comparison = compareAbs(a, b); 522 | if (comparison === -1) return [CACHE[0], self]; 523 | if (comparison === 0) return [CACHE[self.sign === n.sign ? 1 : -1], CACHE[0]]; 524 | 525 | // divMod1 is faster on smaller input sizes 526 | if (a.length + b.length <= 200) 527 | value = divMod1(a, b); 528 | else value = divMod2(a, b); 529 | 530 | quotient = value[0]; 531 | var qSign = self.sign !== n.sign, 532 | mod = value[1], 533 | mSign = self.sign; 534 | if (typeof quotient === "number") { 535 | if (qSign) quotient = -quotient; 536 | quotient = new SmallInteger(quotient); 537 | } else quotient = new BigInteger(quotient, qSign); 538 | if (typeof mod === "number") { 539 | if (mSign) mod = -mod; 540 | mod = new SmallInteger(mod); 541 | } else mod = new BigInteger(mod, mSign); 542 | return [quotient, mod]; 543 | } 544 | 545 | BigInteger.prototype.divmod = function (v) { 546 | var result = divModAny(this, v); 547 | return { 548 | quotient: result[0], 549 | remainder: result[1] 550 | }; 551 | }; 552 | SmallInteger.prototype.divmod = BigInteger.prototype.divmod; 553 | 554 | BigInteger.prototype.divide = function (v) { 555 | return divModAny(this, v)[0]; 556 | }; 557 | SmallInteger.prototype.over = SmallInteger.prototype.divide = BigInteger.prototype.over = BigInteger.prototype.divide; 558 | 559 | BigInteger.prototype.mod = function (v) { 560 | return divModAny(this, v)[1]; 561 | }; 562 | SmallInteger.prototype.remainder = SmallInteger.prototype.mod = BigInteger.prototype.remainder = BigInteger.prototype.mod; 563 | 564 | BigInteger.prototype.pow = function (v) { 565 | var n = parseValue(v), 566 | a = this.value, 567 | b = n.value, 568 | value, x, y; 569 | if (b === 0) return CACHE[1]; 570 | if (a === 0) return CACHE[0]; 571 | if (a === 1) return CACHE[1]; 572 | if (a === -1) return n.isEven() ? CACHE[1] : CACHE[-1]; 573 | if (n.sign) { 574 | return CACHE[0]; 575 | } 576 | if (!n.isSmall) throw new Error("The exponent " + n.toString() + " is too large."); 577 | if (this.isSmall) { 578 | if (isPrecise(value = Math.pow(a, b))) 579 | return new SmallInteger(truncate(value)); 580 | } 581 | x = this; 582 | y = CACHE[1]; 583 | while (true) { 584 | if (b & 1 === 1) { 585 | y = y.times(x); 586 | --b; 587 | } 588 | if (b === 0) break; 589 | b /= 2; 590 | x = x.square(); 591 | } 592 | return y; 593 | }; 594 | SmallInteger.prototype.pow = BigInteger.prototype.pow; 595 | 596 | BigInteger.prototype.modPow = function (exp, mod) { 597 | exp = parseValue(exp); 598 | mod = parseValue(mod); 599 | if (mod.isZero()) throw new Error("Cannot take modPow with modulus 0"); 600 | var r = CACHE[1], 601 | base = this.mod(mod); 602 | if (base.isZero()) return CACHE[0]; 603 | while (exp.isPositive()) { 604 | if (exp.isOdd()) r = r.multiply(base).mod(mod); 605 | exp = exp.divide(2); 606 | base = base.square().mod(mod); 607 | } 608 | return r; 609 | }; 610 | SmallInteger.prototype.modPow = BigInteger.prototype.modPow; 611 | 612 | function compareAbs(a, b) { 613 | if (a.length !== b.length) { 614 | return a.length > b.length ? 1 : -1; 615 | } 616 | for (var i = a.length - 1; i >= 0; i--) { 617 | if (a[i] !== b[i]) return a[i] > b[i] ? 1 : -1; 618 | } 619 | return 0; 620 | } 621 | 622 | BigInteger.prototype.compareAbs = function (v) { 623 | var n = parseValue(v), 624 | a = this.value, 625 | b = n.value; 626 | if (n.isSmall) return 1; 627 | return compareAbs(a, b); 628 | }; 629 | SmallInteger.prototype.compareAbs = function (v) { 630 | var n = parseValue(v), 631 | a = Math.abs(this.value), 632 | b = n.value; 633 | if (n.isSmall) { 634 | b = Math.abs(b); 635 | return a === b ? 0 : a > b ? 1 : -1; 636 | } 637 | return -1; 638 | }; 639 | 640 | BigInteger.prototype.compare = function (v) { 641 | var n = parseValue(v), 642 | a = this.value, 643 | b = n.value; 644 | if (this.sign !== n.sign) { 645 | return n.sign ? 1 : -1; 646 | } 647 | if (n.isSmall) { 648 | return this.sign ? -1 : 1; 649 | } 650 | return compareAbs(a, b) * (this.sign ? -1 : 1); 651 | }; 652 | BigInteger.prototype.compareTo = BigInteger.prototype.compare; 653 | 654 | SmallInteger.prototype.compare = function (v) { 655 | var n = parseValue(v), 656 | a = this.value, 657 | b = n.value; 658 | if (n.isSmall) { 659 | return a == b ? 0 : a > b ? 1 : -1; 660 | } 661 | if (a < 0 !== n.sign) { 662 | return a < 0 ? -1 : 1; 663 | } 664 | return a < 0 ? 1 : -1; 665 | }; 666 | SmallInteger.prototype.compareTo = SmallInteger.prototype.compare; 667 | 668 | BigInteger.prototype.equals = function (v) { 669 | return this.compare(v) === 0; 670 | }; 671 | SmallInteger.prototype.eq = SmallInteger.prototype.equals = BigInteger.prototype.eq = BigInteger.prototype.equals; 672 | 673 | BigInteger.prototype.notEquals = function (v) { 674 | return this.compare(v) !== 0; 675 | }; 676 | SmallInteger.prototype.neq = SmallInteger.prototype.notEquals = BigInteger.prototype.neq = BigInteger.prototype.notEquals; 677 | 678 | BigInteger.prototype.greater = function (v) { 679 | return this.compare(v) > 0; 680 | }; 681 | SmallInteger.prototype.gt = SmallInteger.prototype.greater = BigInteger.prototype.gt = BigInteger.prototype.greater; 682 | 683 | BigInteger.prototype.lesser = function (v) { 684 | return this.compare(v) < 0; 685 | }; 686 | SmallInteger.prototype.lt = SmallInteger.prototype.lesser = BigInteger.prototype.lt = BigInteger.prototype.lesser; 687 | 688 | BigInteger.prototype.greaterOrEquals = function (v) { 689 | return this.compare(v) >= 0; 690 | }; 691 | SmallInteger.prototype.geq = SmallInteger.prototype.greaterOrEquals = BigInteger.prototype.geq = BigInteger.prototype.greaterOrEquals; 692 | 693 | BigInteger.prototype.lesserOrEquals = function (v) { 694 | return this.compare(v) <= 0; 695 | }; 696 | SmallInteger.prototype.leq = SmallInteger.prototype.lesserOrEquals = BigInteger.prototype.leq = BigInteger.prototype.lesserOrEquals; 697 | 698 | BigInteger.prototype.isEven = function () { 699 | return (this.value[0] & 1) === 0; 700 | }; 701 | SmallInteger.prototype.isEven = function () { 702 | return (this.value & 1) === 0; 703 | }; 704 | 705 | BigInteger.prototype.isOdd = function () { 706 | return (this.value[0] & 1) === 1; 707 | }; 708 | SmallInteger.prototype.isOdd = function () { 709 | return (this.value & 1) === 1; 710 | }; 711 | 712 | BigInteger.prototype.isPositive = function () { 713 | return !this.sign; 714 | }; 715 | SmallInteger.prototype.isPositive = function () { 716 | return this.value > 0; 717 | }; 718 | 719 | BigInteger.prototype.isNegative = function () { 720 | return this.sign; 721 | }; 722 | SmallInteger.prototype.isNegative = function () { 723 | return this.value < 0; 724 | }; 725 | 726 | BigInteger.prototype.isUnit = function () { 727 | return false; 728 | }; 729 | SmallInteger.prototype.isUnit = function () { 730 | return Math.abs(this.value) === 1; 731 | }; 732 | 733 | BigInteger.prototype.isZero = function () { 734 | return false; 735 | }; 736 | SmallInteger.prototype.isZero = function () { 737 | return this.value === 0; 738 | }; 739 | BigInteger.prototype.isDivisibleBy = function (v) { 740 | var n = parseValue(v); 741 | var value = n.value; 742 | if (value === 0) return false; 743 | if (value === 1) return true; 744 | if (value === 2) return this.isEven(); 745 | return this.mod(n).equals(CACHE[0]); 746 | }; 747 | SmallInteger.prototype.isDivisibleBy = BigInteger.prototype.isDivisibleBy; 748 | 749 | function isBasicPrime(v) { 750 | var n = v.abs(); 751 | if (n.isUnit()) return false; 752 | if (n.equals(2) || n.equals(3) || n.equals(5)) return true; 753 | if (n.isEven() || n.isDivisibleBy(3) || n.isDivisibleBy(5)) return false; 754 | if (n.lesser(25)) return true; 755 | // we don't know if it's prime: let the other functions figure it out 756 | }; 757 | 758 | BigInteger.prototype.isPrime = function () { 759 | var isPrime = isBasicPrime(this); 760 | if (isPrime !== undefined) return isPrime; 761 | var n = this.abs(), 762 | nPrev = n.prev(); 763 | var a = [2, 3, 5, 7, 11, 13, 17, 19], 764 | b = nPrev, 765 | d, t, i, x; 766 | while (b.isEven()) b = b.divide(2); 767 | for (i = 0; i < a.length; i++) { 768 | x = bigInt(a[i]).modPow(b, n); 769 | if (x.equals(CACHE[1]) || x.equals(nPrev)) continue; 770 | for (t = true, d = b; t && d.lesser(nPrev) ; d = d.multiply(2)) { 771 | x = x.square().mod(n); 772 | if (x.equals(nPrev)) t = false; 773 | } 774 | if (t) return false; 775 | } 776 | return true; 777 | }; 778 | SmallInteger.prototype.isPrime = BigInteger.prototype.isPrime; 779 | 780 | BigInteger.prototype.isProbablePrime = function (iterations) { 781 | var isPrime = isBasicPrime(this); 782 | if (isPrime !== undefined) return isPrime; 783 | var n = this.abs(); 784 | var t = iterations === undefined ? 5 : iterations; 785 | // use the Fermat primality test 786 | for (var i = 0; i < t; i++) { 787 | var a = bigInt.randBetween(2, n.minus(2)); 788 | if (!a.modPow(n.prev(), n).isUnit()) return false; // definitely composite 789 | } 790 | return true; // large chance of being prime 791 | }; 792 | SmallInteger.prototype.isProbablePrime = BigInteger.prototype.isProbablePrime; 793 | 794 | BigInteger.prototype.next = function () { 795 | var value = this.value; 796 | if (this.sign) { 797 | return subtractSmall(value, 1, this.sign); 798 | } 799 | return new BigInteger(addSmall(value, 1), this.sign); 800 | }; 801 | SmallInteger.prototype.next = function () { 802 | var value = this.value; 803 | if (value + 1 < MAX_INT) return new SmallInteger(value + 1); 804 | return new BigInteger(MAX_INT_ARR, false); 805 | }; 806 | 807 | BigInteger.prototype.prev = function () { 808 | var value = this.value; 809 | if (this.sign) { 810 | return new BigInteger(addSmall(value, 1), true); 811 | } 812 | return subtractSmall(value, 1, this.sign); 813 | }; 814 | SmallInteger.prototype.prev = function () { 815 | var value = this.value; 816 | if (value - 1 > -MAX_INT) return new SmallInteger(value - 1); 817 | return new BigInteger(MAX_INT_ARR, true); 818 | }; 819 | 820 | var powersOfTwo = [1]; 821 | while (powersOfTwo[powersOfTwo.length - 1] <= BASE) powersOfTwo.push(2 * powersOfTwo[powersOfTwo.length - 1]); 822 | var powers2Length = powersOfTwo.length, highestPower2 = powersOfTwo[powers2Length - 1]; 823 | 824 | function shift_isSmall(n) { 825 | return ((typeof n === "number" || typeof n === "string") && +Math.abs(n) <= BASE) || 826 | (n instanceof BigInteger && n.value.length <= 1); 827 | } 828 | 829 | BigInteger.prototype.shiftLeft = function (n) { 830 | if (!shift_isSmall(n)) { 831 | if (n.isNegative()) return this.shiftRight(n.abs()); 832 | return this.times(CACHE[2].pow(n)); 833 | } 834 | n = +n; 835 | if (n < 0) return this.shiftRight(-n); 836 | var result = this; 837 | while (n >= powers2Length) { 838 | result = result.multiply(highestPower2); 839 | n -= powers2Length - 1; 840 | } 841 | return result.multiply(powersOfTwo[n]); 842 | }; 843 | SmallInteger.prototype.shiftLeft = BigInteger.prototype.shiftLeft; 844 | 845 | BigInteger.prototype.shiftRight = function (n) { 846 | var remQuo; 847 | if (!shift_isSmall(n)) { 848 | if (n.isNegative()) return this.shiftLeft(n.abs()); 849 | remQuo = this.divmod(CACHE[2].pow(n)); 850 | return remQuo.remainder.isNegative() ? remQuo.quotient.prev() : remQuo.quotient; 851 | } 852 | n = +n; 853 | if (n < 0) return this.shiftLeft(-n); 854 | var result = this; 855 | while (n >= powers2Length) { 856 | if (result.isZero()) return result; 857 | remQuo = divModAny(result, highestPower2); 858 | result = remQuo[1].isNegative() ? remQuo[0].prev() : remQuo[0]; 859 | n -= powers2Length - 1; 860 | } 861 | remQuo = divModAny(result, powersOfTwo[n]); 862 | return remQuo[1].isNegative() ? remQuo[0].prev() : remQuo[0]; 863 | }; 864 | SmallInteger.prototype.shiftRight = BigInteger.prototype.shiftRight; 865 | 866 | function bitwise(x, y, fn) { 867 | y = parseValue(y); 868 | var xSign = x.isNegative(), ySign = y.isNegative(); 869 | var xRem = xSign ? x.not() : x, 870 | yRem = ySign ? y.not() : y; 871 | var xBits = [], yBits = []; 872 | var xStop = false, yStop = false; 873 | while (!xStop || !yStop) { 874 | if (xRem.isZero()) { // virtual sign extension for simulating two's complement 875 | xStop = true; 876 | xBits.push(xSign ? 1 : 0); 877 | } 878 | else if (xSign) xBits.push(xRem.isEven() ? 1 : 0); // two's complement for negative numbers 879 | else xBits.push(xRem.isEven() ? 0 : 1); 880 | 881 | if (yRem.isZero()) { 882 | yStop = true; 883 | yBits.push(ySign ? 1 : 0); 884 | } 885 | else if (ySign) yBits.push(yRem.isEven() ? 1 : 0); 886 | else yBits.push(yRem.isEven() ? 0 : 1); 887 | 888 | xRem = xRem.over(2); 889 | yRem = yRem.over(2); 890 | } 891 | var result = []; 892 | for (var i = 0; i < xBits.length; i++) result.push(fn(xBits[i], yBits[i])); 893 | var sum = bigInt(result.pop()).negate().times(bigInt(2).pow(result.length)); 894 | while (result.length) { 895 | sum = sum.add(bigInt(result.pop()).times(bigInt(2).pow(result.length))); 896 | } 897 | return sum; 898 | } 899 | 900 | BigInteger.prototype.not = function () { 901 | return this.negate().prev(); 902 | }; 903 | SmallInteger.prototype.not = BigInteger.prototype.not; 904 | 905 | BigInteger.prototype.and = function (n) { 906 | return bitwise(this, n, function (a, b) { return a & b; }); 907 | }; 908 | SmallInteger.prototype.and = BigInteger.prototype.and; 909 | 910 | BigInteger.prototype.or = function (n) { 911 | return bitwise(this, n, function (a, b) { return a | b; }); 912 | }; 913 | SmallInteger.prototype.or = BigInteger.prototype.or; 914 | 915 | BigInteger.prototype.xor = function (n) { 916 | return bitwise(this, n, function (a, b) { return a ^ b; }); 917 | }; 918 | SmallInteger.prototype.xor = BigInteger.prototype.xor; 919 | 920 | var LOBMASK_I = 1 << 30, LOBMASK_BI = (BASE & -BASE) * (BASE & -BASE) | LOBMASK_I; 921 | function roughLOB(n) { // get lowestOneBit (rough) 922 | // SmallInteger: return Min(lowestOneBit(n), 1 << 30) 923 | // BigInteger: return Min(lowestOneBit(n), 1 << 14) [BASE=1e7] 924 | var v = n.value, x = typeof v === "number" ? v | LOBMASK_I : v[0] + v[1] * BASE | LOBMASK_BI; 925 | return x & -x; 926 | } 927 | 928 | function max(a, b) { 929 | a = parseValue(a); 930 | b = parseValue(b); 931 | return a.greater(b) ? a : b; 932 | } 933 | function min(a,b) { 934 | a = parseValue(a); 935 | b = parseValue(b); 936 | return a.lesser(b) ? a : b; 937 | } 938 | function gcd(a, b) { 939 | a = parseValue(a).abs(); 940 | b = parseValue(b).abs(); 941 | if (a.equals(b)) return a; 942 | if (a.isZero()) return b; 943 | if (b.isZero()) return a; 944 | var c = CACHE[1], d, t; 945 | while (a.isEven() && b.isEven()) { 946 | d = Math.min(roughLOB(a), roughLOB(b)); 947 | a = a.divide(d); 948 | b = b.divide(d); 949 | c = c.multiply(d); 950 | } 951 | while (a.isEven()) { 952 | a = a.divide(roughLOB(a)); 953 | } 954 | do { 955 | while (b.isEven()) { 956 | b = b.divide(roughLOB(b)); 957 | } 958 | if (a.greater(b)) { 959 | t = b; b = a; a = t; 960 | } 961 | b = b.subtract(a); 962 | } while (!b.isZero()); 963 | return c.isUnit() ? a : a.multiply(c); 964 | } 965 | function lcm(a, b) { 966 | a = parseValue(a).abs(); 967 | b = parseValue(b).abs(); 968 | return a.divide(gcd(a, b)).multiply(b); 969 | } 970 | function randBetween(a, b) { 971 | a = parseValue(a); 972 | b = parseValue(b); 973 | var low = min(a, b), high = max(a, b); 974 | var range = high.subtract(low); 975 | if (range.isSmall) return low.add(Math.round(Math.random() * range)); 976 | var length = range.value.length - 1; 977 | var result = [], restricted = true; 978 | for (var i = length; i >= 0; i--) { 979 | var top = restricted ? range.value[i] : BASE; 980 | var digit = truncate(Math.random() * top); 981 | result.unshift(digit); 982 | if (digit < top) restricted = false; 983 | } 984 | result = arrayToSmall(result); 985 | return low.add(typeof result === "number" ? new SmallInteger(result) : new BigInteger(result, false)); 986 | } 987 | var parseBase = function (text, base) { 988 | var val = CACHE[0], pow = CACHE[1], 989 | length = text.length; 990 | if (2 <= base && base <= 36) { 991 | if (length <= LOG_MAX_INT / Math.log(base)) { 992 | return new SmallInteger(parseInt(text, base)); 993 | } 994 | } 995 | base = parseValue(base); 996 | var digits = []; 997 | var i; 998 | var isNegative = text[0] === "-"; 999 | for (i = isNegative ? 1 : 0; i < text.length; i++) { 1000 | var c = text[i].toLowerCase(), 1001 | charCode = c.charCodeAt(0); 1002 | if (48 <= charCode && charCode <= 57) digits.push(parseValue(c)); 1003 | else if (97 <= charCode && charCode <= 122) digits.push(parseValue(c.charCodeAt(0) - 87)); 1004 | else if (c === "<") { 1005 | var start = i; 1006 | do { i++; } while (text[i] !== ">"); 1007 | digits.push(parseValue(text.slice(start + 1, i))); 1008 | } 1009 | else throw new Error(c + " is not a valid character"); 1010 | } 1011 | digits.reverse(); 1012 | for (i = 0; i < digits.length; i++) { 1013 | val = val.add(digits[i].times(pow)); 1014 | pow = pow.times(base); 1015 | } 1016 | return isNegative ? val.negate() : val; 1017 | }; 1018 | 1019 | function stringify(digit) { 1020 | var v = digit.value; 1021 | if (typeof v === "number") v = [v]; 1022 | if (v.length === 1 && v[0] <= 36) { 1023 | return "0123456789abcdefghijklmnopqrstuvwxyz".charAt(v[0]); 1024 | } 1025 | return "<" + v + ">"; 1026 | } 1027 | function toBase(n, base) { 1028 | base = bigInt(base); 1029 | if (base.isZero()) { 1030 | if (n.isZero()) return "0"; 1031 | throw new Error("Cannot convert nonzero numbers to base 0."); 1032 | } 1033 | if (base.equals(-1)) { 1034 | if (n.isZero()) return "0"; 1035 | if (n.isNegative()) return new Array(1 - n).join("10"); 1036 | return "1" + new Array(+n).join("01"); 1037 | } 1038 | var minusSign = ""; 1039 | if (n.isNegative() && base.isPositive()) { 1040 | minusSign = "-"; 1041 | n = n.abs(); 1042 | } 1043 | if (base.equals(1)) { 1044 | if (n.isZero()) return "0"; 1045 | return minusSign + new Array(+n + 1).join(1); 1046 | } 1047 | var out = []; 1048 | var left = n, divmod; 1049 | while (left.isNegative() || left.compareAbs(base) >= 0) { 1050 | divmod = left.divmod(base); 1051 | left = divmod.quotient; 1052 | var digit = divmod.remainder; 1053 | if (digit.isNegative()) { 1054 | digit = base.minus(digit).abs(); 1055 | left = left.next(); 1056 | } 1057 | out.push(stringify(digit)); 1058 | } 1059 | out.push(stringify(left)); 1060 | return minusSign + out.reverse().join(""); 1061 | } 1062 | 1063 | BigInteger.prototype.toString = function (radix) { 1064 | if (radix === undefined) radix = 10; 1065 | if (radix !== 10) return toBase(this, radix); 1066 | var v = this.value, l = v.length, str = String(v[--l]), zeros = "0000000", digit; 1067 | while (--l >= 0) { 1068 | digit = String(v[l]); 1069 | str += zeros.slice(digit.length) + digit; 1070 | } 1071 | var sign = this.sign ? "-" : ""; 1072 | return sign + str; 1073 | }; 1074 | SmallInteger.prototype.toString = function (radix) { 1075 | if (radix === undefined) radix = 10; 1076 | if (radix != 10) return toBase(this, radix); 1077 | return String(this.value); 1078 | }; 1079 | 1080 | BigInteger.prototype.valueOf = function () { 1081 | return +this.toString(); 1082 | }; 1083 | BigInteger.prototype.toJSNumber = BigInteger.prototype.valueOf; 1084 | 1085 | SmallInteger.prototype.valueOf = function () { 1086 | return this.value; 1087 | }; 1088 | SmallInteger.prototype.toJSNumber = SmallInteger.prototype.valueOf; 1089 | 1090 | function parseStringValue(v) { 1091 | if (isPrecise(+v)) { 1092 | var x = +v; 1093 | if (x === truncate(x)) 1094 | return new SmallInteger(x); 1095 | throw "Invalid integer: " + v; 1096 | } 1097 | var sign = v[0] === "-"; 1098 | if (sign) v = v.slice(1); 1099 | var split = v.split(/e/i); 1100 | if (split.length > 2) throw new Error("Invalid integer: " + text.join("e")); 1101 | if (split.length === 2) { 1102 | var exp = split[1]; 1103 | if (exp[0] === "+") exp = exp.slice(1); 1104 | exp = +exp; 1105 | if (exp !== truncate(exp) || !isPrecise(exp)) throw new Error("Invalid integer: " + exp + " is not a valid exponent."); 1106 | var text = split[0]; 1107 | var decimalPlace = text.indexOf("."); 1108 | if (decimalPlace >= 0) { 1109 | exp -= text.length - decimalPlace; 1110 | text = text.slice(0, decimalPlace) + text.slice(decimalPlace + 1); 1111 | } 1112 | if (exp < 0) throw new Error("Cannot include negative exponent part for integers"); 1113 | text += (new Array(exp + 1)).join("0"); 1114 | v = text; 1115 | } 1116 | var isValid = /^([0-9][0-9]*)$/.test(v); 1117 | if (!isValid) throw new Error("Invalid integer: " + v); 1118 | var r = [], max = v.length, l = LOG_BASE, min = max - l; 1119 | while (max > 0) { 1120 | r.push(+v.slice(min, max)); 1121 | min -= l; 1122 | if (min < 0) min = 0; 1123 | max -= l; 1124 | } 1125 | trim(r); 1126 | return new BigInteger(r, sign); 1127 | } 1128 | 1129 | function parseNumberValue(v) { 1130 | if (isPrecise(v)) return new SmallInteger(v); 1131 | return parseStringValue(v.toString()); 1132 | } 1133 | 1134 | function parseValue(v) { 1135 | if (typeof v === "number") { 1136 | return parseNumberValue(v); 1137 | } 1138 | if (typeof v === "string") { 1139 | return parseStringValue(v); 1140 | } 1141 | return v; 1142 | } 1143 | // Pre-define numbers in range [-999,999] 1144 | var CACHE = function (v, radix) { 1145 | if (typeof v === "undefined") return CACHE[0]; 1146 | if (typeof radix !== "undefined") return +radix === 10 ? parseValue(v) : parseBase(v, radix); 1147 | return parseValue(v); 1148 | }; 1149 | for (var i = 0; i < 1000; i++) { 1150 | CACHE[i] = new SmallInteger(i); 1151 | if (i > 0) CACHE[-i] = new SmallInteger(-i); 1152 | } 1153 | // Backwards compatibility 1154 | CACHE.one = CACHE[1]; 1155 | CACHE.zero = CACHE[0]; 1156 | CACHE.minusOne = CACHE[-1]; 1157 | CACHE.max = max; 1158 | CACHE.min = min; 1159 | CACHE.gcd = gcd; 1160 | CACHE.lcm = lcm; 1161 | CACHE.isInstance = function (x) { return x instanceof BigInteger || x instanceof SmallInteger; }; 1162 | CACHE.randBetween = randBetween; 1163 | return CACHE; 1164 | })(); 1165 | 1166 | // Node.js check 1167 | if (typeof module !== "undefined" && module.hasOwnProperty("exports")) { 1168 | module.exports = bigInt; 1169 | } 1170 | 1171 | },{}],2:[function(require,module,exports){ 1172 | var window = require('global/window'); 1173 | var nodeCrypto = require('crypto'); 1174 | 1175 | function getRandomValues(buf) { 1176 | if (window.crypto && window.crypto.getRandomValues) { 1177 | window.crypto.getRandomValues(buf); 1178 | } 1179 | else if (typeof window.msCrypto === 'object' && typeof window.msCrypto.getRandomValues === 'function') { 1180 | window.msCrypto.getRandomValues(buf); 1181 | } 1182 | else if (nodeCrypto.randomBytes) { 1183 | if (buf.length > 65536) { 1184 | var e = new Error(); 1185 | e.code = 22; 1186 | e.message = 'Failed to execute \'getRandomValues\' on \'Crypto\': The ' + 1187 | 'ArrayBufferView\'s byte length (' + buf.length + ') exceeds the ' + 1188 | 'number of bytes of entropy available via this API (65536).'; 1189 | e.name = 'QuotaExceededError'; 1190 | throw e; 1191 | } 1192 | var bytes = nodeCrypto.randomBytes(buf.length); 1193 | buf.set(bytes); 1194 | } 1195 | else { 1196 | throw new Error('No secure random number generator available.'); 1197 | } 1198 | } 1199 | 1200 | module.exports = getRandomValues; 1201 | },{"crypto":10,"global/window":3}],3:[function(require,module,exports){ 1202 | (function (global){ 1203 | if (typeof window !== "undefined") { 1204 | module.exports = window; 1205 | } else if (typeof global !== "undefined") { 1206 | module.exports = global; 1207 | } else if (typeof self !== "undefined"){ 1208 | module.exports = self; 1209 | } else { 1210 | module.exports = {}; 1211 | } 1212 | 1213 | }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) 1214 | },{}],4:[function(require,module,exports){ 1215 | arguments[4][3][0].apply(exports,arguments) 1216 | },{"dup":3}],5:[function(require,module,exports){ 1217 | /*! http://mths.be/fromcodepoint v0.2.1 by @mathias */ 1218 | if (!String.fromCodePoint) { 1219 | (function() { 1220 | var defineProperty = (function() { 1221 | // IE 8 only supports `Object.defineProperty` on DOM elements 1222 | try { 1223 | var object = {}; 1224 | var $defineProperty = Object.defineProperty; 1225 | var result = $defineProperty(object, object, object) && $defineProperty; 1226 | } catch(error) {} 1227 | return result; 1228 | }()); 1229 | var stringFromCharCode = String.fromCharCode; 1230 | var floor = Math.floor; 1231 | var fromCodePoint = function(_) { 1232 | var MAX_SIZE = 0x4000; 1233 | var codeUnits = []; 1234 | var highSurrogate; 1235 | var lowSurrogate; 1236 | var index = -1; 1237 | var length = arguments.length; 1238 | if (!length) { 1239 | return ''; 1240 | } 1241 | var result = ''; 1242 | while (++index < length) { 1243 | var codePoint = Number(arguments[index]); 1244 | if ( 1245 | !isFinite(codePoint) || // `NaN`, `+Infinity`, or `-Infinity` 1246 | codePoint < 0 || // not a valid Unicode code point 1247 | codePoint > 0x10FFFF || // not a valid Unicode code point 1248 | floor(codePoint) != codePoint // not an integer 1249 | ) { 1250 | throw RangeError('Invalid code point: ' + codePoint); 1251 | } 1252 | if (codePoint <= 0xFFFF) { // BMP code point 1253 | codeUnits.push(codePoint); 1254 | } else { // Astral code point; split in surrogate halves 1255 | // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae 1256 | codePoint -= 0x10000; 1257 | highSurrogate = (codePoint >> 10) + 0xD800; 1258 | lowSurrogate = (codePoint % 0x400) + 0xDC00; 1259 | codeUnits.push(highSurrogate, lowSurrogate); 1260 | } 1261 | if (index + 1 == length || codeUnits.length > MAX_SIZE) { 1262 | result += stringFromCharCode.apply(null, codeUnits); 1263 | codeUnits.length = 0; 1264 | } 1265 | } 1266 | return result; 1267 | }; 1268 | if (defineProperty) { 1269 | defineProperty(String, 'fromCodePoint', { 1270 | 'value': fromCodePoint, 1271 | 'configurable': true, 1272 | 'writable': true 1273 | }); 1274 | } else { 1275 | String.fromCodePoint = fromCodePoint; 1276 | } 1277 | }()); 1278 | } 1279 | 1280 | },{}],6:[function(require,module,exports){ 1281 | /*! http://mths.be/codepointat v0.2.0 by @mathias */ 1282 | if (!String.prototype.codePointAt) { 1283 | (function() { 1284 | 'use strict'; // needed to support `apply`/`call` with `undefined`/`null` 1285 | var defineProperty = (function() { 1286 | // IE 8 only supports `Object.defineProperty` on DOM elements 1287 | try { 1288 | var object = {}; 1289 | var $defineProperty = Object.defineProperty; 1290 | var result = $defineProperty(object, object, object) && $defineProperty; 1291 | } catch(error) {} 1292 | return result; 1293 | }()); 1294 | var codePointAt = function(position) { 1295 | if (this == null) { 1296 | throw TypeError(); 1297 | } 1298 | var string = String(this); 1299 | var size = string.length; 1300 | // `ToInteger` 1301 | var index = position ? Number(position) : 0; 1302 | if (index != index) { // better `isNaN` 1303 | index = 0; 1304 | } 1305 | // Account for out-of-bounds indices: 1306 | if (index < 0 || index >= size) { 1307 | return undefined; 1308 | } 1309 | // Get the first code unit 1310 | var first = string.charCodeAt(index); 1311 | var second; 1312 | if ( // check if it’s the start of a surrogate pair 1313 | first >= 0xD800 && first <= 0xDBFF && // high surrogate 1314 | size > index + 1 // there is a next code unit 1315 | ) { 1316 | second = string.charCodeAt(index + 1); 1317 | if (second >= 0xDC00 && second <= 0xDFFF) { // low surrogate 1318 | // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae 1319 | return (first - 0xD800) * 0x400 + second - 0xDC00 + 0x10000; 1320 | } 1321 | } 1322 | return first; 1323 | }; 1324 | if (defineProperty) { 1325 | defineProperty(String.prototype, 'codePointAt', { 1326 | 'value': codePointAt, 1327 | 'configurable': true, 1328 | 'writable': true 1329 | }); 1330 | } else { 1331 | String.prototype.codePointAt = codePointAt; 1332 | } 1333 | }()); 1334 | } 1335 | 1336 | },{}],7:[function(require,module,exports){ 1337 | // UTF8 : Manage UTF-8 strings in ArrayBuffers 1338 | if(module.require) { 1339 | require('string.fromcodepoint'); 1340 | require('string.prototype.codepointat'); 1341 | } 1342 | 1343 | var UTF8={ 1344 | // non UTF8 encoding detection (cf README file for details) 1345 | 'isNotUTF8': function(bytes, byteOffset, byteLength) { 1346 | try { 1347 | UTF8.getStringFromBytes(bytes, byteOffset, byteLength, true); 1348 | } catch(e) { 1349 | return true; 1350 | } 1351 | return false; 1352 | }, 1353 | // UTF8 decoding functions 1354 | 'getCharLength': function(theByte) { 1355 | // 4 bytes encoded char (mask 11110000) 1356 | if(0xF0 == (theByte&0xF0)) { 1357 | return 4; 1358 | // 3 bytes encoded char (mask 11100000) 1359 | } else if(0xE0 == (theByte&0xE0)) { 1360 | return 3; 1361 | // 2 bytes encoded char (mask 11000000) 1362 | } else if(0xC0 == (theByte&0xC0)) { 1363 | return 2; 1364 | // 1 bytes encoded char 1365 | } else if(theByte == (theByte&0x7F)) { 1366 | return 1; 1367 | } 1368 | return 0; 1369 | }, 1370 | 'getCharCode': function(bytes, byteOffset, charLength) { 1371 | var charCode = 0, mask = ''; 1372 | byteOffset = byteOffset || 0; 1373 | // Retrieve charLength if not given 1374 | charLength = charLength || UTF8.getCharLength(bytes[byteOffset]); 1375 | if(charLength == 0) { 1376 | throw new Error(bytes[byteOffset].toString(2)+' is not a significative' + 1377 | ' byte (offset:'+byteOffset+').'); 1378 | } 1379 | // Return byte value if charlength is 1 1380 | if(1 === charLength) { 1381 | return bytes[byteOffset]; 1382 | } 1383 | // Test UTF8 integrity 1384 | mask = '00000000'.slice(0, charLength) + 1 + '00000000'.slice(charLength + 1); 1385 | if(bytes[byteOffset]&(parseInt(mask, 2))) { 1386 | throw Error('Index ' + byteOffset + ': A ' + charLength + ' bytes' + 1387 | ' encoded char' +' cannot encode the '+(charLength+1)+'th rank bit to 1.'); 1388 | } 1389 | // Reading the first byte 1390 | mask='0000'.slice(0,charLength+1)+'11111111'.slice(charLength+1); 1391 | charCode+=(bytes[byteOffset]&parseInt(mask,2))<<((--charLength)*6); 1392 | // Reading the next bytes 1393 | while(charLength) { 1394 | if(0x80!==(bytes[byteOffset+1]&0x80) 1395 | ||0x40===(bytes[byteOffset+1]&0x40)) { 1396 | throw Error('Index '+(byteOffset+1)+': Next bytes of encoded char' 1397 | +' must begin with a "10" bit sequence.'); 1398 | } 1399 | charCode += ((bytes[++byteOffset]&0x3F) << ((--charLength) * 6)); 1400 | } 1401 | return charCode; 1402 | }, 1403 | 'getStringFromBytes': function(bytes, byteOffset, byteLength, strict) { 1404 | var charLength, chars = []; 1405 | byteOffset = byteOffset|0; 1406 | byteLength=('number' === typeof byteLength ? 1407 | byteLength : 1408 | bytes.byteLength || bytes.length 1409 | ); 1410 | for(; byteOffset < byteLength; byteOffset++) { 1411 | charLength = UTF8.getCharLength(bytes[byteOffset]); 1412 | if(byteOffset + charLength > byteLength) { 1413 | if(strict) { 1414 | throw Error('Index ' + byteOffset + ': Found a ' + charLength + 1415 | ' bytes encoded char declaration but only ' + 1416 | (byteLength - byteOffset) +' bytes are available.'); 1417 | } 1418 | } else { 1419 | chars.push(String.fromCodePoint( 1420 | UTF8.getCharCode(bytes, byteOffset, charLength, strict) 1421 | )); 1422 | } 1423 | byteOffset += charLength - 1; 1424 | } 1425 | return chars.join(''); 1426 | }, 1427 | // UTF8 encoding functions 1428 | 'getBytesForCharCode': function(charCode) { 1429 | if(charCode < 128) { 1430 | return 1; 1431 | } else if(charCode < 2048) { 1432 | return 2; 1433 | } else if(charCode < 65536) { 1434 | return 3; 1435 | } else if(charCode < 2097152) { 1436 | return 4; 1437 | } 1438 | throw new Error('CharCode '+charCode+' cannot be encoded with UTF8.'); 1439 | }, 1440 | 'setBytesFromCharCode': function(charCode, bytes, byteOffset, neededBytes) { 1441 | charCode = charCode|0; 1442 | bytes = bytes || []; 1443 | byteOffset = byteOffset|0; 1444 | neededBytes = neededBytes || UTF8.getBytesForCharCode(charCode); 1445 | // Setting the charCode as it to bytes if the byte length is 1 1446 | if(1 == neededBytes) { 1447 | bytes[byteOffset] = charCode; 1448 | } else { 1449 | // Computing the first byte 1450 | bytes[byteOffset++] = 1451 | (parseInt('1111'.slice(0, neededBytes), 2) << 8 - neededBytes) + 1452 | (charCode >>> ((--neededBytes) * 6)); 1453 | // Computing next bytes 1454 | for(;neededBytes>0;) { 1455 | bytes[byteOffset++] = ((charCode>>>((--neededBytes) * 6))&0x3F)|0x80; 1456 | } 1457 | } 1458 | return bytes; 1459 | }, 1460 | 'setBytesFromString': function(string, bytes, byteOffset, byteLength, strict) { 1461 | string = string || ''; 1462 | bytes = bytes || []; 1463 | byteOffset = byteOffset|0; 1464 | byteLength = ('number' === typeof byteLength ? 1465 | byteLength : 1466 | bytes.byteLength||Infinity 1467 | ); 1468 | for(var i = 0, j = string.length; i < j; i++) { 1469 | var neededBytes = UTF8.getBytesForCharCode(string[i].codePointAt(0)); 1470 | if(strict && byteOffset + neededBytes > byteLength) { 1471 | throw new Error('Not enought bytes to encode the char "' + string[i] + 1472 | '" at the offset "' + byteOffset + '".'); 1473 | } 1474 | UTF8.setBytesFromCharCode(string[i].codePointAt(0), 1475 | bytes, byteOffset, neededBytes, strict); 1476 | byteOffset += neededBytes; 1477 | } 1478 | return bytes; 1479 | } 1480 | }; 1481 | 1482 | if('undefined' !== typeof module) { 1483 | module.exports = UTF8; 1484 | } 1485 | 1486 | 1487 | },{"string.fromcodepoint":5,"string.prototype.codepointat":6}],8:[function(require,module,exports){ 1488 | (function (global){ 1489 | if (typeof require === "function") { 1490 | var bigInt = require("big-integer"); 1491 | var getRandomValues = require('get-random-values'); 1492 | var UTF8 = require('utf-8'); 1493 | var window = require('global/window'); 1494 | 1495 | /* 1496 | * Implements base64 decode and encode in browser that 1497 | * it hasn't support of window.btoa and window.atob 1498 | * methods. 1499 | * Based in Nick Galbreath 1500 | * http://code.google.com/p/stringencoders/source/browse/#svn/ 1501 | * and Carlo Zottmann jQuery port 1502 | * http://github.com/carlo/jquery-base64 1503 | * Adapted by SeViR in DIGIO 1504 | */ 1505 | 1506 | if (!window.atob && !window.btoa){ 1507 | ( function( window ) { 1508 | var _PADCHAR = "=", 1509 | _ALPHA = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 1510 | 1511 | function _getbyte64( s, i ) { 1512 | var idx = _ALPHA.indexOf( s.charAt( i ) ); 1513 | 1514 | if ( idx === -1 ) { 1515 | throw "Cannot decode base64"; 1516 | } 1517 | 1518 | return idx; 1519 | } 1520 | 1521 | function _decode( s ) { 1522 | var pads = 0, 1523 | i, 1524 | b10, 1525 | imax = s.length, 1526 | x = []; 1527 | 1528 | s = String( s ); 1529 | 1530 | if ( imax === 0 ) { 1531 | return s; 1532 | } 1533 | 1534 | if ( imax % 4 !== 0 ) { 1535 | throw "Cannot decode base64"; 1536 | } 1537 | 1538 | if ( s.charAt( imax - 1 ) === _PADCHAR ) { 1539 | pads = 1; 1540 | 1541 | if ( s.charAt( imax - 2 ) === _PADCHAR ) { 1542 | pads = 2; 1543 | } 1544 | 1545 | // either way, we want to ignore this last block 1546 | imax -= 4; 1547 | } 1548 | 1549 | for ( i = 0; i < imax; i += 4 ) { 1550 | b10 = ( _getbyte64( s, i ) << 18 ) | ( _getbyte64( s, i + 1 ) << 12 ) | ( _getbyte64( s, i + 2 ) << 6 ) | _getbyte64( s, i + 3 ); 1551 | x.push( String.fromCharCode( b10 >> 16, ( b10 >> 8 ) & 0xff, b10 & 0xff ) ); 1552 | } 1553 | 1554 | switch ( pads ) { 1555 | case 1: 1556 | b10 = ( _getbyte64( s, i ) << 18 ) | ( _getbyte64( s, i + 1 ) << 12 ) | ( _getbyte64( s, i + 2 ) << 6 ); 1557 | x.push( String.fromCharCode( b10 >> 16, ( b10 >> 8 ) & 0xff ) ); 1558 | break; 1559 | 1560 | case 2: 1561 | b10 = ( _getbyte64( s, i ) << 18) | ( _getbyte64( s, i + 1 ) << 12 ); 1562 | x.push( String.fromCharCode( b10 >> 16 ) ); 1563 | break; 1564 | } 1565 | 1566 | return x.join( "" ); 1567 | } 1568 | 1569 | function _getbyte( s, i ) { 1570 | var x = s.charCodeAt( i ); 1571 | 1572 | if ( x > 255 ) { 1573 | throw "INVALID_CHARACTER_ERR: DOM Exception 5"; 1574 | } 1575 | 1576 | return x; 1577 | } 1578 | 1579 | function _encode( s ) { 1580 | if ( arguments.length !== 1 ) { 1581 | throw "SyntaxError: exactly one argument required"; 1582 | } 1583 | 1584 | s = String( s ); 1585 | 1586 | var i, 1587 | b10, 1588 | x = [], 1589 | imax = s.length - s.length % 3; 1590 | 1591 | if ( s.length === 0 ) { 1592 | return s; 1593 | } 1594 | 1595 | for ( i = 0; i < imax; i += 3 ) { 1596 | b10 = ( _getbyte( s, i ) << 16 ) | ( _getbyte( s, i + 1 ) << 8 ) | _getbyte( s, i + 2 ); 1597 | x.push( _ALPHA.charAt( b10 >> 18 ) ); 1598 | x.push( _ALPHA.charAt( ( b10 >> 12 ) & 0x3F ) ); 1599 | x.push( _ALPHA.charAt( ( b10 >> 6 ) & 0x3f ) ); 1600 | x.push( _ALPHA.charAt( b10 & 0x3f ) ); 1601 | } 1602 | 1603 | switch ( s.length - imax ) { 1604 | case 1: 1605 | b10 = _getbyte( s, i ) << 16; 1606 | x.push( _ALPHA.charAt( b10 >> 18 ) + _ALPHA.charAt( ( b10 >> 12 ) & 0x3F ) + _PADCHAR + _PADCHAR ); 1607 | break; 1608 | 1609 | case 2: 1610 | b10 = ( _getbyte( s, i ) << 16 ) | ( _getbyte( s, i + 1 ) << 8 ); 1611 | x.push( _ALPHA.charAt( b10 >> 18 ) + _ALPHA.charAt( ( b10 >> 12 ) & 0x3F ) + _ALPHA.charAt( ( b10 >> 6 ) & 0x3f ) + _PADCHAR ); 1612 | break; 1613 | } 1614 | 1615 | return x.join( "" ); 1616 | } 1617 | 1618 | window.btoa = _encode; 1619 | window.atob = _decode; 1620 | 1621 | })( window ); 1622 | } 1623 | } 1624 | 1625 | var _sssa_utils = (function (root) { 1626 | var prime = bigInt("115792089237316195423570985008687907853269984665640564039457584007913129639747"); 1627 | 1628 | function random() { 1629 | var bytes = new Uint8Array(32), 1630 | string = "", 1631 | i = 0; 1632 | 1633 | getRandomValues(bytes) 1634 | for (i in bytes) { 1635 | string += Array((2 - bytes[i].toString(16).length) + 1).join(0) + bytes[i].toString(16); 1636 | } 1637 | 1638 | return bigInt(string, 16); 1639 | } 1640 | 1641 | function split_ints(secrets) { 1642 | var result = [], 1643 | working = [], 1644 | i = 0, 1645 | hex_data = ""; 1646 | 1647 | working = UTF8.setBytesFromString(secrets); 1648 | 1649 | for (i in working) { 1650 | hex_data += Array((2 - working[i].toString(16).length) + 1).join(0) + working[i].toString(16); 1651 | } 1652 | 1653 | for (i = 0; i < hex_data.length/64; i++) { 1654 | if ((i+1)*64 < hex_data.length) { 1655 | result[i] = bigInt(hex_data.substring(i*64, (i+1)*64), 16); 1656 | } else { 1657 | result[i] = bigInt(hex_data.substring(i*64) + Array(((i+1)*64 - hex_data.length)+1).join(0), 16); 1658 | } 1659 | } 1660 | 1661 | return result; 1662 | } 1663 | 1664 | function merge_ints(secrets) { 1665 | var hex_data = "", 1666 | bytes = [], 1667 | temp = "", 1668 | i = 0; 1669 | 1670 | for (i in secrets) { 1671 | temp = secrets[i].toString(16); 1672 | temp = Array(64 - temp.length + 1).join(0) + temp; 1673 | hex_data += temp; 1674 | } 1675 | 1676 | hex_data = hex_data.replace(/(00){1,}$/, ''); 1677 | 1678 | for (i = 0; i < hex_data.length/2; i++) { 1679 | bytes.push(parseInt(hex_data.substring(i*2, (i+1)*2), 16)); 1680 | } 1681 | 1682 | return UTF8.getStringFromBytes(bytes); 1683 | } 1684 | 1685 | function evaluate_polynomial(coefficients, value) { 1686 | var result = bigInt(coefficients[0]), 1687 | i = 1; 1688 | 1689 | for (i = 1; i < coefficients.length; i++) { 1690 | result = result.add(value.pow(i, prime).mod(prime).add(prime).mod(prime).multiply(coefficients[i]).mod(prime).add(prime).mod(prime)); 1691 | } 1692 | 1693 | return result.mod(prime); 1694 | } 1695 | 1696 | function to_base64(number) { 1697 | var hex_data = number.toString(16), 1698 | result = "", 1699 | i = 0; 1700 | 1701 | hex_data = Array(64 - hex_data.length + 1).join('0') + hex_data; 1702 | 1703 | for (i = 0; i < hex_data.length/2; i++) { 1704 | result += String.fromCharCode(parseInt(hex_data.substring(i*2, (i+1)*2), 16)); 1705 | } 1706 | 1707 | return btoa(result).replace(/\//g, '_').replace(/\+/g, '-'); 1708 | } 1709 | 1710 | function from_base64(number) { 1711 | var bytes = atob(number.replace(/_/g, '/').replace(/-/g, '+')), 1712 | hex_data = "", 1713 | temp = "", 1714 | i = 0; 1715 | 1716 | for (i = 0; i < bytes.length; i++) { 1717 | temp = bytes.charCodeAt(i).toString(16); 1718 | temp = Array(2 - (temp.length % 3) + 1).join(0) + temp; 1719 | hex_data += temp; 1720 | } 1721 | 1722 | hex_data = hex_data.replace(/^(00){1,}/, ''); 1723 | 1724 | return bigInt(hex_data, 16); 1725 | } 1726 | 1727 | function gcd(a, b) { 1728 | var n = bigInt(0), 1729 | c = bigInt(0), 1730 | r = bigInt(0); 1731 | 1732 | if (b.compare(bigInt(0)) == 0) { 1733 | return [a, bigInt(1), bigInt(0)]; 1734 | } 1735 | 1736 | n = a.divmod(b).quotient; 1737 | c = a.mod(b).add(b).mod(b); 1738 | r = gcd(b, c); 1739 | 1740 | return [r[0], r[2], r[1].subtract(r[2].multiply(n))]; 1741 | } 1742 | 1743 | function mod_inverse(number) { 1744 | var value = gcd(prime, number.mod(prime)); 1745 | var remainder = value[2]; 1746 | 1747 | if (number.compare(0) == -1) { 1748 | remainder = remainder.multiply(-1); 1749 | } 1750 | 1751 | return remainder.mod(prime).add(prime).mod(prime); 1752 | } 1753 | 1754 | return { 1755 | 'prime': prime, 1756 | 'random': random, 1757 | 'split_ints': split_ints, 1758 | 'merge_ints': merge_ints, 1759 | 'evaluate_polynomial': evaluate_polynomial, 1760 | 'to_base64': to_base64, 1761 | 'from_base64': from_base64, 1762 | 'gcd': gcd, 1763 | 'mod_inverse': mod_inverse, 1764 | } 1765 | }(this)); 1766 | 1767 | var _sssa = (function(root) { 1768 | var utils = _sssa_utils; 1769 | 1770 | function create(minimum, shares, raw) { 1771 | if (minimum > shares) { 1772 | return; 1773 | } 1774 | 1775 | var secret = utils.split_ints(raw), 1776 | numbers = [bigInt(0)], 1777 | polynomial = [], 1778 | result = [], 1779 | i = 0, 1780 | j = 1; 1781 | 1782 | for (i in secret) { 1783 | polynomial.push([secret[i]]); 1784 | for (j = 1; j < minimum; j++) { 1785 | value = utils.random(); 1786 | while (value in numbers) { 1787 | value = utils.random(); 1788 | } 1789 | numbers.push(value); 1790 | 1791 | polynomial[i].push(value); 1792 | } 1793 | } 1794 | 1795 | 1796 | for (i = 0; i < shares; i++) { 1797 | for (j in secret) { 1798 | value = utils.random(); 1799 | while (value in numbers) { 1800 | value = utils.random(); 1801 | } 1802 | numbers.push(value); 1803 | 1804 | if (typeof result[i] !== typeof "string") { 1805 | result[i] = ""; 1806 | } 1807 | 1808 | result[i] += utils.to_base64(value); 1809 | result[i] += utils.to_base64(utils.evaluate_polynomial(polynomial[j], value)); 1810 | } 1811 | } 1812 | 1813 | return result; 1814 | } 1815 | 1816 | function combine(shares) { 1817 | var secrets = [], 1818 | share = "", 1819 | count = 0, 1820 | cshare = "", 1821 | secret = [], 1822 | origin = bigInt(0), 1823 | originy = bigInt(0), 1824 | numerator = bigInt(1), 1825 | denominator = bigInt(1), 1826 | i = 0, 1827 | j = 0, 1828 | k = 0; 1829 | 1830 | for (i in shares) { 1831 | if (shares[i].length % 88 != 0) { 1832 | return; 1833 | } 1834 | 1835 | share = shares[i]; 1836 | count = share.length / 88; 1837 | secrets[i] = []; 1838 | 1839 | for (j = 0; j < count; j++) { 1840 | cshare = share.substring(j*88, (j+1)*88); 1841 | secrets[i][j] = [utils.from_base64(cshare.substring(0, 44)), utils.from_base64(cshare.substring(44))]; 1842 | } 1843 | } 1844 | 1845 | for (j = 0; j < secrets[0].length; j++) { 1846 | secret[j] = bigInt(0); 1847 | for (i in secrets) { 1848 | origin = secrets[i][j][0]; 1849 | originy = secrets[i][j][1]; 1850 | numerator = bigInt(1); 1851 | denominator = bigInt(1); 1852 | 1853 | for (k in secrets) { 1854 | if (k !== i) { 1855 | numerator = numerator.multiply(secrets[k][j][0].multiply(-1)).mod(utils.prime).add(utils.prime).mod(utils.prime); 1856 | denominator = denominator.multiply(origin.subtract(secrets[k][j][0])).mod(utils.prime).add(utils.prime).mod(utils.prime); 1857 | } 1858 | } 1859 | 1860 | secret[j] = secret[j].add(originy.multiply(numerator).mod(utils.prime).add(utils.prime).mod(utils.prime).multiply(utils.mod_inverse(denominator)).mod(utils.prime).add(utils.prime).mod(utils.prime)).mod(utils.prime).add(utils.prime).mod(utils.prime); 1861 | } 1862 | } 1863 | 1864 | return utils.merge_ints(secret); 1865 | } 1866 | 1867 | return sssa = { 1868 | 'create': create, 1869 | 'combine': combine 1870 | }; 1871 | }(this)); 1872 | 1873 | var sssa = _sssa; 1874 | module.exports = sssa; 1875 | 1876 | if (typeof global.testing !== "undefined" && global.testing === true) { 1877 | global._sssa_utils = _sssa_utils; 1878 | global._sssa = _sssa; 1879 | } 1880 | 1881 | _sssa = undefined; 1882 | _sssa_utils = undefined; 1883 | 1884 | }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) 1885 | },{"big-integer":1,"get-random-values":2,"global/window":4,"utf-8":7}],9:[function(require,module,exports){ 1886 | (function (global){ 1887 | require('global'); 1888 | 1889 | global.testing = true; 1890 | sssa = require('../sssa.js'); 1891 | bigInt = require('big-integer'); 1892 | 1893 | function logger(text) { 1894 | if (typeof document === "undefined") { 1895 | console.log(text); 1896 | } else { 1897 | document.write(text + "
"); 1898 | } 1899 | } 1900 | 1901 | function assertEqual(actual, expected) { 1902 | if (typeof actual === typeof bigInt(0)) { 1903 | if (actual.compare(expected) !== 0) { 1904 | logger("Assert error: " + actual.toString() + " !== " + expected.toString()); 1905 | return false; 1906 | } 1907 | } else { 1908 | if (actual !== expected) { 1909 | logger("Assert error: " + actual + " !== " + expected); 1910 | return false; 1911 | } 1912 | } 1913 | 1914 | return true; 1915 | } 1916 | 1917 | function main() { 1918 | var utils = global._sssa_utils; 1919 | 1920 | var tests = [ 1921 | function() { 1922 | var start = new Date(); 1923 | 1924 | for (var i = 0; i < 10000; i++) { 1925 | var result = assertEqual(utils.random() < utils.prime, true); 1926 | if (!result) { 1927 | logger("Test failed: TestRandom"); 1928 | return false; 1929 | } 1930 | } 1931 | 1932 | var end = new Date(); 1933 | logger("ok @ TestRandom in " + ((end.getTime() - start.getTime())/1000) + "s"); 1934 | return true; 1935 | }, 1936 | 1937 | function() { 1938 | var start = new Date(); 1939 | 1940 | for (var i = 0; i < 10000; i++) { 1941 | var value = utils.random(); 1942 | 1943 | var result = assertEqual(utils.from_base64(utils.to_base64(value)), value); 1944 | if (!result) { 1945 | logger("Test failed: TestBaseConversion"); 1946 | return false; 1947 | } 1948 | } 1949 | 1950 | var end = new Date(); 1951 | logger("ok @ TestBaseConversion in " + ((end.getTime() - start.getTime())/1000) + "s"); 1952 | return true; 1953 | }, 1954 | 1955 | function() { 1956 | var start = new Date(); 1957 | 1958 | for (var i = 0; i < 10000; i++) { 1959 | var value = utils.random(); 1960 | 1961 | var result = assertEqual(utils.to_base64(value).length, 44); 1962 | if (!result) { 1963 | logger("Test failed: TestToBase64"); 1964 | return false; 1965 | } 1966 | } 1967 | 1968 | var end = new Date(); 1969 | logger("ok @ TestToBase64 in " + ((end.getTime() - start.getTime())/1000) + "s"); 1970 | return true; 1971 | }, 1972 | 1973 | function() { 1974 | var start = new Date(); 1975 | 1976 | var values = ["N17FigASkL6p1EOgJhRaIquQLGvYV0", "0y10VAfmyH7GLQY6QccCSLKJi8iFgpcSBTLyYOGbiYPqOpStAf1OYuzEBzZR", "KjRHO1nHmIDidf6fKvsiXWcTqNYo2U9U8juO94EHXVqgearRISTQe0zAjkeUYYBvtcB8VWzZHYm6ktMlhOXXCfRFhbJzBUsXaHb5UDQAvs2GKy6yq0mnp8gCj98ksDlUultqygybYyHvjqR7D7EAWIKPKUVz4of8OzSjZlYg7YtCUMYhwQDryESiYabFID1PKBfKn5WSGgJBIsDw5g2HB2AqC1r3K8GboDN616Swo6qjvSFbseeETCYDB3ikS7uiK67ErIULNqVjf7IKoOaooEhQACmZ5HdWpr34tstg18rO"]; 1977 | 1978 | for (var index in values) { 1979 | var result = assertEqual(utils.merge_ints(utils.split_ints(values[index])), values[index]); 1980 | if (!result) { 1981 | logger("Test failed: TestSplitMerge"); 1982 | return false; 1983 | } 1984 | } 1985 | 1986 | var end = new Date(); 1987 | logger("ok @ TestSplitMerge in " + ((end.getTime() - start.getTime())/1000) + "s"); 1988 | return true; 1989 | }, 1990 | 1991 | function() { 1992 | var start = new Date(); 1993 | 1994 | var values = ["a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00a", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa哈囉世界", "こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界"]; 1995 | for (var index in values) { 1996 | var result = assertEqual(utils.merge_ints(utils.split_ints(values[index])), values[index]); 1997 | if (!result) { 1998 | logger("Test failed: TestSplitMergeOdds"); 1999 | return false; 2000 | } 2001 | } 2002 | 2003 | var end = new Date(); 2004 | logger("ok @ TestSplitMergeOdds in " + ((end.getTime() - start.getTime())/1000) + "s"); 2005 | return true; 2006 | }, 2007 | 2008 | function() { 2009 | var start = new Date(); 2010 | 2011 | for (var i = 0; i < 10000; i++) { 2012 | var value = utils.random(); 2013 | var inverse = utils.mod_inverse(value); 2014 | var actual = value.multiply(inverse).mod(utils.prime).add(utils.prime).mod(utils.prime); 2015 | 2016 | var result = assertEqual(actual, bigInt(1)); 2017 | if (!result) { 2018 | logger("Test failed: TestModInverse"); 2019 | return false; 2020 | } 2021 | } 2022 | 2023 | var end = new Date(); 2024 | logger("ok @ TestModInverse in " + ((end.getTime() - start.getTime())/1000) + "s"); 2025 | return true; 2026 | }, 2027 | 2028 | function() { 2029 | var start = new Date(); 2030 | 2031 | var values = [[[bigInt(20), bigInt(21), bigInt(42)], bigInt(0)], [[bigInt(0), bigInt(0), bigInt(0)], bigInt(4)], [[bigInt(1), bigInt(2), bigInt(3), bigInt(4), bigInt(5)], bigInt(10)]]; 2032 | var actual = [bigInt(20), bigInt(0), bigInt(54321)]; 2033 | 2034 | for (var index in values) { 2035 | var result = assertEqual(utils.evaluate_polynomial(values[index][0], values[index][1]), actual[index]); 2036 | if (!result) { 2037 | logger("Test failed: TestEvaluatePolynomial"); 2038 | return false; 2039 | } 2040 | } 2041 | 2042 | var end = new Date(); 2043 | logger("ok @ TestEvaluatePolynomial in " + ((end.getTime() - start.getTime())/1000) + "s"); 2044 | return true; 2045 | }, 2046 | 2047 | function() { 2048 | var start = new Date(); 2049 | 2050 | var values = ["N17FigASkL6p1EOgJhRaIquQLGvYV0", "0y10VAfmyH7GLQY6QccCSLKJi8iFgpcSBTLyYOGbiYPqOpStAf1OYuzEBzZR", "KjRHO1nHmIDidf6fKvsiXWcTqNYo2U9U8juO94EHXVqgearRISTQe0zAjkeUYYBvtcB8VWzZHYm6ktMlhOXXCfRFhbJzBUsXaHb5UDQAvs2GKy6yq0mnp8gCj98ksDlUultqygybYyHvjqR7D7EAWIKPKUVz4of8OzSjZlYg7YtCUMYhwQDryESiYabFID1PKBfKn5WSGgJBIsDw5g2HB2AqC1r3K8GboDN616Swo6qjvSFbseeETCYDB3ikS7uiK67ErIULNqVjf7IKoOaooEhQACmZ5HdWpr34tstg18rO"], 2051 | minimum = [4, 6, 20], 2052 | shares = [5, 100, 100]; 2053 | 2054 | for (var index in values) { 2055 | var result = assertEqual(sssa.combine(sssa.create(minimum[index], shares[index], values[index])), values[index]); 2056 | if (!result) { 2057 | logger("Test failed: TestCreateCombine"); 2058 | return false; 2059 | } 2060 | } 2061 | 2062 | var end = new Date(); 2063 | logger("ok @ TestCreateCombine in " + ((end.getTime() - start.getTime())/1000) + "s"); 2064 | return true; 2065 | }, 2066 | 2067 | function() { 2068 | var start = new Date(); 2069 | 2070 | var shares = ["U1k9koNN67-og3ZY3Mmikeyj4gEFwK4HXDSglM8i_xc=yA3eU4_XYcJP0ijD63Tvqu1gklhBV32tu8cHPZXP-bk=", "O7c_iMBaGmQQE_uU0XRCPQwhfLBdlc6jseTzK_qN-1s=ICDGdloemG50X5GxteWWVZD3EGuxXST4UfZcek_teng=", "8qzYpjk7lmB7cRkOl6-7srVTKNYHuqUO2WO31Y0j1Tw=-g6srNoWkZTBqrKA2cMCA-6jxZiZv25rvbrCUWVHb5g=", "wGXxa_7FPFSVqdo26VKdgFxqVVWXNfwSDQyFmCh2e5w=8bTrIEs0e5FeiaXcIBaGwtGFxeyNtCG4R883tS3MsZ0=", "j8-Y4_7CJvL8aHxc8WMMhP_K2TEsOkxIHb7hBcwIBOo=T5-EOvAlzGMogdPawv3oK88rrygYFza3KSki2q8WEgs="]; 2071 | var result = assertEqual(sssa.combine(shares), "test-pass"); 2072 | 2073 | if (!result) { 2074 | logger("Test failed: TestLibraryCombine"); 2075 | return false; 2076 | } 2077 | var end = new Date(); 2078 | 2079 | logger("ok @ TestLibraryCombine in " + ((end.getTime() - start.getTime())/1000) + "s"); 2080 | return true; 2081 | } 2082 | ]; 2083 | 2084 | for (var i in tests) { 2085 | if (!tests[i]()) { 2086 | return false; 2087 | } 2088 | } 2089 | } 2090 | 2091 | main(); 2092 | 2093 | }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) 2094 | },{"../sssa.js":8,"big-integer":1,"global":4}],10:[function(require,module,exports){ 2095 | 2096 | },{}]},{},[9]); 2097 | -------------------------------------------------------------------------------- /test/sssa.js: -------------------------------------------------------------------------------- 1 | require('global'); 2 | 3 | global.testing = true; 4 | sssa = require('../sssa.js'); 5 | bigInt = require('big-integer'); 6 | 7 | function logger(text) { 8 | if (typeof document === "undefined") { 9 | console.log(text); 10 | } else { 11 | document.write(text + "
"); 12 | } 13 | } 14 | 15 | function assertEqual(actual, expected) { 16 | if (typeof actual === typeof bigInt(0)) { 17 | if (actual.compare(expected) !== 0) { 18 | logger("Assert error: " + actual.toString() + " !== " + expected.toString()); 19 | return false; 20 | } 21 | } else { 22 | if (actual !== expected) { 23 | logger("Assert error: " + actual + " !== " + expected); 24 | return false; 25 | } 26 | } 27 | 28 | return true; 29 | } 30 | 31 | function main() { 32 | var utils = global._sssa_utils; 33 | 34 | var tests = [ 35 | function() { 36 | var start = new Date(); 37 | 38 | for (var i = 0; i < 10000; i++) { 39 | var result = assertEqual(utils.random() < utils.prime, true); 40 | if (!result) { 41 | logger("Test failed: TestRandom"); 42 | return false; 43 | } 44 | } 45 | 46 | var end = new Date(); 47 | logger("ok @ TestRandom in " + ((end.getTime() - start.getTime())/1000) + "s"); 48 | return true; 49 | }, 50 | 51 | function() { 52 | var start = new Date(); 53 | 54 | for (var i = 0; i < 10000; i++) { 55 | var value = utils.random(); 56 | 57 | var result = assertEqual(utils.from_base64(utils.to_base64(value)), value); 58 | if (!result) { 59 | logger("Test failed: TestBaseConversion"); 60 | return false; 61 | } 62 | } 63 | 64 | var end = new Date(); 65 | logger("ok @ TestBaseConversion in " + ((end.getTime() - start.getTime())/1000) + "s"); 66 | return true; 67 | }, 68 | 69 | function() { 70 | var start = new Date(); 71 | 72 | for (var i = 0; i < 10000; i++) { 73 | var value = utils.random(); 74 | 75 | var result = assertEqual(utils.to_base64(value).length, 44); 76 | if (!result) { 77 | logger("Test failed: TestToBase64"); 78 | return false; 79 | } 80 | } 81 | 82 | var end = new Date(); 83 | logger("ok @ TestToBase64 in " + ((end.getTime() - start.getTime())/1000) + "s"); 84 | return true; 85 | }, 86 | 87 | function() { 88 | var start = new Date(); 89 | 90 | var values = ["N17FigASkL6p1EOgJhRaIquQLGvYV0", "0y10VAfmyH7GLQY6QccCSLKJi8iFgpcSBTLyYOGbiYPqOpStAf1OYuzEBzZR", "KjRHO1nHmIDidf6fKvsiXWcTqNYo2U9U8juO94EHXVqgearRISTQe0zAjkeUYYBvtcB8VWzZHYm6ktMlhOXXCfRFhbJzBUsXaHb5UDQAvs2GKy6yq0mnp8gCj98ksDlUultqygybYyHvjqR7D7EAWIKPKUVz4of8OzSjZlYg7YtCUMYhwQDryESiYabFID1PKBfKn5WSGgJBIsDw5g2HB2AqC1r3K8GboDN616Swo6qjvSFbseeETCYDB3ikS7uiK67ErIULNqVjf7IKoOaooEhQACmZ5HdWpr34tstg18rO"]; 91 | 92 | for (var index in values) { 93 | var result = assertEqual(utils.merge_ints(utils.split_ints(values[index])), values[index]); 94 | if (!result) { 95 | logger("Test failed: TestSplitMerge"); 96 | return false; 97 | } 98 | } 99 | 100 | var end = new Date(); 101 | logger("ok @ TestSplitMerge in " + ((end.getTime() - start.getTime())/1000) + "s"); 102 | return true; 103 | }, 104 | 105 | function() { 106 | var start = new Date(); 107 | 108 | var values = ["a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00a", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa哈囉世界", "こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界こんにちは、世界"]; 109 | for (var index in values) { 110 | var result = assertEqual(utils.merge_ints(utils.split_ints(values[index])), values[index]); 111 | if (!result) { 112 | logger("Test failed: TestSplitMergeOdds"); 113 | return false; 114 | } 115 | } 116 | 117 | var end = new Date(); 118 | logger("ok @ TestSplitMergeOdds in " + ((end.getTime() - start.getTime())/1000) + "s"); 119 | return true; 120 | }, 121 | 122 | function() { 123 | var start = new Date(); 124 | 125 | for (var i = 0; i < 10000; i++) { 126 | var value = utils.random(); 127 | var inverse = utils.mod_inverse(value); 128 | var actual = value.multiply(inverse).mod(utils.prime).add(utils.prime).mod(utils.prime); 129 | 130 | var result = assertEqual(actual, bigInt(1)); 131 | if (!result) { 132 | logger("Test failed: TestModInverse"); 133 | return false; 134 | } 135 | } 136 | 137 | var end = new Date(); 138 | logger("ok @ TestModInverse in " + ((end.getTime() - start.getTime())/1000) + "s"); 139 | return true; 140 | }, 141 | 142 | function() { 143 | var start = new Date(); 144 | 145 | var values = [[[bigInt(20), bigInt(21), bigInt(42)], bigInt(0)], [[bigInt(0), bigInt(0), bigInt(0)], bigInt(4)], [[bigInt(1), bigInt(2), bigInt(3), bigInt(4), bigInt(5)], bigInt(10)]]; 146 | var actual = [bigInt(20), bigInt(0), bigInt(54321)]; 147 | 148 | for (var index in values) { 149 | var result = assertEqual(utils.evaluate_polynomial(values[index][0], values[index][1]), actual[index]); 150 | if (!result) { 151 | logger("Test failed: TestEvaluatePolynomial"); 152 | return false; 153 | } 154 | } 155 | 156 | var end = new Date(); 157 | logger("ok @ TestEvaluatePolynomial in " + ((end.getTime() - start.getTime())/1000) + "s"); 158 | return true; 159 | }, 160 | 161 | function() { 162 | var start = new Date(); 163 | 164 | var values = ["N17FigASkL6p1EOgJhRaIquQLGvYV0", "0y10VAfmyH7GLQY6QccCSLKJi8iFgpcSBTLyYOGbiYPqOpStAf1OYuzEBzZR", "KjRHO1nHmIDidf6fKvsiXWcTqNYo2U9U8juO94EHXVqgearRISTQe0zAjkeUYYBvtcB8VWzZHYm6ktMlhOXXCfRFhbJzBUsXaHb5UDQAvs2GKy6yq0mnp8gCj98ksDlUultqygybYyHvjqR7D7EAWIKPKUVz4of8OzSjZlYg7YtCUMYhwQDryESiYabFID1PKBfKn5WSGgJBIsDw5g2HB2AqC1r3K8GboDN616Swo6qjvSFbseeETCYDB3ikS7uiK67ErIULNqVjf7IKoOaooEhQACmZ5HdWpr34tstg18rO"], 165 | minimum = [4, 6, 20], 166 | shares = [5, 100, 100]; 167 | 168 | for (var index in values) { 169 | var result = assertEqual(sssa.combine(sssa.create(minimum[index], shares[index], values[index])), values[index]); 170 | if (!result) { 171 | logger("Test failed: TestCreateCombine"); 172 | return false; 173 | } 174 | } 175 | 176 | var end = new Date(); 177 | logger("ok @ TestCreateCombine in " + ((end.getTime() - start.getTime())/1000) + "s"); 178 | return true; 179 | }, 180 | 181 | function() { 182 | var start = new Date(); 183 | 184 | var shares = ["U1k9koNN67-og3ZY3Mmikeyj4gEFwK4HXDSglM8i_xc=yA3eU4_XYcJP0ijD63Tvqu1gklhBV32tu8cHPZXP-bk=", "O7c_iMBaGmQQE_uU0XRCPQwhfLBdlc6jseTzK_qN-1s=ICDGdloemG50X5GxteWWVZD3EGuxXST4UfZcek_teng=", "8qzYpjk7lmB7cRkOl6-7srVTKNYHuqUO2WO31Y0j1Tw=-g6srNoWkZTBqrKA2cMCA-6jxZiZv25rvbrCUWVHb5g=", "wGXxa_7FPFSVqdo26VKdgFxqVVWXNfwSDQyFmCh2e5w=8bTrIEs0e5FeiaXcIBaGwtGFxeyNtCG4R883tS3MsZ0=", "j8-Y4_7CJvL8aHxc8WMMhP_K2TEsOkxIHb7hBcwIBOo=T5-EOvAlzGMogdPawv3oK88rrygYFza3KSki2q8WEgs="]; 185 | var result = assertEqual(sssa.combine(shares), "test-pass"); 186 | 187 | if (!result) { 188 | logger("Test failed: TestLibraryCombine"); 189 | return false; 190 | } 191 | var end = new Date(); 192 | 193 | logger("ok @ TestLibraryCombine in " + ((end.getTime() - start.getTime())/1000) + "s"); 194 | return true; 195 | } 196 | ]; 197 | 198 | for (var i in tests) { 199 | if (!tests[i]()) { 200 | return false; 201 | } 202 | } 203 | } 204 | 205 | main(); 206 | -------------------------------------------------------------------------------- /test/testing.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | REPL 5 | 6 | 7 | 8 | --------------------------------------------------------------------------------