GithubHelp home page GithubHelp logo

shinji-san / secretsharingdotnet Goto Github PK

View Code? Open in Web Editor NEW
38.0 4.0 10.0 502 KB

An C# implementation of Shamir's Secret Sharing

License: MIT License

C# 100.00%
dotnet-core dotnet csharp csharp-library secret-sharing cryptography shamir-secret-sharing mit-license dotnet-framework

secretsharingdotnet's Introduction

SecretSharingDotNet

An C# implementation of Shamir's Secret Sharing.

Build & Test Status Of Default Branch

Status Solution Project Format .NET Version
Build status SecretSharingDotNet.sln SDK Standard 2.0
Standard 2.1
FX 4.6.2
FX 4.7
FX 4.7.1
FX 4.7.2
FX 4.8
.NET 6
.NET 7
.NET 8

NuGet

Supported Target Frameworks

Build And Test Status NuGet Version Git Tag Target Frameworks
SecretSharingDotNet NuGet NuGet Version 0.11.0 Tag Standard 2.0
Standard 2.1
FX 4.6.2
FX 4.7
FX 4.7.1
FX 4.7.2
FX 4.8
.NET 6
.NET 7
.NET 8

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.11.0 of the SecretSharingDotNet package:

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

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

    <ItemGroup>
      <PackageReference Include="SecretSharingDotNet" Version="0.11.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 completion of the command, look at the project file to make sure that the package is successfully 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.

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);
    }
  }
}

CLI building instructions

Prerequisites

For the following instructions, please make sure that you are connected to the internet. If necessary, NuGet will try to restore the xUnit packages.

If you start the unit tests on Linux, you must install the mono-complete package in case of the .NET Frameworks 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8 and 4.8.1. You can find the Mono installation instructions here.

The .NET Frameworks 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8 and 4.8.1 can be found here.

The .NET SDKs 6.0, 7.0 and 8.0 can be found here.

Build and test the solution

You can use the SecretSharingDotNet.sln solution file with the dotnet command to build the SecretSharingDotNet library in the Debug or Release configuration. You can also use the dotnet command to start the unit tests.

1. Restore NuGet packages

dotnet restore SecretSharingDotNet.sln

2. Build the solution

dotnet build -c Debug --no-restore SecretSharingDotNet.sln

or

dotnet build -c Release --no-restore SecretSharingDotNet.sln

3. Test the solution

dotnet test -c Debug --no-restore --no-build SecretSharingDotNet.sln -- RunConfiguration.TargetPlatform=x64 RunConfiguration.MaxCpuCount=1  xUnit.AppDomain=denied xUnit.ParallelizeAssembly=false xUnit.ParallelizeTestCollections=false

or

dotnet test -c Release --no-restore --no-build SecretSharingDotNet.sln -- RunConfiguration.TargetPlatform=x64 RunConfiguration.MaxCpuCount=1  xUnit.AppDomain=denied xUnit.ParallelizeAssembly=false xUnit.ParallelizeTestCollections=false

secretsharingdotnet's People

Contributors

dependabot[bot] avatar janniksam avatar nathanael-mtd avatar shinji-san avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

secretsharingdotnet's Issues

Reconstruction fails at random

The following function returns a double around 0.5, instead of 1 as would be expected:

static double TestShamir()
{
    int ok = 0;
    const int total = 1000;
    var sss = new ShamirsSecretSharing<BigInteger>(new ExtendedEuclideanAlgorithm<BigInteger>());
    var rng = new Random();
    for (int i = 0; i < total; i++)
    {
        var message = new byte[32];
        rng.NextBytes(message);
        const int n = 5;
        var secret = new Secret<BigInteger>(Convert.ToBase64String(message));
        var shares = sss.MakeShares((n + 1) / 2, n, secret);
        var reconstructed =
            Convert.FromBase64String(sss.Reconstruction(shares.Take((n + 1) / 2).ToArray())
                .ToBase64());
        if (message.SequenceEqual(reconstructed))
            ok++;
    }
    return (double) ok / total;
}

