www.scilab.org

Shamir's "How to share a Secret"

//////////////////////////////////////////////////////////////////////////////
//
//          Shamir's Secret Sharing demonstration (version 2008/11/10)
//
// Shamir A.,
// How to Share a Secret,
// Communications of the ACM, 22, 1979, pp. 612--613.
//
//                  Copyright (C) 2008 Christophe DAVID
//        http://www.christophedavid.org/w/c/w.php/Files/Security
//
//  This program is free software; you  can redistribute it and/or modify it
//  under the terms of the GNU General Public License version 2 as published
//  by the Free Software Foundation (http://www.gnu.org/licenses/gpl.html).
//
//////////////////////////////////////////////////////////////////////////////

//                This program was last tested with Scilab 4.1.2
//                            http://www.scilab.org

//////////////////////////////////////////////////////////////////////////////

// start reading at the very end of this file.

//////////////////////////////////////////////////////////////////////////////


errclear      // clear all errors
clear;        // kill variables
clearglobal   // kill global variables
clc;          // clear command window
tohome;       // move the cursor to the upper left corner of the Command Window
clf;          // clear or reset the current graphic figure (window) to default values
clear_pixmap; // erase the pixmap buffer


//////////////////////////////////////////////////////////////////////////////

function [ReturnValue] = FindMultipeBytesFmShares(SharesMatrix)
   // disp(SharesMatrix);
   ReturnValue = [];

   SizeOfSharesMatrix = size(SharesMatrix);

   X = SharesMatrix(:,1);
   // disp(X);

   for i = 2 : 1 : SizeOfSharesMatrix(1, 2);
      tmp(:, 1) =  X;  
      tmp(:, 2) =  SharesMatrix(:,i);
      //disp(tmp);
      ReturnValue(1, i - 1) = FindSingleByteFromShares(tmp);          
   end
endfunction

//////////////////////////////////////////////////////////////////////////////

function [ReturnValue] = FindSingleByteFromShares(SharesMatrix)
   //disp(SharesMatrix);

   SizeOfSharesMatrix = size(SharesMatrix);
   NumberOfShares     = SizeOfSharesMatrix(1, 1);

   CoefficientsMatrix = [];
   for i = 1 : 1 : NumberOfShares
      temp = 1;
      for j = 1 : 1 : NumberOfShares
         if (i <> j)
            temp = pmodulo(  (  (- temp)..
                             * SharesMatrix(j, 1)..
                             * ModuloPrimeInverse(  SharesMatrix(i, 1)..
                                                  - SharesMatrix(j, 1)..
                                                 )..
                            ),..
                          Prime..
                         );
         end
      end
      CoefficientsMatrix(1, i) = temp;
   end
   // disp(CoefficientsMatrix);

   ResultsMatrix = SharesMatrix(1:$, 2:2);
   //disp(ResultsMatrix);  

   ReturnValue = 0;
   for i = 1 : 1 : NumberOfShares
      ReturnValue = pmodulo(  (  ReturnValue..
                               + (   SharesMatrix(i, 2)..
                                   * CoefficientsMatrix(1, i)..
                                 )..
                             ),..
                           Prime..
                          );
   end
   //disp(ReturnValue);
endfunction

//////////////////////////////////////////////////////////////////////////////

function [ReturnValue] = ModuloPrimeInverse(InputValue)
   if InputValue < 0
      // ReturnValue = pmodulo((InversesMatrix(258 + InputValue)), Prime);      
      ReturnValue = pmodulo(InversesMatrix(258 + InputValue), Prime);
   else
      ReturnValue = InversesMatrix(InputValue + 1);
   end
   // printf("%d %d\n", InputValue, ReturnValue);
endfunction

//////////////////////////////////////////////////////////////////////////////

function [ReturnValue] = PolynomialFunction(CoefficientsMatrix, XMatrix)
   ReturnValue = 0;

   SizeOfCoefficientsMatrix = size(CoefficientsMatrix);
   SizeOfXMatrix            = size(XMatrix);
   NumberOfX                = SizeOfXMatrix(1,1);
   NumberOfCoefficients     = SizeOfCoefficientsMatrix(1, 2);

   for i = 1 : 1 : NumberOfX
      SubTotal = 0;
      for j = 1 : 1 : NumberOfCoefficients
        SubTotal = pmodulo( ( i  * XMatrix(i, 1)) +  CoefficientsMatrix(1, j),  Prime);
      end
   ReturnValue(i, 1) = SubTotal;
   end
