SecretSharingDotNet 0.8.0

.NET 6.0 .NET Core 3.1 .NET Standard 2.0 .NET Framework 4.6.2
Install-Package SecretSharingDotNet -Version 0.8.0
dotnet add package SecretSharingDotNet --version 0.8.0
<PackageReference Include="SecretSharingDotNet" Version="0.8.0" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add SecretSharingDotNet --version 0.8.0
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: SecretSharingDotNet, 0.8.0"
#r directive can be used in F# Interactive, C# scripting and .NET Interactive. Copy this into the interactive tool or source code of the script to reference the package.
// Install SecretSharingDotNet as a Cake Addin
#addin nuget:?package=SecretSharingDotNet&version=0.8.0

// Install SecretSharingDotNet as a Cake Tool
#tool nuget:?package=SecretSharingDotNet&version=0.8.0
The NuGet Team does not provide support for this client. Please contact its maintainers for support.

Setup

Install SecretSharingDotNet package

  1. Open a console and switch to the directory, containing your project file.

  2. Use the following command to install version 0.8.0 of the SecretSharingDotNet package:

    dotnet add package SecretSharingDotNet -v 0.8.0 -f <FRAMEWORK>
    
  3. After the completition of the command, look at the project file to make sure that the package is successfuly installed.

    You can open the .csproj file to see the added package reference:

    <ItemGroup>
      <PackageReference Include="SecretSharingDotNet" Version="0.8.0" />
    </ItemGroup>
    

Remove SecretSharingDotNet package

  1. Open a console and switch to the directory, containing your project file.

  2. Use the following command to remove the SecretSharingDotNet package:

    dotnet remove package SecretSharingDotNet
    
  3. After the completition of the command, look at the project file to make sure that the package is successfuly removed.

    You can open the .csproj file to check the deleted package reference.

Usage

Basics

Use the function MakeShares to generate the shares, based on a random or pre-defined secret. Afterwards, use the function Reconstruction to re-construct the original secret.

The length of the shares is based on the security level. It's possible to pre-define a security level by ctor or the SecurityLevel property. The pre-defined security level will be overriden, if the secret size is greater than the Mersenne prime, which is calculated by means of the security level. It is not necessary to define a security level for a re-construction.

Attention: Breaking change - Normal and legacy mode in v0.7.0

Library version 0.7.0 introduces a normal mode and a legacy mode for secrets. The normal mode is the new and default mode. The legacy mode is for backward compatibility.

Why was the normal mode introduced?

The normal mode supports positive secret values and also negative secret values like negative integer numbers or byte arrays with most significant byte greater than 0x7F. The legacy mode generates shares that can't be used to reconstruct negative secret values. So the original secret and the reconstructed secret aren't identical for negative secret values (e.g. BigInetger secret = -2000). The legacy mode only returns correct results for positive secret values.

Mode overview

  • Normal mode (Secret.LegacyMode.Value = false):
    • Shares generated with v0.7.0 or later cannot be used with v0.6.0 or earlier to reconstruct the secret.
    • Shares generated with v0.6.0 or earlier cannot be used with v0.7.0 or later to reconstruct the secret.
    • This mode supports security level 13 as minimum.
  • Legacy mode: (Secret.LegacyMode.Value = true):
    • Shares generated with v0.7.0 or later can be used with v0.6.0 or earlier to reconstruct the secret.
    • Shares generated with v0.6.0 or earlier can be used with v0.7.0 or later to reconstruct the secret.
    • This mode supports security level 5 as minimum.

A mixed mode is not possible. It is recommended to reconstruct the secret with the old procedure and to split again with the new procedure.

The legacy mode is thread-safe, but not task-safe.

For further details see the example below:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;

using SecretSharingDotNet.Cryptography;
using SecretSharingDotNet.Math;

namespace LegacyModeExample
{
  public class Program
  {
    public static void Main(string[] args)
    {
      //// Legacy mode on / normal mode off
      Secret.LegacyMode.Value = true
      try
      {
        var gcd = new ExtendedEuclideanAlgorithm<BigInteger>();

        var split = new ShamirsSecretSharing<BigInteger>(gcd);

        string password = "Hello World!!";
        
        var shares = split.MakeShares(3, 7, password);

        var combine = new ShamirsSecretSharing<BigInteger>(gcd);
        var subSet = shares.Where(p => p.X.IsEven).ToList();
        var recoveredSecret = combine.Reconstruction(subSet.ToArray());

      }
      finally
      {
        //// Legacy mode off / normal mode on
        Secret.LegacyMode.Value = false
      }
    }
  }
}

Random secret

Create a random secret in conjunction with the generation of shares. The length of the generated shares and of the secret are based on the security level. Here is an example with a pre-defined security level of 127:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;

using SecretSharingDotNet.Cryptography;
using SecretSharingDotNet.Math;