Bug with different numbers in secureLevel

Good times!

I am writing you a question, I do not understand why this code works correctly, it looks like a bug, but maybe I am not good at this subject
If you use different numbers in the secureLevel parameter, when i create variables split and combine

var gcd = new ExtendedEuclideanAlgorithm<BigInteger>();

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

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

var secret = shares.OriginalSecret.ToString();


var combine = new ShamirsSecretSharing<BigInteger>(gcd, 521);
var sh1 = shares[1].ToString();
var sh4 = shares[4].ToString();
var sh6 = shares[5].ToString();
var recoveredSecret = combine.Reconstruction(new []{sh1, sh4, sh6} );

**Update README.MD**

inform users about supported .Net Fx, Standard and Core versions provided by the SecretSharingDotNet NuGet package.

What about a v1

Is your feature request related to a problem? Please describe.
Looking at the releases we already have a long list of releases even going through different .NET versions, but the project having a <1.0 version makes it look like something new and untested. The project has automated tests, has a great changelog, already handled breaking changes, ...
Why not bump it up to a v1?

Describe the solution you'd like
Just bump it up to v1

Describe alternatives you've considered
The alternative https://www.nuget.org/packages/SecretSharing/ hasn't been updated since 2018 and only targets net461 (so no .NET core/6/7).

Additional context
Nothing else

Question about usage

Am I correct to assume that:

/// I can call this once in my program and reuse gcd for each different share I create?
var gcd = new ExtendedEuclideanAlgorithm();

/// This should be called for each different secret that I am going to share.
var split = new ShamirsSecretSharing(gcd);

/// This obviously is called for each different secret, but the above two are not obvious.
var shares = split.MakeShares(3, 7, "my secrect");

Performance?

Notice my posting on a closed issue regarding reusing the "sss = new ShamirsSecretSharing(gcd);". I figure this is a bug that you will want to address, and I am OK for now because making a new one every time seems to cure the slowness.

However, performance will be important for me and want to know if there are any optimizations available for my situation.

I am always doing splits that require all of the shares. I always do MakeShares(n,n,...).
n is generally < 10.
The secret is either a ToHexString(byte[32]) or a share.

I am wondering if there is an optimization I can take advantage of given that I am doing n of n splitting?
Maybe Shamir's is overkill for n of n?

**Create class as return type**

As developer I want a specific return type for the MakeShares functions of the ShamirsSecretSharing class to increase the usability.
The class contains the secret and the collection of shares.
Maybe this class implements IEquatable.

Build Instructions

Is your feature request related to a problem? Please describe.
How can I build this project from command line?

Describe the solution you'd like
Pls extends the README.MD with a section which describes the build commands.

.NET FX Workflow: 'GitHub Actions: Deprecating set-env and add-path commands'

Describe the bug
If I trigger the the .NET Framework workflow (see dotnetfx.yml), I will get the following failure for the step Setup NuGet.exe:

The add-path command is deprecated and will be disabled on November 16th. Please upgrade to using Environment Files. For more information see: https://github.blog/changelog/2020-10-01-github-actions-deprecating-set-env-and-add-path-commands/

Expected behavior
Step Setup NuGet.exe doesn't generate any warnings or errors.

Environment (please complete the following information):

To Reproduce
Trigger the .NET Framework workflow (see dotnetfx.yml).

Screenshots

Additional context

Maximum exceeded! (Parameter 'value') Actual value was 10912."

I am trying to send string to make share: 308201510201010420c6aec0586f4beae95eb9307dab9146aa71e35c5fa40f8cbdd79e122d860a303aa081e33081e0020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f3044042000000000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000000704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141020101a144034200044d173ba23c9596335ea4509c73ff9274b02dec7babbee0e09d80374715cab00389c1a552be908d522522ef4d5c21f10f68bef93a168ced732d577180d25b5147 It throws exception

Maximum exceeded! (Parameter 'value')
Actual value was 10912.

How to resolve this issue?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.