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 createElement(e,t){return '<'+e+'>'+t+'</'+e+'>';} // html element with content t
55 function getElement(i){return document.getElementById(i);}
56 function setHtmlOf(i,t){getElement(i).innerHTML=t};
57 function valueOfField(i){return getElement(i).value;} // value of element with id
60 return Math.floor(Math.random() * 256);
63 /* Split number into the shares */
64 function split(number, number_of_shares, needed) {
68 for(var coef_index = 1; coef_index < needed; coef_index++){
69 coef[coef_index] = rand256();
72 for(var share_number = 1; share_number <= number_of_shares; share_number++) {
74 for (var coef_index =0; coef_index<needed; coef_index++){
75 sum += coef[coef_index]*Math.pow(share_number,coef_index);
78 shares[share_number-1] = sum % prime;
83 function share(index,string){
85 this.codes=string.split(' ');
86 this.codeCount=function(){return this.codes.length};
87 this.code=function(i){return this.codes[i];};
88 this.pick=function(i){return [this.index,this.codes[i]]};
89 this.string=function(){
90 return 'Share '+this.index+': '+this.codes.join(' / ');
95 var divs=document.getElementsByClassName('share');
96 var shares=[],lastValue,div,inputs,num;
97 for (i=0; i<divs.length; i++){
99 inputs = div.getElementsByTagName('input');
101 for (var j=0; j<inputs.length;j++){
102 var input = inputs[j];
103 if (input.className == 'num') {
106 lastValue=input.value;
107 if (num>0 && lastValue!='') shares[i]=new share(num,lastValue);
112 var clone=div.cloneNode(true);
113 var inputs=clone.getElementsByTagName('input');
114 for (var j=0; j<inputs.length; j++) inputs[j].value='';
115 div.parentNode.appendChild(clone);
121 if (b == 0) return [a, 1, 0];
123 var n = Math.floor(a/b), c = a % b, r = gcdD(b,c);
124 return [r[0], r[2], r[1]-r[2]*n];
128 function modInverse(k) {
130 var r = (k < 0) ? -gcdD(prime,-k)[2] : gcdD(prime,k)[2];
131 return (prime + r) % prime;
134 function join(shares) {
135 var accum, count, formula, startposition, nextposition, value, numerator, denominator;
136 for(formula = accum = 0; formula < shares.length; formula++) {
137 for(count = 0, numerator = denominator = 1; count < shares.length; count++) {
138 if(formula == count) continue; // If not the same value
139 startposition = shares[formula][0];
140 nextposition = shares[count][0];
141 numerator = (numerator * -nextposition) % prime;
142 denominator = (denominator * (startposition - nextposition)) % prime;
144 value = shares[formula][1];
145 accum = (prime + accum + (value * numerator * modInverse(denominator))) % prime;
151 var shares=collect(); // fetch shares
153 for (var i=0; i<shares.length; i++) codeCount=(codeCount==null)?shares[i].codeCount():Math.min(shares[i].codeCount(),codeCount);
154 var ascii=document.getElementById('ascii');
155 ascii.innerHTML='ascii: ';
156 result.innerHTML='Passphrase: ';
157 for (codeIndex=0; codeIndex<codeCount; codeIndex++){
159 for (var i=0; i<shares.length; i++){
160 shareSet[i]=shares[i].pick(codeIndex);
162 var r=join(shareSet);
163 ascii.innerHTML += r+' ';
164 result.innerHTML+= String.fromCharCode(r);
168 function secret2numbers(string){
169 var string_pos,share_number,coef,char_code,x,sum;
170 var number_of_shares = valueOfField('shares');
171 var treshold = valueOfField('treshold');
174 // create table elements for displaying the shares
175 var char_cells = createElement('th','char');;
176 var char_code_cells = createElement('th','ascii');;
178 // decompose string, for each character create secrets from asccii code
179 for (string_pos=0; string_pos<string.length;string_pos++) {
180 char_code = string.charCodeAt(string_pos);
181 char_cells += createElement('td',string[string_pos]);
182 char_code_cells += createElement('td',char_code);
184 results[string_pos] = split(char_code,number_of_shares,treshold);
187 var code=createElement('tr',char_cells)+createElement('tr',char_code_cells);
188 var pages=getElement('pages');
189 var explanation=valueOfField('explanation').replace('%n',valueOfField('treshold')).replace(/\n/g,'<br/>');
191 for (share_number=0;share_number<number_of_shares;share_number++){
192 var line=createElement('th','share '+(share_number+1));
194 for (string_pos=0;string_pos<string.length;string_pos++){
195 line+=createElement('td',results[string_pos][share_number]);
196 page+=createElement('span',results[string_pos][share_number]);
198 code+=createElement('tr',line);
199 pages.innerHTML+=createElement('div', createElement('p',explanation)+createElement('p','Your share number: '+(share_number+1))+createElement('p',page) );
201 setHtmlOf('tab',code);
208 <legend>Decode secret from shares</legend>
211 Share #<input class="num" value="1" />: <input class="code" onkeyup="decode();"/>
218 <legend>Create shares from secret</legend>
219 Explanation to add:<br/>
220 <textarea id="explanation" name="explanation">
221 This document is a PART of a secret passphrase. At least %n of these secret parts are required to reconstruct the original passphrase.
222 In the event of (enter condition here), you may meet with other secret-part holders to unite your keys.
224 To obtain the secret phassphrase:
226 <li>collect at least %n secret shares</li>
227 <li>go to [url of this page]</li>
228 <li>enter the share number and the respective numbers separated by spaces</li>
230 The passphrase obtained will give you access to [insert description of secured thing here...].
234 Info: These secrets were generated using the "Shamir's Secret Sharing" algorithm.
236 Passphrase parts to generate: <input id="shares" value="5" /></br>
237 Minimum nuber of shares required to recreate secret: <input id="treshold" value="3" /></br>
238 Secret: <input name="secret" onkeyup="secret2numbers(this.value);" />
239 <table id="tab"></table>
241 <li>Set the explanation you want.</li>
242 <li>Enter the number of parts and shares you wish.</li>
243 <li>Enter your secret passphrase</li>
244 <li>Hit Ctrl+P or go to print via the menu</li>
247 <div id="pages"></div>