namespace Example1
{
  public class Program
  {
    public static void Main(string[] args)
    {
      var gcd = new ExtendedEuclideanAlgorithm<BigInteger>();

      //// Create Shamir's Secret Sharing instance with BigInteger
      var split = new ShamirsSecretSharing<BigInteger>(gcd);

      //// Minimum number of shared secrets for reconstruction: 3
      //// Maximum number of shared secrets: 7
      //// Security level: 127 (Mersenne prime exponent)
      var shares = split.MakeShares(3, 7, 127);

      //// The property 'shares.OriginalSecret' represents the random secret
      var secret = shares.OriginalSecret;

      //// Secret as big integer number
      Console.WriteLine((BigInteger)secret);

      //// Secret as base64 string
      Console.WriteLine(secret.ToBase64());

      //// The 'shares' instance contains the shared secrets
      var combine = new ShamirsSecretSharing<BigInteger>(gcd);
      var subSet1 = shares.Where(p => p.X.IsEven).ToList();
      var recoveredSecret1 = combine.Reconstruction(subSet1.ToArray());
      var subSet2 = shares.Where(p => !p.X.IsEven).ToList();
      var recoveredSecret2 = combine.Reconstruction(subSet2.ToArray());

      //// String representation of all shares
      Console.WriteLine(shares);

      //// 1st recovered secret as big integer number
      Console.WriteLine((BigInteger)recoveredSecret1);

      //// 2nd recovered secret as big integer number
      Console.WriteLine((BigInteger)recoveredSecret2);

      //// 1st recovered secret as base64 string
      Console.WriteLine(recoveredSecret1.ToBase64());

      //// 2nd recovered secret as base64 string
      Console.WriteLine(recoveredSecret2.ToBase64());
    }
  }
}

Pre-defined secret: text

Use a text as secret, which can be divided into shares. The length of the generated shares is based on the security level. Here is an example with auto-detected security level:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;

using SecretSharingDotNet.Cryptography;
using SecretSharingDotNet.Math;

namespace Example2
{
  public class Program
  {
    public static void Main(string[] args)
    {
      var gcd = new ExtendedEuclideanAlgorithm<BigInteger>();

      //// Create Shamir's Secret Sharing instance with BigInteger
      var split = new ShamirsSecretSharing<BigInteger>(gcd);

      string password = "Hello World!!";
      //// Minimum number of shared secrets for reconstruction: 3
      //// Maximum number of shared secrets: 7
      //// Attention: The password length can change the security level set by the ctor
      //// or SecurityLevel property.
      var shares = split.MakeShares(3, 7, password);

      //// The property 'shares.OriginalSecret' represents the original password
      var secret = shares.OriginalSecret;

      //// The 'shares' instance contains the shared secrets
      var combine = new ShamirsSecretSharing<BigInteger>(gcd);
      var subSet1 = shares.Where(p => p.X.IsEven).ToList();
      var recoveredSecret1 = combine.Reconstruction(subSet1.ToArray());
      var subSet2 = shares.Where(p => !p.X.IsEven).ToList();
      var recoveredSecret2 = combine.Reconstruction(subSet2.ToArray());

      //// String representation of all shares
      Console.WriteLine(shares);

      //// 1st recovered secret as string (not base64!)
      Console.WriteLine(recoveredSecret1);

      //// 2nd recovered secret as string (not base64!)
      Console.WriteLine(recoveredSecret2);
    }
  }
}

Pre-defined secret: number

Use an integer number as secret, which can be divided into shares. The length of the generated shares is based on the security level. Here is an example with a pre-defined security level of 521:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;

using SecretSharingDotNet.Cryptography;
using SecretSharingDotNet.Math;

namespace Example3
{
  public class Program
  {
    public static void Main(string[] args)
    {
      var gcd = new ExtendedEuclideanAlgorithm<BigInteger>();

      //// Create Shamir's Secret Sharing instance with BigInteger
      //// and 
      var split = new ShamirsSecretSharing<BigInteger>(gcd);

      BigInteger number = 20000;
      //// Minimum number of shared secrets for reconstruction: 3
      //// Maximum number of shared secrets: 7
      //// Security level: 521 (Mersenne prime exponent)
      //// Attention: The size of the number can change the security level set by the ctor
      //// or SecurityLevel property.
      var shares = split.MakeShares (3, 7, number, 521);

      //// The property 'shares.OriginalSecret' represents the number (original secret)
      var secret = shares.OriginalSecret;

      ////  The 'shares' instance contains the shared secrets
      var combine = new ShamirsSecretSharing<BigInteger>(gcd);
      var subSet1 = shares.Where(p => p.X.IsEven).ToList();
      var recoveredSecret1 = combine.Reconstruction(subSet1.ToArray());
      var subSet2 = shares.Where(p => !p.X.IsEven).ToList();
      var recoveredSecret2 = combine.Reconstruction(subSet2.ToArray());

      //// String representation of all shares
      Console.WriteLine(shares);

      //// 1st recovered secret as big integer number
      Console.WriteLine((BigInteger)recoveredSecret1);

      //// 2nd recovered secret as big integer number
      Console.WriteLine((BigInteger)recoveredSecret2);
    }
  }
}

Pre-defined secret: byte array

Use a byte array as secret, which can be divided into shares. The length of the generated shares is based on the security level. Here is an example with auto-detected security level:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;