endfunction

//////////////////////////////////////////////////////////////////////////////

function [ReturnValue] = PopulateInversesMatrix()
   ReturnValue = 0;

   x = 1;
   y = 1;
   ReturnValue(1) = 0;

   for i = 2 : 1 : Prime
      ReturnValue(x + 1) = y;
      x = pmodulo( 3 * x, Prime); //  3 is a generator of the ring Z/Z257
      y = pmodulo(86 * y, Prime); // 86 is the inverse of 3 modulo 257      
   end
   // disp(ReturnValue);
endfunction

//   0   1 129  86 193 103  43 147 225 200
// 180 187 150 178 202 120 241 121 100 230
//  90  49 222 190  75  72  89 238 101 195
//  60 199 249 148 189 235  50 132 115 145
//  45 163 153   6 111  40  95 175 166  21
//  36 126 173  97 119 243 179 248 226  61
//  30  59 228 102 253  87  74 234 223 149
// 246 181  25 169  66  24 186 247 201 244
// 151 165 210  96 205 127   3  65 184  26
//  20 209 176 152 216  46  83  53 139 135
//  18  28  63   5 215 164 177 245 188 224
// 250  44 218 116 124  38 113 134 159  54
//  15  17 158 140 114 220  51  85 255   2
// 172 206  37 143 117  99 240 242 203  98
// 123 144 219 133 141  39 213   7  33  69
//  12  80  93  42 252 194 229 239 122 118
// 204 174 211  41 105  81  48 237 231  73
// 192 254 130  52 161  47  92 106  13  56
//  10  71 233 191  88 232  76  11 108  34
//  23 183 170   4 155  29 198 227 196  31
//   9  78  14 138 160  84 131 221 236  91
//  82 162 217 146 251 104  94 212 112 142
// 125 207  22  68 109   8  58 197  62 156
//  19 168 185 182  67  35 208 167  27 157
// 136  16 137  55  79 107  70  77  57  32
// 110 214 154  64 171 128 256

//////////////////////////////////////////////////////////////////////////////

function [ReturnValue] = ShareMultipleBytes(MM, k, n)
   ReturnValue = (1:n);
   ReturnValue = ReturnValue';
   // disp(ReturnValue);  

   col = 2;
   for M = MM
      SingleByteShares = ShareSingleByte(M, k, n);
      //disp(SingleByteShares);
      for i = 1 : 1 : n
          ReturnValue(i, col) = SingleByteShares(i, 2);
      end
   col = col + 1;
   end
// disp(ReturnValue);  
endfunction


//////////////////////////////////////////////////////////////////////////////

function [ReturnValue] = ShareSingleByte(M, k, n)
   ReturnValue = 0;

   Coefficients       = rand(1, k - 1);
   Coefficients       = floor(Coefficients * Prime);

   Coefficients(1, k) = M;
   // disp(Coefficients);

   for i = 1 : 1 : n
      ReturnValue(i, 1) = i;
      ReturnValue(i, 2) = pmodulo(PolynomialFunction(Coefficients, i), Prime);
   end

   // disp(ReturnValue);

   if 1
      Polynomial         = "y = pmodulo((0";
      for i = 1 : 1 : k
         Polynomial      =   Polynomial + ' + ('  + string(Coefficients(1, i)) + '*(x**' + string(k-i) +  + '))';
      end
      Polynomial =   Polynomial + '), Prime)';
      // disp(Polynomial);
      deff("[y]=f(x)", Polynomial)
      fplot2d(0:Prime, f);
   end
endfunction

//////////////////////////////////////////////////////////////////////////////

