3 <style type="text/css">
6 page-break-after: always;
28 border-width: 0 0 5px 0;
33 border: 1px solid black;
40 border: 1px solid gray;
41 display: inline-block;
52 <script type="text/javascript">
54 function e(e,t){return '<'+e+'>'+t+'</'+e+'>';} // html element with content t
55 function g(i){return document.getElementById(i);}
56 function h(i,t){g(i).innerHTML=t};
57 function v(i){return g(i).value;} // value of element with id
60 /* Split number into the shares */
61 function split(number, available, needed) {
62 var coef = [], x, exp, c, accum, shares = [];
63 for(c = 1, coef[0] = number; c < needed; c++) coef[c] = Math.floor(Math.random() * (prime - 1));
64 for(x = 1; x <= available; x++) {
65 for(exp = 1, accum = coef[0]; exp < needed; exp++) accum = (accum + (coef[exp] * (Math.pow(x, exp) % prime) % prime)) % prime;
66 shares[x - 1] = accum;
71 function share(index,string){
73 this.codes=string.split(' ');
74 this.codeCount=function(){return this.codes.length};
75 this.code=function(i){return this.codes[i];};
76 this.pick=function(i){return [this.index,this.codes[i]]};
77 this.string=function(){
78 return 'Share '+this.index+': '+this.codes.join(' / ');
83 var divs=document.getElementsByClassName('share');
84 var shares=[],lastValue,div,inputs,num;
85 for (i=0; i<divs.length; i++){
87 inputs = div.getElementsByTagName('input');
89 for (var j=0; j<inputs.length;j++){
90 var input = inputs[j];
91 if (input.className == 'num') {
94 lastValue=input.value;
95 if (num>0 && lastValue!='') shares[i]=new share(num,lastValue);
100 var clone=div.cloneNode(true);
101 var inputs=clone.getElementsByTagName('input');
102 for (var j=0; j<inputs.length; j++) inputs[j].value='';
103 div.parentNode.appendChild(clone);
109 if (b == 0) return [a, 1, 0];
111 var n = Math.floor(a/b), c = a % b, r = gcdD(b,c);
112 return [r[0], r[2], r[1]-r[2]*n];
116 function modInverse(k) {
118 var r = (k < 0) ? -gcdD(prime,-k)[2] : gcdD(prime,k)[2];
119 return (prime + r) % prime;
122 function join(shares) {
123 var accum, count, formula, startposition, nextposition, value, numerator, denominator;
124 for(formula = accum = 0; formula < shares.length; formula++) {
125 for(count = 0, numerator = denominator = 1; count < shares.length; count++) {
126 if(formula == count) continue; // If not the same value
127 startposition = shares[formula][0];
128 nextposition = shares[count][0];
129 numerator = (numerator * -nextposition) % prime;
130 denominator = (denominator * (startposition - nextposition)) % prime;
132 value = shares[formula][1];
133 accum = (prime + accum + (value * numerator * modInverse(denominator))) % prime;
139 var shares=collect(); // fetch shares
141 for (var i=0; i<shares.length; i++) codeCount=(codeCount==null)?shares[i].codeCount():Math.min(shares[i].codeCount(),codeCount);
142 var ascii=document.getElementById('ascii');
143 ascii.innerHTML='ascii: ';
144 result.innerHTML='Passphrase: ';
145 for (codeIndex=0; codeIndex<codeCount; codeIndex++){
147 for (var i=0; i<shares.length; i++){
148 shareSet[i]=shares[i].pick(codeIndex);
150 var r=join(shareSet);
151 ascii.innerHTML += r+' ';
152 result.innerHTML+= String.fromCharCode(r);
156 function secret2numbers(s){
157 var i,j,coef,n,x,sum;
158 var shares = v('shares');
159 var treshold = v('treshold');
161 var th=e('th','char');;
162 var ns=e('th','ascii');;
164 for (i=0; i<s.length;i++) {
170 for (j=1; j<treshold;j++) coef[j]=Math.floor(Math.random()*prime);
172 results[i]=split(n,shares,treshold);
175 var code=e('tr',th)+e('tr',ns);
176 var pages=g('pages');
177 var explanation=v('explanation').replace('%n',v('treshold')).replace(/\n/g,'<br/>');
179 for (j=0;j<shares;j++){
180 var line=e('th','share '+(j+1));
182 for (i=0;i<s.length;i++){
183 line+=e('td',results[i][j]);
184 page+=e('span',results[i][j]);
187 pages.innerHTML+=e('div', e('p',explanation)+e('p','Your share number: '+(j+1))+e('p',page) );
196 <legend>Decode secret from shares</legend>
199 Share #<input class="num" value="1" />: <input class="code" onkeyup="decode();"/>
206 <legend>Create shares from secret</legend>
207 Explanation to add:<br/>
208 <textarea id="explanation" name="explanation">
209 This document is a PART of a secret passphrase. At least %n of these secret parts are required to reconstruct the original passphrase.
210 In the event of (enter condition here), you may meet with other secret-part holders to unite your keys.
212 To obtain the secret phassphrase:
214 <li>collect at least %n secret shares</li>
215 <li>go to [url of this page]</li>
216 <li>enter the share number and the respective numbers separated by spaces</li>
218 The passphrase obtained will give you access to [insert description of secured thing here...].
222 Info: These secrets were generated using the "Shamir's Secret Sharing" algorithm.
224 Passphrase parts to generate: <input id="shares" value="5" /></br>
225 Minimum nuber of shares required to recreate secret: <input id="treshold" value="3" /></br>
226 Secret: <input name="secret" onkeyup="secret2numbers(this.value);" />
227 <table id="tab"></table>
229 <li>Set the explanation you want.</li>
230 <li>Enter the number of parts and shares you wish.</li>
231 <li>Enter your secret passphrase</li>
232 <li>Hit Ctrl+P or go to print via the menu</li>
235 <div id="pages"></div>