using SecretSharingDotNet.Cryptography;
using SecretSharingDotNet.Math;

namespace Example4
{
  public class Program
  {
    public static void Main(string[] args)
    {
      var gcd = new ExtendedEuclideanAlgorithm<BigInteger>();

      //// Create Shamir's Secret Sharing instance with BigInteger
      var split = new ShamirsSecretSharing<BigInteger>(gcd);

      byte[] bytes = { 0x1D, 0x2E, 0x3F };
      //// Minimum number of shared secrets for reconstruction: 4
      //// Maximum number of shared secrets: 10
      //// Attention: The password length changes the security level set by the ctor
      var shares = split.MakeShares(4, 10, bytes);

      //// The 'shares' instance contains the shared secrets
      var combine = new ShamirsSecretSharing<BigInteger>(gcd);
      var subSet = shares.Where(p => p.X.IsEven).ToList();
      var recoveredSecret = combine.Reconstruction(subSet.ToArray()).ToByteArray();

      //// String representation of all shares
      Console.WriteLine(shares);

      //// The secret bytes.
      Console.WriteLine($"{recoveredSecret[0]:X2}, {recoveredSecret[1]:X2}, {recoveredSecret[2]:X2}");
    }
  }
}

Shares

The following example shows three ways to use shares to reconstruct a secret:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;

using SecretSharingDotNet.Cryptography;
using SecretSharingDotNet.Math;

namespace Example5
{
  public class Program
  {
    public static void Main(string[] args)
    {
      var gcd = new ExtendedEuclideanAlgorithm<BigInteger>();

      //// One way to use shares
      string shares1 = "02-665C74ED38FDFF095B2FC9319A272A75" + Environment.NewLine +
                       "05-CDECB88126DBC04D753E0C2D83D7B55D" + Environment.NewLine +
                       "07-54A83E34AB0310A7F5D80F2A68FD4F33";

      //// A 2nd way to use shares
      string[] shares2 = {"02-665C74ED38FDFF095B2FC9319A272A75",
                          "07-54A83E34AB0310A7F5D80F2A68FD4F33",
                          "05-CDECB88126DBC04D753E0C2D83D7B55D"};

      //// Another way to use shares
      var fp1 = new FinitePoint<BigInteger>("05-CDECB88126DBC04D753E0C2D83D7B55D");
      var fp2 = new FinitePoint<BigInteger>("07-54A83E34AB0310A7F5D80F2A68FD4F33");
      var fp3 = new FinitePoint<BigInteger>("02-665C74ED38FDFF095B2FC9319A272A75");

      var combine = new ShamirsSecretSharing<BigInteger>(gcd);
 
      var recoveredSecret1 = combine.Reconstruction(shares1);
      //// Output should be 52199147989510990914370102003412153
      Console.WriteLine((BigInteger)recoveredSecret1);

      var recoveredSecret2 = combine.Reconstruction(shares2);
      //// Output should be 52199147989510990914370102003412153
      Console.WriteLine((BigInteger)recoveredSecret2);

      //// Output should be 52199147989510990914370102003412153
      var recoveredSecret3 = combine.Reconstruction(fp1, fp2, fp3);
      Console.WriteLine((BigInteger)recoveredSecret3);
    }
  }
}
Product Versions
.NET net5.0 net5.0-windows net6.0 net6.0-android net6.0-ios net6.0-maccatalyst net6.0-macos net6.0-tvos net6.0-windows
.NET Core netcoreapp2.0 netcoreapp2.1 netcoreapp2.2 netcoreapp3.0 netcoreapp3.1
.NET Standard netstandard2.0 netstandard2.1
.NET Framework net461 net462 net463 net47 net471 net472 net48
MonoAndroid monoandroid
MonoMac monomac
MonoTouch monotouch
Tizen tizen40 tizen60
Xamarin.iOS xamarinios
Xamarin.Mac xamarinmac
Xamarin.TVOS xamarintvos
Xamarin.WatchOS xamarinwatchos
Compatible target framework(s)
Additional computed target framework(s)
Learn more about Target Frameworks and .NET Standard.
  • .NETCoreApp 3.1

    • No dependencies.
  • .NETFramework 4.6.2

    • No dependencies.
  • .NETFramework 4.7

    • No dependencies.
  • .NETFramework 4.7.1

    • No dependencies.
  • .NETFramework 4.7.2

    • No dependencies.
  • .NETFramework 4.8

    • No dependencies.
  • .NETStandard 2.0

    • No dependencies.
  • .NETStandard 2.1

    • No dependencies.
  • net6.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
0.8.0 168 7/5/2022
0.7.0 1,661 2/8/2022
0.6.0 3,673 11/25/2021
0.5.0 257 10/7/2021
0.4.2 1,565 12/18/2020
0.3.0 443 4/19/2020
0.2.0 351 4/12/2020
0.1.1 349 4/10/2020

Removed .NET 5 support. Added localization for exception messages in English and German. Add new overloads for the MakeShares method. Mark some ctors, properties and methods as deprecated.