function [ReturnValue] = WriteShares(SharesMatrix, k ,n)
   // disp(SharesMatrix);
   ReturnValue = [];

   SizeOfSharesMatrix = size(SharesMatrix);

   for row = 1 : 1 : SizeOfSharesMatrix(1, 1);
      ReturnValue(row) = sprintf("%02X%02X", SharesMatrix(row, 1), k);
      for col = 1 : 1 : SizeOfSharesMatrix(1, 2);
         if SharesMatrix(row, col) < 256
            PseudoHex = sprintf("%02X", SharesMatrix(row, col))
         else
            PseudoHex = 'G0'
         end
         ReturnValue(row) = ReturnValue(row) + PseudoHex;
      end
   end
endfunction


//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////

Prime          = 257;
InversesMatrix = PopulateInversesMatrix();


// Test PolynomialFunction
if 0
   X = [10; 20; 30];
   Coefficients = [2, 3, 4];
   test = PolynomialFunction(Coefficients, X);
end


// test ShareSingleByte
if 0
   M =  floor(rand() * 255);
   k =   3;
   n = 222;

   Shares = ShareSingleByte(M, k, n);
   //disp(Shares);

   if 0
      printf("\n");          
      for i = 1 : 1 : n
         printf("(:%d:%d:%d:)\n", k, Shares(i, 1), Shares(i, 2));
      end
   end  

   // solve first k shares
   // printf("\nM=%d, result=%d\n", M, FindSingleByteFromShares(Shares(1:k, 1:2)));          

   // solve last k shares
   printf("\nM=%d, result=%d\n", M, FindSingleByteFromShares(Shares(n-k+1:n, 1:2)));
end


// test ShareMultipleBytes
if 0
   k = 3;
   n = 5;
   SecretBytes = [3, 5, 7, 9, 11, 13, 15, 127, 256];
   Shares = ShareMultipleBytes(SecretBytes, k, n);
   // disp(Shares);
   recovered = FindMultipeBytesFmShares(Shares);
   disp(SecretBytes);
   disp(recovered);
end

// test ShareMultipleBytes - string
if 0
   k =   3;
   n = 255;
   SecretString = 'the quick brown fox jumps over the lazy dog';  
   disp(SecretString);

   SecretBytes = ascii(SecretString);
   Shares = ShareMultipleBytes(SecretBytes, k, n);
   // disp(Shares);

   if 0
      Txt = WriteShares(Shares);

      if 0
         Txt = [
                'E303E37CA2CE28DBF1';
                'F703F75027A5370B55';
                'D903D9B96FB75412B0';
               ];

         Shares = [];      
      end

      if 1
         FileName = '~/test/shares.txt';
         mdelete(FileName);
         f = file('open', FileName,'new');
         for i = 1 : 1 : n
            fprintf(f, "%s\n", Txt(i));
         end
         file('close', f);
      end


      SizeOfTxt = size(Txt);      
      for i = 1 : 1 : SizeOfTxt(1, 1);
         // printf("%s %d\n", txt(i), length(txt(1)));
         printf("%s\n", Txt(i));          
         A = strsplit(Txt(i), (2:2:length(Txt(i)) - 2));
         //  disp(A);

         SizeOfA = size(A);
         for j = 3 : 1 : SizeOfA(1, 1);          
            //disp(sscanf(A(j, 1), "%X"));        
            if A(j, 1) == 'G0'
               Shares(i, j - 2) = 256;
            else
               Shares(i, j - 2) = sscanf(A(j, 1), "%02X");
            end
         end
      end
   end

   //disp(Shares);


   recovered = ascii(FindMultipeBytesFmShares(Shares(1:k, 1:$)));
   disp(recovered);
end

/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////


// global test

if 1
   k =  3;                                               // number of shares required to reconstruct the secret
   n =  5;                                               // total number of shares
   SecretString = 'My secret';              
   disp(SecretString);                                   // the secret
   SecretBytes  = ascii(SecretString);
   Shares       = ShareMultipleBytes(SecretBytes, k, n);
   disp(WriteShares(Shares));                            // the shares    
   reconstructed   = ascii(FindMultipeBytesFmShares(Shares(1:k, 1:$))); // the secret, reconstructed
   disp(reconstructed);
end


//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////

<< Decision matrix analysis | index | >>

Google

 

Web

www.christophedavid.org