Open In App

Additive Secret Sharing and Share Proactivization – Using Python

Improve
Improve
Like Article
Like
Save
Share
Report

A Secret Sharing Scheme is a Cryptographic Scheme that involves the breaking up of a secret value into multiple fragments/shares in a manner that prevents a single shareholder from having complete knowledge of the original secret. Thus, the secret is divided into multiple shares and distributed among multiple participants. Therefore, the control over the secret value is distributed and not held by a single party. 
The simplest example of a Secret Sharing Scheme is Additive Secret Sharing which involves breaking a numeric secret into fragments that add up to the original secret. Once divided into shares, each share is distributed to different participants. None of the individual participants have enough information to reconstruct the secret. To reconstruct the secret, all participant must pool their shares together to reveal the original secret value.
 

Additive secret sharing

Fig 1: Division of a secret among three parties using Additive Sharing


Example 
Assume that the following conditions exist: 
 

  • The secret we want to divide is given by the value s = 12345
  • The number of participants in the system are n = 3. Thus, we need to obtain three shares, one for each party
  • When all parties pool and combine their shares, the secret is revealed


One arbitrary division of the secret might be: 12345 = 3512 + 2100 + 6733    . Thus, the first party is given a share with value 3512, the second party is given 2100 and the third party gets 6733. Clearly, unless all three parties pool their shares, the secret cannot be revealed. Such a scheme is called an n-out-of-n sharing scheme since all shares are required for secret reconstruction.
 

Additive Sharing over a Finite Field


Conventionally, the secret values and share values are bound to a finite field where all computations take place. All but the last shares, in such a scheme, are picked randomly, ensuring they belong to the chosen finite field. Assume (n-1) out of the total n shares are S(1), S(2), …, S(n-1). The final share is computed as S(n) = V – (S(1) + S(2) + … + S(n-1)) where V is the value of the original secret.
To recapitulate, we pick (n-1) random shares and compute the final share. 
 

Python3

import random
 
def getAdditiveShares(secret, N, fieldSize):
    '''Generate N additive shares from 'secret' in finite field of size 'fieldSize'.'''
 
    # Generate n-1 shares randomly
    shares = [random.randrange(fieldSize) for i in range(N-1)]
 
    # Append final share by subtracting all shares from secret
    # Modulo is done with fieldSize to ensure share is within finite field
    shares.append((secret - sum(shares)) % fieldSize )
    return shares
 
def reconstructSecret(shares, fieldSize):
    '''Regenerate secret from additive shares'''
    return sum(shares) % fieldSize
 
if __name__ == "__main__":
    # Generating the shares
    shares = getAdditiveShares(1234, 5, 10**5)
    print('Shares are:', shares)
     
    # Reconstructing the secret from shares
    print('Reconstructed secret:', reconstructSecret(shares, 10**5))

                    

Output: 
Shares are: [488, 62586, 9652, 49515, 78993]
Reconstructed secret: 1234

 

Proactivization of Additive Shares

Proactivization refers to the refreshing of the shares after fixed intervals to reduce the possibility of an attacker accessing the secret. It is assumed that an attacker can gain access to the shares held by any participant in some reasonable time. However, the compromise of a single share does not reveal the entire secret. As such, the attacker will have to compromise all the generated shares to gain access to the actual secret. This is where Proactivization comes into play. Using Proactivization, all shares are arbitrarily refreshed after a fixed interval such that the attacker may never have access to all of the most current shares. Thus, if the shares are refreshed at a rate such that the adversary only has access to just a subset of all shares at any given point, the scheme is protected from compromise.
The goal with Proactivization is to maintain the same key value yet to change its share representation. A new set of additive shares are generated after each lifecycle as follows: 
 

  1. Each additive share S(i) is subdivided into sub-fragments d(i, 1), d(i, 2), …, d(i, n) such the summation of all d(i, j) yields S(i) and n is the number of participants in the system 
     
  2. The sub-fragment d(i, j) is distributed by the owning party, i, to the party j. In this manner, all participants exchange their subfragments.
  3. To compute its refreshed share, party i adds the sub-fragments it received from all other participants as follows: {d(i)}^{new}={\sum_{j=1}^{n?}}{d(j, i)}


On closer observation, we see that each shareholder essentially performs additive sharing on their own shares and distributed the generated sub-shares among the participants. Subsequently, each participant adds up the received sub-shares. In this manner, the original secret is preserved while refreshing the shares held by the participants. 
 

Proactivization of Additive Shares

Fig 02: Additive shares are refreshed in Proactivization without altering the secret itself


 

Python3

# Additive Sharing with facility to Refresh shares via Proactivization
import random
 
def getAdditiveShares(secret, N, fieldSize):
    '''Generate N additive shares from 'secret' in finite field of size 'fieldSize'.'''
 
    # Generate n-1 shares randomly
    shares = [random.randrange(fieldSize) for i in range(N-1)]
    # Append final share by subtracting all shares from secret
    shares.append((secret - sum(shares)) % fieldSize )
    return shares
 
def reconstructSecret(shares, fieldSize):
    '''Regenerate secret from additive shares'''
    return sum(shares) % fieldSize
 
def proactivizeShares(shares):
    '''Refreshed shares by proactivization'''
     
    n = len(shares)
    refreshedShares = [0]*n
 
    for s in shares:
 
        # Divide each share into sub-fragments using additive sharing
        subShares = getAdditiveShares(s, n, 10**5)
 
        # Add subfragments of corresponding parties
        for p, sub in enumerate(subShares):
            refreshedShares[p] += sub
             
    return refreshedShares
 
if __name__ == "__main__":
    # Generating the shares
    shares = getAdditiveShares(1234, 5, 10**5)
    print('Shares are:', shares)
 
    # Running Proactivization
    newShares = proactivizeShares(shares)
    print('Refreshed Shares are:', newShares)
     
    # Reconstructing secret from refreshed shares
    print('Secret:', reconstructSecret(newShares, 10**5))

                    

Output: 
Shares are: [45142, 41833, 39277, 49009, 25973]
Refreshed Shares are: [298371, 255404, 117787, 239851, 189821]
Secret: 1234

 


Last Updated : 16 Jul, 2021
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads