diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 70f14f5..2cac28b 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -13,10 +13,10 @@ name: "CodeQL" on: push: - branches: [ develop, main, master ] + branches: [ develop, main ] pull_request: # The branches below must be a subset of the branches above - branches: [ develop ] + branches: [ develop, main ] schedule: - cron: '18 17 * * 4' diff --git a/CHANGELOG.md b/CHANGELOG.md index c7f0d0c..3801f7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,140 +1,181 @@ -# Changelog -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - -## [0.8.0] - 2022-07-05 -### Added -- Added more examples in the section *Usage* of the `README.md` file to explain the use of shares and the use of the new type casting from byte array to secret and vice versa. -- Added method `MakeShares(TNumber numberOfMinimumShares, TNumber numberOfShares, int securityLevel)` -- Added method `MakeShares(TNumber numberOfMinimumShares, TNumber numberOfShares, Secret secret, int securityLevel)` -- Added localization for exception messages in English and German languages - -### Changed -- Changed existing examples in the section *Usage* of the `README.md` file to explain the use and the type casting of recovered secrets. -- Minify NuGet package README.md -- Changed ctor `ShamirsSecretSharing(IExtendedGcdAlgorithm extendedGcd)`. This ctor sets the SecurityLevel to 13. - -### Deprecated -- Ctor `ShamirsSecretSharing(IExtendedGcdAlgorithm extendedGcd, int securityLevel)` is deprecated. -- Method `MakeShares(TNumber numberOfMinimumShares, TNumber numberOfShares)` is deprecated. -- Shares to tuple type casting is obsolete and will be remove in the next release. -- Shares.Item1 property is obsolete and will be remove in the next release. -- Shares.Item2 property is obsolete and will be remove in the next release. - -### Removed -- Removed .NET 5 support, because it retires on May 10, 2022. See [Microsoft .NET and .NET Core - Support Dates](https://docs.microsoft.com/en-us/lifecycle/products/microsoft-net-and-net-core). - -## [0.7.0] - 2022-02-09 -### Added -- Added implicit casts for byte arrays in *Secret* class. -- Added legacy mode. See README.md, section "Usage" for more details. - -### Changed -- Changed behavior of *Secret* class for negative secret values. See README.md, section "Usage" and bug report [#60](https://github.com/shinji-san/SecretSharingDotNet/issues/60) for more details. -- Changed calculation of maximum security level in Reconstruction method. - -### Fixed -- Fixed reopened bug [#60](https://github.com/shinji-san/SecretSharingDotNet/issues/60) "Reconstruction fails at random". -- Fixed assembly output path in `SecretSharingDotNetFx4.6.2.csproj` - -### Removed -- Removed .NET FX 4.5.2 support, because it retires on April 26, 2022. See [.NET FX Lifecycle Policy](https://docs.microsoft.com/en-us/lifecycle/products/microsoft-net-framework). -- Removed .NET FX 4.6 support, because it retires on April 26, 2022. See [.NET FX Lifecycle Policy](https://docs.microsoft.com/en-us/lifecycle/products/microsoft-net-framework). -- Removed .NET FX 4.6.1 support, because it retires on April 26, 2022. See [.NET FX Lifecycle Policy](https://docs.microsoft.com/en-us/lifecycle/products/microsoft-net-framework). - -## [0.6.0] - 2021-11-25 -### Added -- Add .NET 6 support - -### Changed -- Use RandomNumberGenerator class instead RNGCryptoServiceProvider class to create the polynomial. For details see dotnet runtime issue [40169](https://github.com/dotnet/runtime/issues/40169) - -### Fixed -- Fixed bug [#60](https://github.com/shinji-san/SecretSharingDotNet/issues/60) "Reconstruction fails at random" which occurs when the secret is created from a base64 string - -### Removed -- Removed .NET Core 2.1 (LTS) support - -## [0.5.0] - 2021-10-07 -### Added -- Introduced a new return type for the split method 'MakeShares' -- Added CLI building instructions in README.md - -### Changed -- Updated examples in README.md based on the new return type for the split method -- Updated xUnit package references in CSharp projects -- Updated Microsoft Test SDK package references in CSharp projects -- Updated Mircosoft .NET FX reference assemblies package references in CSharp projects - -### Deprecated -- The tuple return type for the split method 'MakeShares' is obsolete - -### Fixed -- Fixed CI version dependency -- Fixed code quality issues in CSharp code -- Fixed spelling mistakes in README.md -- Fixed .NET 5 solution filename in README.md -- Added missing target framework .NET 5 to SecretSharingDotNetTest.csproj - -## [0.4.2] - 2020-12-18 -### Fixed -- Fixed wrong NuGet package version - -## [0.4.1] - 2020-12-18 -### Fixed -- NuGet build environment modified to build for .NET 5.0 - -## [0.4.0] - 2020-12-18 -### Added -- Added .NET 5.0 support - -### Fixed -- Fixed bug 40 (_Maximum exceeded!_) reported [@varshadqz](https://github.com/shinji-san/SecretSharingDotNet/issues/40) - -## [0.3.0] - 2020-04-19 -### Added -- Added .NET FX 4.6 support -- Added .NET FX 4.6.1 support -- Added .NET FX 4.6.2 support -- Added .NET FX 4.7 support -- Added .NET FX 4.7.1 support -- Added .NET FX 4.7.2 support -- Added .NET FX 4.8 support -- Added .NET Standard 2.1 support - -### Changed -- README.md: Extend build & test status corresponding to the .NET versions - -## [0.2.0] - 2020-04-12 -### Added -- Addded full .NET Core 3.1 support - -## [0.1.1] - 2020-04-11 -### Fixed -- Fixed wrong NuGet package version - -## [0.1.0] - 2020-04-11 -### Added -- Added initial verion of SecretSharingDotNet -- Added .NET FX 4.5.2 support -- Added .NET Core 2.1 support -- Added limited .NET Core 3.1 support -- Added GitHub issue template -- Added CODE_OF_CONDUCT.md -- Added LICENSE.md -- Added README.md - -[Unreleased]: https://github.com/shinji-san/SecretSharingDotNet/compare/v0.8.0...HEAD -[0.8.0]: https://github.com/shinji-san/SecretSharingDotNet/compare/v0.7.0...v0.8.0 -[0.7.0]: https://github.com/shinji-san/SecretSharingDotNet/compare/v0.6.0...v0.7.0 -[0.6.0]: https://github.com/shinji-san/SecretSharingDotNet/compare/v0.5.0...v0.6.0 -[0.5.0]: https://github.com/shinji-san/SecretSharingDotNet/compare/v0.4.2...v0.5.0 -[0.4.2]: https://github.com/shinji-san/SecretSharingDotNet/compare/v0.4.1...v0.4.2 -[0.4.1]: https://github.com/shinji-san/SecretSharingDotNet/compare/v0.4.0...v0.4.1 -[0.4.0]: https://github.com/shinji-san/SecretSharingDotNet/compare/v0.3.0...v0.4.0 -[0.3.0]: https://github.com/shinji-san/SecretSharingDotNet/compare/v0.2.0...v0.3.0 -[0.2.0]: https://github.com/shinji-san/SecretSharingDotNet/compare/v0.1.1...v0.2.0 -[0.1.1]: https://github.com/shinji-san/SecretSharingDotNet/compare/v0.1.0...v0.1.1 -[0.1.0]: https://github.com/shinji-san/SecretSharingDotNet/releases/tag/v0.1.0 +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [0.9.0] - 2022-10-09 +### Added +- Add `ToInt32()` method to `BigIntCalculator` and `Calculator` class. +- Introduce the `IExtendedGcdResult` interface to decouple GCD result implementations. + +### Changed +- Moved generic version of the `Calculator` class from the `Calculator.cs` file to the ``Calculator`1.cs`` file. +- Updated `Microsoft.NET.Test.Sdk` Nuget package version to 17.2.0. +- Updated `xunit.runner.visualstudio` Nuget package version to 2.4.5. +- Set `Calculator` fields `ChildTypes` and `ChildBaseCtors` from protected to private. +- Performance improvements for `ShamirsSecretSharing` classes. +- Performance improvements for `FinitePoint` class. +- Performance improvements for generic `Calculator` class. + +### Deprecated +- Ctor `ShamirsSecretSharing(IExtendedGcdAlgorithm extendedGcd, int securityLevel)` is deprecated. +- Method `MakeShares(TNumber numberOfMinimumShares, TNumber numberOfShares)` is deprecated. + +### Fixed +- Fixed style guide violations in `CHANGELOG.md`. +- Fixed style guide violations in `FinitePoint.cs`. +- Fixed style guide violations in `Shares.cs`. +- Fixed style guide violations in `SharesEnumerator.cs`. +- Fixed style guide violations in ``IExtendedGcdAlgorithm`2.cs``. +- Fixed style guide violations in `ExtendedEuclideanAlgorithm.cs`. +- Fixed style guide violations in `Calculator.cs`. +- Fixed style guide violations in ``Calculator`1.cs``. +- Fixed style guide violations in `BigIntCalculator.cs`. +- Fixed style guide violations in `Secret.cs`. Split file into `Secret.cs` and ``Secret`1.cs``. +- Fixed possible null reference exception in `Calculator` class. +- Fixed possible null reference exception in `Shares` class. +- Fixed possible null reference exception in `ShamirsSecretSharing` class. +- Fixed unnecessary boxing/unboxing in the `ToString()` methods in `Calculator` classes. + +### Removed +- Removed constructor w/ `ReadOnlyCollection` parameter from the `SharesEnumerator{TNumber}` class. +- Removed tuple type casting from the `Shares` class. +- Removed `Shares.Item1` property. +- Removed `Shares.Item2` property. + +## [0.8.0] - 2022-07-05 +### Added +- Added more examples in the section *Usage* of the `README.md` file to explain the use of shares and the use of the new type casting from byte array to secret and vice versa. +- Added method `MakeShares(TNumber numberOfMinimumShares, TNumber numberOfShares, int securityLevel)` +- Added method `MakeShares(TNumber numberOfMinimumShares, TNumber numberOfShares, Secret secret, int securityLevel)` +- Added localization for exception messages in English and German languages + +### Changed +- Changed existing examples in the section *Usage* of the `README.md` file to explain the use and the type casting of recovered secrets. +- Minify NuGet package `README.md` +- Changed ctor `ShamirsSecretSharing(IExtendedGcdAlgorithm extendedGcd)`. This ctor sets the SecurityLevel to 13. + +### Deprecated +- Ctor `ShamirsSecretSharing(IExtendedGcdAlgorithm extendedGcd, int securityLevel)` is deprecated. +- Method `MakeShares(TNumber numberOfMinimumShares, TNumber numberOfShares)` is deprecated. +- Shares to tuple type casting is obsolete and will be remove in the next release. +- `Shares.Item1` property is obsolete and will be remove in the next release. +- `Shares.Item2` property is obsolete and will be remove in the next release. + +### Removed +- Removed .NET 5 support, because it retires on May 10, 2022. See [Microsoft .NET and .NET Core - Support Dates](https://docs.microsoft.com/en-us/lifecycle/products/microsoft-net-and-net-core). + +## [0.7.0] - 2022-02-09 +### Added +- Added implicit casts for byte arrays in *Secret* class. +- Added legacy mode. See `README.md`, section "Usage" for more details. + +### Changed +- Changed behavior of *Secret* class for negative secret values. See `README.md`, section "Usage" and bug report [#60](https://github.com/shinji-san/SecretSharingDotNet/issues/60) for more details. +- Changed calculation of maximum security level in Reconstruction method. + +### Fixed +- Fixed reopened bug [#60](https://github.com/shinji-san/SecretSharingDotNet/issues/60) "Reconstruction fails at random". +- Fixed assembly output path in `SecretSharingDotNetFx4.6.2.csproj` + +### Removed +- Removed .NET FX 4.5.2 support, because it retires on April 26, 2022. See [.NET FX Lifecycle Policy](https://docs.microsoft.com/en-us/lifecycle/products/microsoft-net-framework). +- Removed .NET FX 4.6 support, because it retires on April 26, 2022. See [.NET FX Lifecycle Policy](https://docs.microsoft.com/en-us/lifecycle/products/microsoft-net-framework). +- Removed .NET FX 4.6.1 support, because it retires on April 26, 2022. See [.NET FX Lifecycle Policy](https://docs.microsoft.com/en-us/lifecycle/products/microsoft-net-framework). + +## [0.6.0] - 2021-11-25 +### Added +- Add .NET 6 support + +### Changed +- Use `RandomNumberGenerator` class instead `RNGCryptoServiceProvider` class to create the polynomial. For details see dotnet runtime issue [40169](https://github.com/dotnet/runtime/issues/40169) + +### Fixed +- Fixed bug [#60](https://github.com/shinji-san/SecretSharingDotNet/issues/60) "Reconstruction fails at random" which occurs when the secret is created from a base64 string + +### Removed +- Removed .NET Core 2.1 (LTS) support + +## [0.5.0] - 2021-10-07 +### Added +- Introduced a new return type for the split method 'MakeShares' +- Added CLI building instructions in `README.md` + +### Changed +- Updated examples in `README.md` based on the new return type for the split method +- Updated xUnit package references in CSharp projects +- Updated Microsoft Test SDK package references in CSharp projects +- Updated Microsoft .NET FX reference assemblies package references in CSharp projects + +### Deprecated +- The tuple return type for the split method 'MakeShares' is obsolete + +### Fixed +- Fixed CI version dependency +- Fixed code quality issues in CSharp code +- Fixed spelling mistakes in `README.md` +- Fixed .NET 5 solution filename in `README.md` +- Added missing target framework .NET 5 to `SecretSharingDotNetTest.csproj` + +## [0.4.2] - 2020-12-18 +### Fixed +- Fixed wrong NuGet package version + +## [0.4.1] - 2020-12-18 +### Fixed +- NuGet build environment modified to build for .NET 5.0 + +## [0.4.0] - 2020-12-18 +### Added +- Added .NET 5.0 support + +### Fixed +- Fixed bug 40 (_Maximum exceeded!_) reported [@varshadqz](https://github.com/shinji-san/SecretSharingDotNet/issues/40) + +## [0.3.0] - 2020-04-19 +### Added +- Added .NET FX 4.6 support +- Added .NET FX 4.6.1 support +- Added .NET FX 4.6.2 support +- Added .NET FX 4.7 support +- Added .NET FX 4.7.1 support +- Added .NET FX 4.7.2 support +- Added .NET FX 4.8 support +- Added .NET Standard 2.1 support + +### Changed +- `README.md`: Extend build & test status corresponding to the .NET versions + +## [0.2.0] - 2020-04-12 +### Added +- Added full .NET Core 3.1 support + +## [0.1.1] - 2020-04-11 +### Fixed +- Fixed wrong NuGet package version + +## [0.1.0] - 2020-04-11 +### Added +- Added initial version of SecretSharingDotNet +- Added .NET FX 4.5.2 support +- Added .NET Core 2.1 support +- Added limited .NET Core 3.1 support +- Added GitHub issue template +- Added `CODE_OF_CONDUCT.md` +- Added `LICENSE.md` +- Added `README.md` + +[Unreleased]: https://github.com/shinji-san/SecretSharingDotNet/compare/v0.9.0...HEAD +[0.9.0]: https://github.com/shinji-san/SecretSharingDotNet/compare/v0.8.0...v0.9.0 +[0.8.0]: https://github.com/shinji-san/SecretSharingDotNet/compare/v0.7.0...v0.8.0 +[0.7.0]: https://github.com/shinji-san/SecretSharingDotNet/compare/v0.6.0...v0.7.0 +[0.6.0]: https://github.com/shinji-san/SecretSharingDotNet/compare/v0.5.0...v0.6.0 +[0.5.0]: https://github.com/shinji-san/SecretSharingDotNet/compare/v0.4.2...v0.5.0 +[0.4.2]: https://github.com/shinji-san/SecretSharingDotNet/compare/v0.4.1...v0.4.2 +[0.4.1]: https://github.com/shinji-san/SecretSharingDotNet/compare/v0.4.0...v0.4.1 +[0.4.0]: https://github.com/shinji-san/SecretSharingDotNet/compare/v0.3.0...v0.4.0 +[0.3.0]: https://github.com/shinji-san/SecretSharingDotNet/compare/v0.2.0...v0.3.0 +[0.2.0]: https://github.com/shinji-san/SecretSharingDotNet/compare/v0.1.1...v0.2.0 +[0.1.1]: https://github.com/shinji-san/SecretSharingDotNet/compare/v0.1.0...v0.1.1 +[0.1.0]: https://github.com/shinji-san/SecretSharingDotNet/releases/tag/v0.1.0 diff --git a/README.md b/README.md index bd1dd03..75be9cb 100644 --- a/README.md +++ b/README.md @@ -74,9 +74,9 @@ An C# implementation of Shamir's Secret Sharing. - SecretSharingDotNet NuGet - NuGet Version 0.8.0 - Tag + SecretSharingDotNet NuGet + NuGet Version 0.9.0 + Tag Core 3.1 (LTS) @@ -110,10 +110,10 @@ An C# implementation of Shamir's Secret Sharing. 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: +2. Use the following command to install version 0.9.0 of the SecretSharingDotNet package: ```dotnetcli - dotnet add package SecretSharingDotNet -v 0.8.0 -f + dotnet add package SecretSharingDotNet -v 0.9.0 -f ``` 3. After the completition of the command, look at the project file to make sure that the package is successfuly installed. @@ -122,7 +122,7 @@ An C# implementation of Shamir's Secret Sharing. ```xml - + ``` ## Remove SecretSharingDotNet package diff --git a/src/Cryptography/FinitePoint.cs b/src/Cryptography/FinitePoint.cs index 8d9a359..327aabb 100644 --- a/src/Cryptography/FinitePoint.cs +++ b/src/Cryptography/FinitePoint.cs @@ -57,9 +57,10 @@ namespace SecretSharingDotNet.Cryptography /// /// Initializes a new instance of the struct. /// - /// X coordinate as known as share index - /// Polynomial + /// The x-coordinate as known as share index + /// The polynomial /// The prime number given by the security level. + /// One or more of the parameters , or are [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "x")] public FinitePoint(Calculator x, ICollection> polynomial, Calculator prime) { @@ -79,8 +80,8 @@ public FinitePoint(string serialized) throw new ArgumentNullException(nameof(serialized)); } - var s = serialized.Split('-'); - Type numberType = typeof(TNumber); + string[] s = serialized.Split('-'); + var numberType = typeof(TNumber); this.x = Calculator.Create(ToByteArray(s[0]), numberType) as Calculator; this.y = Calculator.Create(ToByteArray(s[1]), numberType) as Calculator; } @@ -111,58 +112,54 @@ public FinitePoint(Calculator x, Calculator y) public Calculator Y => this.y; /// - /// + /// Equality operator /// - /// - /// - /// + /// The left operand + /// The right operand + /// Returns if its operands are equal, otherwise . public static bool operator ==(FinitePoint left, FinitePoint right) => left.Equals(right); /// - /// + /// Inequality operator /// - /// - /// - /// + /// The left operand + /// The right operand + /// Returns if its operands are not equal, otherwise . public static bool operator !=(FinitePoint left, FinitePoint right) => !left.Equals(right); /// - /// + /// Greater than operator /// - /// - /// - /// + /// The 1st operand + /// The 2nd operand + /// Returns if its 1st operand is greater than its 2nd operand, otherwise . public static bool operator >(FinitePoint left, FinitePoint right) => left.CompareTo(right) == 1; /// - /// + /// Less than operator /// - /// - /// - /// + /// The 1st operand + /// The 2nd operand + /// Returns if its 1st operand is less than its 2nd operand, otherwise . public static bool operator <(FinitePoint left, FinitePoint right) => left.CompareTo(right) == -1; /// - /// + /// Greater than or equal operator /// - /// - /// - /// + /// The 1st operand + /// The 2nd operand + /// Returns if its 1st operand is greater than or equal to its 2nd operand, otherwise . public static bool operator >=(FinitePoint left, FinitePoint right) => left.CompareTo(right) >= 0; /// - /// + /// Less than or equal operator /// - /// - /// - /// + /// The 1st operand + /// The 2nd operand + /// Returns if its 1st operand is less than or equal to its 2nd operand, otherwise . public static bool operator <=(FinitePoint left, FinitePoint right) => left.CompareTo(right) <= 0; - /// - /// - /// - /// - /// + /// public int CompareTo(FinitePoint other) { return ((this.X.Pow(2) + this.Y.Pow(2)).Sqrt - (other.X.Pow(2) + other.Y.Pow(2)).Sqrt).Sign; @@ -204,13 +201,20 @@ public override bool Equals(object obj) /// /// Evaluates polynomial (coefficient tuple) at x, used to generate a shamir pool. /// - /// - /// + /// The polynomial + /// The x-coordinate /// Mersenne prime greater or equal 5 - /// + /// y-coordinate from type private static Calculator Evaluate(IEnumerable> polynomial, Calculator x, Calculator prime) { - return polynomial.Reverse().Aggregate(Calculator.Zero, (current, coefficient) => (current * x + coefficient) % prime); + var polynomialArray = polynomial as Calculator[] ?? polynomial.ToArray(); + var result = Calculator.Zero; + for (int index = polynomialArray.Length - 1; index >= 0; index--) + { + result = (result * x + polynomialArray[index]) % prime; + } + + return result; } /// @@ -221,13 +225,14 @@ private static Calculator Evaluate(IEnumerable> pol /// /// Based on discussion on stackoverflow /// - private static string ToHexString(IReadOnlyCollection bytes) + private static string ToHexString(IEnumerable bytes) { - StringBuilder hexRepresentation = new StringBuilder(bytes.Count * 2); - foreach (byte b in bytes) + byte[] byteArray = bytes as byte[] ?? bytes.ToArray(); + var hexRepresentation = new StringBuilder(byteArray.Length * 2); + foreach (byte b in byteArray) { const string hexAlphabet = "0123456789ABCDEF"; - hexRepresentation.Append(new[] { hexAlphabet[b >> 4], hexAlphabet[b & 0xF] }); + hexRepresentation.Append(hexAlphabet[b >> 4]).Append(hexAlphabet[b & 0xF]); } return hexRepresentation.ToString(); @@ -237,11 +242,12 @@ private static string ToHexString(IReadOnlyCollection bytes) /// Converts a hexadecimal string to a byte array. /// /// hexadecimal string - /// + /// Returns a byte array private static byte[] ToByteArray(string hexString) { - var bytes = new byte[hexString.Length / 2]; - var hexValues = Array.AsReadOnly(new[] { + byte[] bytes = new byte[hexString.Length / 2]; + var hexValues = Array.AsReadOnly(new[] + { 0x00, 0x01, 0x02, @@ -267,13 +273,13 @@ private static byte[] ToByteArray(string hexString) 0x0F }); - for (int x = 0, i = 0; i < hexString.Length; i += 2, x += 1) + for (int i = 0, j = 0; j < hexString.Length; j += 2, i += 1) { const char zeroDigit = '0'; - bytes[x] = (byte)((hexValues[char.ToUpper(hexString[i + 0], CultureInfo.InvariantCulture) - zeroDigit] << 4) | hexValues[char.ToUpper(hexString[i + 1], CultureInfo.InvariantCulture) - zeroDigit]); + bytes[i] = (byte)(hexValues[char.ToUpper(hexString[j + 0], CultureInfo.InvariantCulture) - zeroDigit] << 4 | hexValues[char.ToUpper(hexString[j + 1], CultureInfo.InvariantCulture) - zeroDigit]); } return bytes; } } -} \ No newline at end of file +} diff --git a/src/Cryptography/Secret.cs b/src/Cryptography/Secret.cs index 4d01829..de8f722 100644 --- a/src/Cryptography/Secret.cs +++ b/src/Cryptography/Secret.cs @@ -3,7 +3,7 @@ // Copyright (c) 2022 All Rights Reserved // // Sebastian Walther -// 04/20/2019 10:52:28 PM +// 09/22/2022 00:34:47 AM // ---------------------------------------------------------------------------- #region License @@ -29,16 +29,13 @@ // THE SOFTWARE. #endregion -[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("SecretSharingDotNetTest, PublicKey=0024000004800000940000000602000000240000525341310004000001000100257917fef6a3508bdfc3db4dd65b0b485261c2f5bff7380b7737b0d59f741d41b6086743a7957cab387fb7da8a17491dea1239b496cef97ef61cd76bc3b5f0f983d5e693083c8a0c283bb55edd6fe389abda1565c534a3537e9e087ddef8b1525520ebd5ff6f36e74baaa97522816f3a7998bbdd9392f99c0777c421634abaaa")] namespace SecretSharingDotNet.Cryptography { using Helper; using Math; using System; - using System.Collections.Generic; using System.Linq; using System.Security.Cryptography; - using System.Text; using System.Threading; /// @@ -50,7 +47,7 @@ public class Secret /// Gets or sets the legacy mode on () or to be compatible with /// v0.6.0 or older. /// - public static ThreadLocal LegacyMode = new ThreadLocal { Value = false }; + public static readonly ThreadLocal LegacyMode = new ThreadLocal {Value = false}; /// /// Maximum mark byte to terminate the secret array and to avoid negative secret values. @@ -80,7 +77,7 @@ internal static Secret FromCoefficient(Calculator coe /// Use this ctor to create a random secret internal static Secret CreateRandom(Calculator prime) { - var randomSecretBytes = new byte[prime.ByteCount]; + byte[] randomSecretBytes = new byte[prime.ByteCount]; using (var rng = RandomNumberGenerator.Create()) { rng.GetBytes(randomSecretBytes); @@ -104,7 +101,7 @@ internal static Secret CreateRandom(Calculator prime) if (a0.IsZero) { - return new Secret(new byte[] { 0x00 }); + return new Secret(new byte[] {0x00}); } randomSecretBytes[i--] = 0x00; @@ -129,250 +126,4 @@ internal static Secret CreateRandom(Calculator prime) return bytes.ToArray(); }; } - - /// - /// This class represents the secret including members to parse or convert it. - /// - /// Numeric data type (An integer data type) - public sealed class Secret : Secret, IEquatable>, IComparable> - { - /// - /// Saves the secret - /// - private readonly byte[] secretNumber; - - /// - /// Initializes a new instance of the class. - /// - /// A secret as array of type - /// is - public Secret(byte[] secretSource) - { - if (secretSource == null) - { - throw new ArgumentNullException(nameof(secretSource)); - } - - if (secretSource.Length == 0) - { - throw new ArgumentException(ErrorMessages.EmptyCollection, nameof(secretSource)); - } - - var buffer = new byte[1]; - using (var rng = RandomNumberGenerator.Create()) - { - rng.GetNonZeroBytes(buffer); - } - - byte maxMarkByte = secretSource.Length == 1 ? MinMarkByte : MaxMarkByte; - byte markByte = (byte)(new Random(buffer[0]).Next(0x01, maxMarkByte) % maxMarkByte); - var bytes = (byte[])secretSource.Clone(); - this.secretNumber = LegacyMode.Value ? bytes : bytes.Concat(new[] { markByte }).ToArray(); - } - - /// - /// Initializes a new instance of the class. - /// - /// Secret as or value. - public Secret(Calculator secretSource) : this(secretSource.ByteRepresentation.ToArray()) { } - - /// - /// Initializes a new instance of the class. Use this ctor to deserialize a base64 string to - /// a instance. - /// - /// Secret encoded as base-64 - /// For normal text use the implicit cast from to - /// is , empty or consists exclusively of white-space characters - public Secret(string encoded) : this(LegacyMode.Value ? FromBase64Legacy(encoded) : Convert.FromBase64String(encoded)) { } - - /// - /// Gets the byte size. - /// - internal int SecretByteSize => this.secretNumber.Length; - - /// - /// Gets this as an a0 coefficient. - /// - internal Calculator ToCoefficient => Calculator.Create(this.secretNumber, typeof(TNumber)) as Calculator; - - /// - /// Casts the instance to an instance - /// - public static implicit operator Secret(TNumber number) => new Secret(((Calculator)number).ByteRepresentation.ToArray()); - - /// - /// Casts the instance to an instance - /// - public static implicit operator TNumber(Secret secret) - { - if (secret == null || secret.secretNumber == null || secret.secretNumber.Length == 0) - { - return default; - } - - return ((Calculator)secret).Value; - } - - /// - /// Casts the instance to an instance - /// - public static implicit operator Calculator(Secret secret) - { - var bytes = secret?.secretNumber.Subset(0, secret.secretNumber.Length - MarkByteCount); - return Calculator.Create(bytes, typeof(TNumber)) as Calculator; - } - - /// - /// Casts the instance to an instance - /// - public static implicit operator Secret(Calculator calculator) => new Secret(calculator.ByteRepresentation.ToArray()); - - /// - /// Casts the array instance to an instance - /// - public static implicit operator Secret(byte[] array) => new Secret(array); - - /// - /// Casts the instance to an array instance - /// - public static implicit operator byte[](Secret secret) => secret.ToByteArray(); - - /// - /// Casts the instance to an instance - /// - public static implicit operator Secret(string secret) => new Secret(Encoding.Unicode.GetBytes(secret)); - - /// - /// Equality operator - /// - /// The left operand - /// The right operand - /// Returns if its operands are equal, otherwise . - public static bool operator ==(Secret left, Secret right) => left?.Equals(right) ?? right is null; - - /// - /// Inequality operator - /// - /// The left operand - /// The right operand - /// Returns if its operands are not equal, otherwise . - public static bool operator !=(Secret left, Secret right) => !left?.Equals(right) ?? !(right is null); - - /// - /// Greater than operator - /// - /// The left operand - /// The right operand - /// - public static bool operator >(Secret left, Secret right) => !(left is null) && !(right is null) && left.CompareTo(right) == 1; - - /// - /// Less than operator - /// - /// The left operand - /// The right operand - /// - public static bool operator <(Secret left, Secret right) => !(left is null) && !(right is null) && left.CompareTo(right) == -1; - - /// - /// Greater than or equal operator - /// - /// The left operand - /// The right operand - /// - public static bool operator >=(Secret left, Secret right) => !(left is null) && !(right is null) && left.CompareTo(right) >= 0; - - /// - /// Less than or equal operator - /// - /// The left operand - /// The right operand - /// - public static bool operator <=(Secret left, Secret right) => !(left is null) && !(right is null) && left.CompareTo(right) <= 0; - - /// - /// Compares this instance to a specified and returns an indication of their relative values. - /// - /// An instance to compare with this instance. - /// A value that indicates the relative order of the instances being compared. - /// is - public int CompareTo(Secret other) => this.secretNumber.CompareTo(other?.secretNumber ?? throw new ArgumentNullException(nameof(other))); - - /// - /// Determines whether this instance and an specified instance are equal. - /// - /// The instance to compare - /// if the value of the parameter is the same as the value of this instance; otherwise . - /// If is , the method returns . - public bool Equals(Secret other) - { - if (LegacyMode.Value) - { - return !(other is null) && Calculator.Create(this.secretNumber, typeof(TNumber)).Equals(Calculator.Create(other.secretNumber, typeof(TNumber))); - } - - return !(other is null) && this.secretNumber.Subset(0, this.SecretByteSize - MarkByteCount) - .SequenceEqual(other.secretNumber.Subset(0, other.SecretByteSize - MarkByteCount)); - } - - /// - /// Returns a value that indicates whether the current instance and a specified object have the same value. - /// - /// The object to compare. - /// if the argument is a object, - /// and its value is equal to the value of the current instance; otherwise, . - public override bool Equals(object obj) => obj != null && this.Equals((Secret)obj); - - /// - /// Returns the hash code for the current structure. - /// - /// A 32-bit signed integer hash code. - public override int GetHashCode() => this.secretNumber.GetHashCode(); - - /// - /// Converts the value of structure to its equivalent representation - /// that is unicode encoded. - /// - /// representation of - public override string ToString() - { - int padCount = (this.secretNumber.Length - MarkByteCount) % sizeof(char); - if (padCount == 0) - { - return Encoding.Unicode.GetString(this.secretNumber, 0, this.secretNumber.Length - MarkByteCount); - } - - var padded = new List(this.secretNumber.Subset(0, this.secretNumber.Length - MarkByteCount)); - for (int i = 0; i < padCount; i++) - { - padded.Add(0x00); - } - - return Encoding.Unicode.GetString(padded.ToArray(), 0, padded.Count); - } - - /// - /// Converts the secret to a byte array - /// - /// Array of type - public byte[] ToByteArray() - { - return this.secretNumber.Subset(0, this.secretNumber.Length - MarkByteCount).Clone() as byte[]; - } - - /// - /// Converts the value of structure to its equivalent representation - /// that is encoded with base-64 digits. - /// - /// The representation in base 64 - public string ToBase64() - { - if (LegacyMode.Value) - { - return Convert.ToBase64String(this.secretNumber, 1, this.secretNumber.Length - 2); - } - - return Convert.ToBase64String(this.secretNumber, 0, this.secretNumber.Length - MarkByteCount); - } - } -} \ No newline at end of file +} diff --git a/src/Cryptography/Secret`1.cs b/src/Cryptography/Secret`1.cs new file mode 100644 index 0000000..20b5eec --- /dev/null +++ b/src/Cryptography/Secret`1.cs @@ -0,0 +1,288 @@ +// ---------------------------------------------------------------------------- +// +// Copyright (c) 2022 All Rights Reserved +// +// Sebastian Walther +// 09/22/2022 00:34:47 AM +// ---------------------------------------------------------------------------- + +#region License +// ---------------------------------------------------------------------------- +// Copyright 2022 Sebastian Walther +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#endregion + +[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("SecretSharingDotNetTest, PublicKey=0024000004800000940000000602000000240000525341310004000001000100257917fef6a3508bdfc3db4dd65b0b485261c2f5bff7380b7737b0d59f741d41b6086743a7957cab387fb7da8a17491dea1239b496cef97ef61cd76bc3b5f0f983d5e693083c8a0c283bb55edd6fe389abda1565c534a3537e9e087ddef8b1525520ebd5ff6f36e74baaa97522816f3a7998bbdd9392f99c0777c421634abaaa")] +namespace SecretSharingDotNet.Cryptography +{ + using Helper; + using Math; + using System; + using System.Collections.Generic; + using System.Linq; + using System.Security.Cryptography; + using System.Text; + + /// + /// This class represents the secret including members to parse or convert it. + /// + /// Numeric data type (An integer data type) + public sealed class Secret : Secret, IEquatable>, IComparable> + { + /// + /// Saves the secret + /// + private readonly byte[] secretNumber; + + /// + /// Initializes a new instance of the class. + /// + /// A secret as array of type + /// is + public Secret(byte[] secretSource) + { + if (secretSource == null) + { + throw new ArgumentNullException(nameof(secretSource)); + } + + if (secretSource.Length == 0) + { + throw new ArgumentException(ErrorMessages.EmptyCollection, nameof(secretSource)); + } + + byte[] buffer = new byte[1]; + using (var rng = RandomNumberGenerator.Create()) + { + rng.GetNonZeroBytes(buffer); + } + + byte maxMarkByte = secretSource.Length == 1 ? MinMarkByte : MaxMarkByte; + byte markByte = (byte)(new Random(buffer[0]).Next(0x01, maxMarkByte) % maxMarkByte); + byte[] bytes = (byte[])secretSource.Clone(); + this.secretNumber = LegacyMode.Value ? bytes : bytes.Concat(new[] {markByte}).ToArray(); + } + + /// + /// Initializes a new instance of the class. + /// + /// Secret as or value. + public Secret(Calculator secretSource) : this(secretSource.ByteRepresentation.ToArray()) { } + + /// + /// Initializes a new instance of the class. Use this ctor to deserialize a base64 string to + /// a instance. + /// + /// Secret encoded as base-64 + /// For normal text use the implicit cast from to + /// is , empty or consists exclusively of white-space characters + public Secret(string encoded) : this(LegacyMode.Value ? FromBase64Legacy(encoded) : Convert.FromBase64String(encoded)) { } + + /// + /// Gets the byte size. + /// + internal int SecretByteSize => this.secretNumber.Length; + + /// + /// Gets this as an a0 coefficient. + /// + internal Calculator ToCoefficient => Calculator.Create(this.secretNumber, typeof(TNumber)) as Calculator; + + /// + /// Casts the instance to an instance + /// + public static implicit operator Secret(TNumber number) => new Secret(((Calculator)number).ByteRepresentation.ToArray()); + + /// + /// Casts the instance to an instance + /// + public static implicit operator TNumber(Secret secret) + { + if (secret == null || secret.secretNumber == null || secret.secretNumber.Length == 0) + { + return default; + } + + return ((Calculator)secret).Value; + } + + /// + /// Casts the instance to an instance + /// + public static implicit operator Calculator(Secret secret) + { + byte[] bytes = secret?.secretNumber.Subset(0, secret.secretNumber.Length - MarkByteCount); + return Calculator.Create(bytes, typeof(TNumber)) as Calculator; + } + + /// + /// Casts the instance to an instance + /// + public static implicit operator Secret(Calculator calculator) => new Secret(calculator.ByteRepresentation.ToArray()); + + /// + /// Casts the array instance to an instance + /// + public static implicit operator Secret(byte[] array) => new Secret(array); + + /// + /// Casts the instance to an array instance + /// + public static implicit operator byte[](Secret secret) => secret.ToByteArray(); + + /// + /// Casts the instance to an instance + /// + public static implicit operator Secret(string secret) => new Secret(Encoding.Unicode.GetBytes(secret)); + + /// + /// Equality operator + /// + /// The left operand + /// The right operand + /// Returns if its operands are equal, otherwise . + public static bool operator ==(Secret left, Secret right) => left?.Equals(right) ?? right is null; + + /// + /// Inequality operator + /// + /// The left operand + /// The right operand + /// Returns if its operands are not equal, otherwise . + public static bool operator !=(Secret left, Secret right) => !left?.Equals(right) ?? !(right is null); + + /// + /// Greater than operator + /// + /// The left operand + /// The right operand + /// + public static bool operator >(Secret left, Secret right) => !(left is null) && !(right is null) && left.CompareTo(right) == 1; + + /// + /// Less than operator + /// + /// The left operand + /// The right operand + /// + public static bool operator <(Secret left, Secret right) => !(left is null) && !(right is null) && left.CompareTo(right) == -1; + + /// + /// Greater than or equal operator + /// + /// The left operand + /// The right operand + /// + public static bool operator >=(Secret left, Secret right) => !(left is null) && !(right is null) && left.CompareTo(right) >= 0; + + /// + /// Less than or equal operator + /// + /// The left operand + /// The right operand + /// + public static bool operator <=(Secret left, Secret right) => !(left is null) && !(right is null) && left.CompareTo(right) <= 0; + + /// + /// Compares this instance to a specified and returns an indication of their relative values. + /// + /// An instance to compare with this instance. + /// A value that indicates the relative order of the instances being compared. + /// is + public int CompareTo(Secret other) => this.secretNumber.CompareTo(other?.secretNumber ?? throw new ArgumentNullException(nameof(other))); + + /// + /// Determines whether this instance and an specified instance are equal. + /// + /// The instance to compare + /// if the value of the parameter is the same as the value of this instance; otherwise . + /// If is , the method returns . + public bool Equals(Secret other) + { + if (LegacyMode.Value) + { + return !(other is null) && Calculator.Create(this.secretNumber, typeof(TNumber)).Equals(Calculator.Create(other.secretNumber, typeof(TNumber))); + } + + return !(other is null) && this.secretNumber.Subset(0, this.SecretByteSize - MarkByteCount) + .SequenceEqual(other.secretNumber.Subset(0, other.SecretByteSize - MarkByteCount)); + } + + /// + /// Returns a value that indicates whether the current instance and a specified object have the same value. + /// + /// The object to compare. + /// if the argument is a object, + /// and its value is equal to the value of the current instance; otherwise, . + public override bool Equals(object obj) => obj != null && this.Equals((Secret)obj); + + /// + /// Returns the hash code for the current structure. + /// + /// A 32-bit signed integer hash code. + public override int GetHashCode() => this.secretNumber.GetHashCode(); + + /// + /// Converts the value of structure to its equivalent representation + /// that is unicode encoded. + /// + /// representation of + public override string ToString() + { + int padCount = (this.secretNumber.Length - MarkByteCount) % sizeof(char); + if (padCount == 0) + { + return Encoding.Unicode.GetString(this.secretNumber, 0, this.secretNumber.Length - MarkByteCount); + } + + var padded = new List(this.secretNumber.Subset(0, this.secretNumber.Length - MarkByteCount)); + for (int i = 0; i < padCount; i++) + { + padded.Add(0x00); + } + + return Encoding.Unicode.GetString(padded.ToArray(), 0, padded.Count); + } + + /// + /// Converts the secret to a byte array + /// + /// Array of type + public byte[] ToByteArray() + { + return this.secretNumber.Subset(0, this.secretNumber.Length - MarkByteCount).Clone() as byte[]; + } + + /// + /// Converts the value of structure to its equivalent representation + /// that is encoded with base-64 digits. + /// + /// The representation in base 64 + public string ToBase64() + { + if (LegacyMode.Value) + { + return Convert.ToBase64String(this.secretNumber, 1, this.secretNumber.Length - 2); + } + + return Convert.ToBase64String(this.secretNumber, 0, this.secretNumber.Length - MarkByteCount); + } + } +} diff --git a/src/Cryptography/ShamirsSecretSharing`1.cs b/src/Cryptography/ShamirsSecretSharing`1.cs new file mode 100644 index 0000000..9b72bc8 --- /dev/null +++ b/src/Cryptography/ShamirsSecretSharing`1.cs @@ -0,0 +1,47 @@ +// ---------------------------------------------------------------------------- +// +// Copyright (c) 2022 All Rights Reserved +// +// Sebastian Walther +// 08/20/2022 02:37:59 PM +// ---------------------------------------------------------------------------- + +#region License +// ---------------------------------------------------------------------------- +// Copyright 2022 Sebastian Walther +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#endregion + +namespace SecretSharingDotNet.Cryptography +{ + using Math; + using System; + + /// + public class ShamirsSecretSharing : ShamirsSecretSharing, ExtendedGcdResult> + { + /// + public ShamirsSecretSharing(IExtendedGcdAlgorithm extendedGcd) : base(extendedGcd) { } + + /// + [Obsolete("Obsolete")] + public ShamirsSecretSharing(IExtendedGcdAlgorithm extendedGcd, int securityLevel) : base(extendedGcd, securityLevel) { } + } +} diff --git a/src/Cryptography/ShamirsSecretSharing.cs b/src/Cryptography/ShamirsSecretSharing`3.cs similarity index 74% rename from src/Cryptography/ShamirsSecretSharing.cs rename to src/Cryptography/ShamirsSecretSharing`3.cs index eeb530c..3a3ece6 100644 --- a/src/Cryptography/ShamirsSecretSharing.cs +++ b/src/Cryptography/ShamirsSecretSharing`3.cs @@ -1,9 +1,9 @@ // ---------------------------------------------------------------------------- -// +// // Copyright (c) 2022 All Rights Reserved // // Sebastian Walther -// 04/20/2019 10:52:28 PM +// 08/20/2022 02:37:59 PM // ---------------------------------------------------------------------------- #region License @@ -33,27 +33,29 @@ namespace SecretSharingDotNet.Cryptography { using Math; using System; - using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Security.Cryptography; - using System.Threading.Tasks; /// /// Shamir's secret sharing algorithm /// /// Numeric data type - public class ShamirsSecretSharing + /// + /// + public class ShamirsSecretSharing + where TExtendedGcdAlgorithm : class, IExtendedGcdAlgorithm + where TExtendedGcdResult : struct, IExtendedGcdResult { /// /// Saves the known security levels (Mersenne prime exponents) /// - private readonly List securityLevels = new List(new[] + private readonly int[] securityLevels = new int[] { 5, 7, 13, 17, 19, 31, 61, 89, 107, 127, 521, 607, 1279, 2203, 2281, 3217, 4253, 4423, 9689, 9941, 11213, 19937, 21701, 23209, 44497, 86243, 110503, 132049, 216091, 756839, 859433, 1257787, 1398269, 2976221, 3021377, 6972593, 13466917, 20996011, 24036583, 25964951, 30402457, 32582657, 37156667, 42643801, 43112609 - }); + }; /// /// Saves the fixed security level @@ -68,27 +70,27 @@ public class ShamirsSecretSharing /// /// Saves the extended greatest common divisor algorithm /// - private readonly IExtendedGcdAlgorithm extendedGcd; + private readonly TExtendedGcdAlgorithm extendedGcd; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// Extended greatest common divisor algorithm /// The parameter is . - public ShamirsSecretSharing(IExtendedGcdAlgorithm extendedGcd) + public ShamirsSecretSharing(TExtendedGcdAlgorithm extendedGcd) { this.extendedGcd = extendedGcd ?? throw new ArgumentNullException(nameof(extendedGcd)); this.SecurityLevel = 13; } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// Extended greatest common divisor algorithm /// Security level (in number of bits). Minimum is 5 for legacy mode and 13 for normal mode. /// The security level is lower than 5 or greater than 43112609. [Obsolete("Will be removed in future versions. Please use one of the overloads of the method MakeShares.", false)] - public ShamirsSecretSharing(IExtendedGcdAlgorithm extendedGcd, int securityLevel) + public ShamirsSecretSharing(TExtendedGcdAlgorithm extendedGcd, int securityLevel) { this.extendedGcd = extendedGcd ?? throw new ArgumentNullException(nameof(extendedGcd)); try @@ -122,7 +124,7 @@ public int SecurityLevel value = 13; } - int index = this.securityLevels.BinarySearch(value); + int index = Array.BinarySearch(this.securityLevels, value); if (index < 0) { try @@ -150,8 +152,8 @@ public int SecurityLevel /// The parameter is lower than 5 or greater than 43112609. OR The parameter is lower than 2 or greater than . public Shares MakeShares(TNumber numberOfMinimumShares, TNumber numberOfShares, int securityLevel) { - Calculator min = numberOfMinimumShares; - Calculator max = numberOfShares; + int min = ((Calculator)numberOfMinimumShares).ToInt32(); + int max = ((Calculator)numberOfShares).ToInt32(); try { this.SecurityLevel = securityLevel; @@ -175,9 +177,9 @@ public Shares MakeShares(TNumber numberOfMinimumShares, TNumber numberO [Obsolete("Will be removed in future versions. Please use the method MakeShares(TNumber numberOfMinimumShares, TNumber numberOfShares, int securityLevel).", false)] public Shares MakeShares(TNumber numberOfMinimumShares, TNumber numberOfShares) { - Calculator min = numberOfMinimumShares; - Calculator max = numberOfShares; - if (min < Calculator.Two) + int min = ((Calculator)numberOfMinimumShares).ToInt32(); + int max = ((Calculator)numberOfShares).ToInt32(); + if (min < 2) { throw new ArgumentOutOfRangeException(nameof(numberOfMinimumShares), numberOfMinimumShares, ErrorMessages.MinNumberOfSharesLowerThanTwo); } @@ -193,9 +195,9 @@ public Shares MakeShares(TNumber numberOfMinimumShares, TNumber numberO } var secret = Secret.CreateRandom(this.mersennePrime); - var polynomial = CreatePolynomial(min); + var polynomial = this.CreatePolynomial(min); polynomial[0] = secret.ToCoefficient; - var points = CreateSharedSecrets(max, polynomial); + var points = this.CreateSharedSecrets(max, polynomial); return new Shares(secret, points); } @@ -241,9 +243,9 @@ public Shares MakeShares(TNumber numberOfMinimumShares, TNumber numberO throw new ArgumentNullException(nameof(secret)); } - Calculator min = numberOfMinimumShares; - Calculator max = numberOfShares; - if (min < Calculator.Two) + int min = ((Calculator)numberOfMinimumShares).ToInt32(); + int max = ((Calculator)numberOfShares).ToInt32(); + if (min < 2) { throw new ArgumentOutOfRangeException(nameof(numberOfMinimumShares), numberOfMinimumShares, ErrorMessages.MinNumberOfSharesLowerThanTwo); } @@ -259,9 +261,9 @@ public Shares MakeShares(TNumber numberOfMinimumShares, TNumber numberO this.SecurityLevel = newSecurityLevel; } - var polynomial = CreatePolynomial(min); + var polynomial = this.CreatePolynomial(min); polynomial[0] = secret.ToCoefficient; - var points = CreateSharedSecrets(max, polynomial); + var points = this.CreateSharedSecrets(max, polynomial); return new Shares(secret, points); } @@ -271,16 +273,17 @@ public Shares MakeShares(TNumber numberOfMinimumShares, TNumber numberO /// /// Minimum number of shared secrets for reconstruction /// - private List> CreatePolynomial(Calculator numberOfMinimumShares) + private Calculator[] CreatePolynomial(int numberOfMinimumShares) { - var polynomial = new List>() { Calculator.Zero }; - var randomNumber = new byte[this.mersennePrime.ByteCount]; + var polynomial = new Calculator[numberOfMinimumShares]; + polynomial[0] = Calculator.Zero; + byte[] randomNumber = new byte[this.mersennePrime.ByteCount]; using (var rng = RandomNumberGenerator.Create()) { - for (var i = Calculator.One; i < numberOfMinimumShares; i++) + for (int i = 1; i < numberOfMinimumShares; i++) { rng.GetBytes(randomNumber); - polynomial.Add((Calculator.Create(randomNumber, typeof(TNumber)) as Calculator)?.Abs() % this.mersennePrime); + polynomial[i] = (Calculator.Create(randomNumber, typeof(TNumber)) as Calculator)?.Abs() % this.mersennePrime; } } @@ -292,13 +295,16 @@ private List> CreatePolynomial(Calculator numberOfM /// /// Maximum number of shared secrets /// - /// A list of finite points representing the shared secrets - private List> CreateSharedSecrets(Calculator numberOfShares, ICollection> polynomial) + /// Finite points representing the shared secrets + private FinitePoint[] CreateSharedSecrets(int numberOfShares, ICollection> polynomial) { - var points = new List>(); //// pre-init - for (var i = Calculator.One; i < numberOfShares + Calculator.One; i++) + int size = numberOfShares + 1; + var points = new FinitePoint[numberOfShares]; + + for (int i = 1; i < size; i++) { - points.Add(new FinitePoint(i, polynomial, this.mersennePrime)); + var x = Calculator.Create(BitConverter.GetBytes(i), typeof(TNumber)) as Calculator; + points[i - 1] = new FinitePoint(x, polynomial, this.mersennePrime); } return points; @@ -329,64 +335,74 @@ private Calculator DivMod( /// /// /// Helper method for LagrangeInterpolate - private static Calculator Product(IEnumerable> values) + private static Calculator Product(IReadOnlyList> values) { - return values.Aggregate(Calculator.One, (current, v) => current * v); + var result = Calculator.One; + for (int i = 0; i < values.Count; i++) + { + result *= values[i]; + } + + return result; } /// /// Find the y-value for the given x, given n (x, y) points; /// k points will define a polynomial of up to kth order /// - /// + /// The shares represented by a set of . /// A prime number must be defined to avoid computation with real numbers. In fact it is finite field arithmetic. /// The prime number must be the same as used for the construction of shares. + /// /// The re-constructed secret. - private Secret LagrangeInterpolate(List> finitePoints, Calculator prime) + private Secret LagrangeInterpolate(FinitePoint[] finitePoints, Calculator prime) { - if (finitePoints.Distinct().Count() != finitePoints.Count) + if (finitePoints == null) { - throw new ArgumentException(ErrorMessages.FinitePointsNotDistinct, nameof(finitePoints)); + throw new ArgumentNullException(nameof(finitePoints)); } - int k = finitePoints.Count; - var numerators = new List>(k - 1); - var denominators = new List>(k - 1); - for (int i = 0; i < k; i++) + if (prime == null) { - var others = new List>(finitePoints.ToArray()); - var current = others[i]; - others.RemoveAt(i); - var numTask = Task.Run(() => - { - return Product(others.AsParallel().Select(o => Calculator.Zero - o.X).ToList()); - }); - - var denTask = Task.Run(() => - { - return Product(others.AsParallel().Select(o => current.X - o.X).ToList()); - }); - - numerators.Add(numTask.Result); - denominators.Add(denTask.Result); + throw new ArgumentNullException(nameof(prime)); } - var numerator = Calculator.Zero; - var denominator = Product(denominators); + int numberOfPoints = finitePoints.Length; + if (finitePoints.Distinct().Count() != numberOfPoints) + { + throw new ArgumentException(ErrorMessages.FinitePointsNotDistinct, nameof(finitePoints)); + } - object sync = new object(); - var rangePartitioner = Partitioner.Create(0, k); - Parallel.ForEach(rangePartitioner, (range, _) => + var numeratorProducts = new Calculator[numberOfPoints]; + var denominatorProducts = new Calculator[numberOfPoints]; + var numeratorTerms = new Calculator[numberOfPoints]; + var denominatorTerms = new Calculator[numberOfPoints]; + var denominator = Calculator.One; + for (int i = 0; i < numberOfPoints; i++) { - for (int i = range.Item1; i < range.Item2; i++) + for (int j = 0; j < numberOfPoints; j++) { - var result = this.DivMod(numerators[i] * denominator * ((finitePoints[i].Y % prime + prime) % prime), denominators[i], prime); - lock (sync) + if (finitePoints[i] != finitePoints[j]) { - numerator += result; + numeratorTerms[j] = Calculator.Zero - finitePoints[j].X; + denominatorTerms[j] = finitePoints[i].X - finitePoints[j].X; + } + else + { + numeratorTerms[j] = denominatorTerms[j] = Calculator.One; } } - }); + + numeratorProducts[i] = Product(numeratorTerms); + denominatorProducts[i] = Product(denominatorTerms); + denominator *= denominatorProducts[i]; + } + + var numerator = Calculator.Zero; + for (int i = 0; i < numberOfPoints; i++) + { + numerator += this.DivMod(numeratorProducts[i] * denominator * ((finitePoints[i].Y % prime + prime) % prime), denominatorProducts[i], prime); + } var a = this.DivMod(numerator, denominator, prime) + prime; a = (a % prime + prime) % prime; //// mathematical modulo @@ -443,11 +459,11 @@ public Secret Reconstruction(Shares shares) /// /// Recovers the secret from the given (points with x and y on the polynomial) /// - /// two or more shares + /// Two or more shares represented by a set of /// Re-constructed secret /// is . /// The length of is lower than 2. - public Secret Reconstruction(params FinitePoint[] shares) + public Secret Reconstruction(FinitePoint[] shares) { if (shares == null) { @@ -460,15 +476,21 @@ public Secret Reconstruction(params FinitePoint[] shares) } var maximumY = shares.Select(point => point.Y).Max(); + if (maximumY == null) + { + throw new ArgumentException(ErrorMessages.NoMaximumY, nameof(shares)); + } + this.SecurityLevel = maximumY.ByteCount * 8; - var index = this.securityLevels.IndexOf(this.SecurityLevel); + int index = Array.IndexOf(this.securityLevels, this.SecurityLevel); while ((maximumY % this.mersennePrime + this.mersennePrime) % this.mersennePrime == maximumY && index > 0 && this.SecurityLevel > 5) { this.SecurityLevel = this.securityLevels[--index]; } this.SecurityLevel = this.securityLevels[this.SecurityLevel > 5 ? ++index : index]; - return this.LagrangeInterpolate(new List>(shares), this.mersennePrime); + + return this.LagrangeInterpolate(shares, this.mersennePrime); } } } diff --git a/src/Cryptography/Shares.cs b/src/Cryptography/Shares.cs index 119646d..8713646 100644 --- a/src/Cryptography/Shares.cs +++ b/src/Cryptography/Shares.cs @@ -65,7 +65,7 @@ public sealed class Shares : ICollection>, ICollec private Shares(IList> shares) { _ = shares ?? throw new ArgumentNullException(nameof(shares)); - this.shareList = new Collection>(shares); + this.shareList = shares as Collection> ?? new Collection>(shares); } /// @@ -78,7 +78,7 @@ internal Shares(Secret secret, IList> shares) { this.OriginalSecret = secret ?? throw new ArgumentNullException(nameof(secret)); _ = shares ?? throw new ArgumentNullException(nameof(shares)); - this.shareList = new Collection>(shares); + this.shareList = shares as Collection> ?? new Collection>(shares); } /// @@ -87,40 +87,18 @@ internal Shares(Secret secret, IList> shares) public Secret OriginalSecret { get; } /// - /// Gets the original secret - /// - /// Legacy property - [Obsolete("Legacy property. Will be removed in futures versions. Pleas use OriginalSecret property.", true)] - public Secret Item1 => this.OriginalSecret; - - /// - /// Gets or sets the associated with the specified index. + /// Gets the associated with the specified index. /// - /// The index of the to get or set. - /// + /// The index of the to get. + /// Returns a share (shared secret) represented by a . [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "i")] public FinitePoint this[int i] => this.shareList[i]; - /// - /// Gets the shares. - /// - /// Legacy property - [Obsolete("Legacy property. Will be removed in futures versions.", true)] - public ICollection> Item2 => this.shareList; - /// /// Gets a value indicating whether or not the original secret is available. /// public bool OriginalSecretExists => this.OriginalSecret != null; - /// - /// Casts a object to a object. - /// - /// A object. - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")] - [Obsolete("Legacy property. Will be removed in futures versions.", true)] - public static implicit operator Tuple, ICollection>>(Shares shares) => new Tuple, ICollection>>(shares?.OriginalSecret, shares); - /// /// Casts a object to a array of s. /// @@ -171,8 +149,9 @@ public static explicit operator FinitePoint[](Shares shares) = /// A human readable list of shares separated by newlines public override string ToString() { - StringBuilder stringBuilder = new StringBuilder(); - foreach (var share in this.shareList) + var stringBuilder = new StringBuilder(); + var shares = this.shareList as FinitePoint[] ?? this.shareList.ToArray(); + foreach (var share in shares) { stringBuilder.AppendLine(share.ToString()); } @@ -184,13 +163,13 @@ public override string ToString() /// Returns an enumerator that iterates through a collection. /// /// An enumerator that can be used to iterate through the collection. - IEnumerator> IEnumerable>.GetEnumerator() => GetEnumerator(); + IEnumerator> IEnumerable>.GetEnumerator() => this.GetEnumerator(); /// /// Returns an enumerator that iterates through a collection. /// /// An object that can be used to iterate through the collection. - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); /// /// Returns an that iterates through the collection. @@ -275,14 +254,14 @@ public bool Remove(FinitePoint item) /// /// The one-dimensional that is the destination of the items copied from collection. /// The must have zero-based indexing. - /// The zero-based index in at which copying begins. - void ICollection.CopyTo(Array array, int arrayIndex) + /// The zero-based index in at which copying begins. + void ICollection.CopyTo(Array array, int index) { _ = array ?? throw new ArgumentNullException(nameof(array)); switch (array) { case FinitePoint[] x: - this.CopyTo(x, arrayIndex); + this.CopyTo(x, index); break; default: throw new InvalidCastException(string.Format(ErrorMessages.InvalidArrayTypeCast, nameof(array), array.GetType().GetElementType(), typeof(FinitePoint))); @@ -296,30 +275,37 @@ void ICollection.CopyTo(Array array, int arrayIndex) /// The one-dimensional array of items that is the destination of the /// items copied from collection. /// The array must have zero-based indexing. - /// The zero-based index in at which copying begins. - public void CopyTo(FinitePoint[] array, int arrayIndex) + /// The zero-based index in at which copying begins. + public void CopyTo(FinitePoint[] array, int index) { _ = array ?? throw new ArgumentNullException(nameof(array)); - if (arrayIndex < 0) + if (index < 0) { - throw new ArgumentOutOfRangeException(nameof(arrayIndex), ErrorMessages.StartArrayIndexNegative); + throw new ArgumentOutOfRangeException(nameof(index), ErrorMessages.StartArrayIndexNegative); } - if (Count > array.Length - arrayIndex + 1) + if (this.Count > array.Length - index + 1) { throw new ArgumentException(ErrorMessages.DestinationArrayHasFewerElements, nameof(array)); } for (int i = 0; i < this.shareList.Count; i++) { - array[i + arrayIndex] = this.shareList[i]; + array[i + index] = this.shareList[i]; } } /// /// Gets an object that can be used to synchronize access to the collection. /// - object ICollection.SyncRoot => (this.syncRoot ?? Interlocked.CompareExchange(ref this.syncRoot, new object(), null)) ?? this.syncRoot; + object ICollection.SyncRoot + { + get + { + object newValue = new object(); + return (this.syncRoot ?? Interlocked.CompareExchange(ref this.syncRoot, newValue, null)) ?? newValue; + } + } /// /// Gets a value indicating whether access to the collection is synchronized (thread safe). diff --git a/src/Cryptography/SharesEnumerator.cs b/src/Cryptography/SharesEnumerator.cs index 13932fc..070be1f 100644 --- a/src/Cryptography/SharesEnumerator.cs +++ b/src/Cryptography/SharesEnumerator.cs @@ -53,16 +53,6 @@ public sealed class SharesEnumerator : IEnumerator /// private int position = -1; - /// - /// Initializes a new instance of the class. - /// - /// A collection of items representing the shares. - /// is - public SharesEnumerator(ReadOnlyCollection> shares) - { - this.shareList = shares ?? throw new ArgumentNullException(nameof(shares)); - } - /// /// Initializes a new instance of the class. /// @@ -82,7 +72,7 @@ public SharesEnumerator(Collection> shares) public bool MoveNext() { this.position++; - return (this.position < shareList.Count); + return this.position < this.shareList.Count; } /// @@ -109,7 +99,7 @@ public FinitePoint Current { try { - return this.shareList[position]; + return this.shareList[this.position]; } catch (IndexOutOfRangeException) { diff --git a/src/Math/BigIntCalculator.cs b/src/Math/BigIntCalculator.cs index bb28e29..77f3853 100644 --- a/src/Math/BigIntCalculator.cs +++ b/src/Math/BigIntCalculator.cs @@ -1,14 +1,38 @@ // ---------------------------------------------------------------------------- // -// Copyright (c) 2019 All Rights Reserved +// Copyright (c) 2022 All Rights Reserved // // Sebastian Walther -// 04/20/2019 10:52:28 PM +// 08/20/2022 02:34:00 PM // ---------------------------------------------------------------------------- +#region License +// ---------------------------------------------------------------------------- +// Copyright 2022 Sebastian Walther +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#endregion + namespace SecretSharingDotNet.Math { using System; + using System.Collections.Generic; using System.Collections.ObjectModel; using System.Numerics; @@ -57,6 +81,10 @@ public BigIntCalculator(byte[] data) : base(new BigInteger(data)) { } /// This method returns if this instance is less than or equal to the instance, otherwise. public override bool EqualOrLowerThan(BigInteger right) => this.Value <= right; + /// + /// Unable to convert the current instance of class to . + public override int ToInt32() => (int)this.Value; + /// /// Compares this instance to a second and returns an integer that /// indicates whether the value of this instance is less than, equal to, or greater than the value of the specified object. @@ -147,7 +175,7 @@ public override int CompareTo(Calculator other) /// /// Gets the byte representation of the object. /// - public override ReadOnlyCollection ByteRepresentation => new ReadOnlyCollection(this.Value.ToByteArray()); + public override IEnumerable ByteRepresentation => new ReadOnlyCollection(this.Value.ToByteArray()); /// /// Gets a value indicating whether or not the current object is zero (0). @@ -173,9 +201,9 @@ public override int CompareTo(Calculator other) /// Returns the square root of the current object. /// /// NaN (value is lower than zero) - public override Calculator Sqrt + public override Calculator Sqrt { - get + get { if (this.Value == BigInteger.Zero) { @@ -188,15 +216,21 @@ public override Calculator Sqrt } int bitLength = Convert.ToInt32(Math.Ceiling(BigInteger.Log(this.Value, 2))); - BigInteger root = BigInteger.One << (bitLength >> 1); + var root = BigInteger.One << (bitLength >> 1); bool IsSqrt(BigInteger n, BigInteger r) => n >= r * r && n < (r + 1) * (r + 1); while (!IsSqrt(this.Value, root)) { - root = (root + this.Value / root) >> 1; + root = root + this.Value / root >> 1; } return root; } } + + /// + /// Converts the numeric value of the current object to its equivalent string representation. + /// + /// The representation of the current value. + public override string ToString() => this.Value.ToString(); } -} \ No newline at end of file +} diff --git a/src/Math/Calculator.cs b/src/Math/Calculator.cs index 407e89b..3fdf3df 100644 --- a/src/Math/Calculator.cs +++ b/src/Math/Calculator.cs @@ -1,11 +1,34 @@ // ---------------------------------------------------------------------------- // -// Copyright (c) 2019 All Rights Reserved +// Copyright (c) 2022 All Rights Reserved // // Sebastian Walther -// 04/20/2019 10:52:28 PM +// 08/20/2022 02:34:00 PM // ---------------------------------------------------------------------------- +#region License +// ---------------------------------------------------------------------------- +// Copyright 2022 Sebastian Walther +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#endregion + namespace SecretSharingDotNet.Math { using System; @@ -25,22 +48,22 @@ public abstract class Calculator /// Saves a dictionary of number data types derived from the class. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] - protected static readonly ReadOnlyDictionary ChildTypes = new ReadOnlyDictionary(GetDerivedNumberTypes()); + private static readonly IReadOnlyDictionary ChildTypes = new ReadOnlyDictionary(GetDerivedNumberTypes()); /// - /// Gets the number of elements of the byte representation of the object. + /// Saves a dictionary of constructors of number data types derived from the class. /// - public abstract int ByteCount { get; } + private static readonly IReadOnlyDictionary> ChildBaseCtors = new ReadOnlyDictionary>(GetDerivedCtors()); /// - /// Saves a dictionary of constructors of number data types derived from the class. + /// Gets the number of elements of the byte representation of the object. /// - protected static readonly ReadOnlyDictionary> ChildBaseCtors = new ReadOnlyDictionary>(GetDerivedCtors()); + public abstract int ByteCount { get; } /// /// Gets the byte representation of the object. /// - public abstract ReadOnlyCollection ByteRepresentation { get; } + public abstract IEnumerable ByteRepresentation { get; } /// /// Gets a value indicating whether or not the current object is zero. @@ -62,6 +85,13 @@ public abstract class Calculator /// public abstract int Sign { get; } + /// + /// Converts the current instance to a . + /// + /// A value of the type. + /// Unable to convert the current instance of class to . + public abstract int ToInt32(); + /// /// Creates a new instance derived from the class. /// @@ -70,6 +100,12 @@ public abstract class Calculator /// public static Calculator Create(byte[] data, Type numberType) => ChildBaseCtors[numberType](data); + /// + /// Returns a that represents the current . + /// + /// The representation of this object + public abstract override string ToString(); + /// /// Returns a dictionary of constructors of number data types derived from the class. /// @@ -81,7 +117,12 @@ protected static Dictionary> GetDerivedCtors var parameterExpression = Expression.Parameter(paramType); foreach (var childType in ChildTypes) { - var ctorInfo = childType.Value.GetConstructor(new[] { paramType }); + var ctorInfo = childType.Value.GetConstructor(new[] {paramType}); + if (ctorInfo == null) + { + continue; + } + var ctor = Expression.Lambda>(Expression.New(ctorInfo, parameterExpression), parameterExpression) .Compile(); res.Add(childType.Key, ctor); @@ -98,361 +139,8 @@ protected static Dictionary> GetDerivedCtors private static Dictionary GetDerivedNumberTypes() { var asm = Assembly.GetAssembly(typeof(Calculator)); - var listOfClasses = asm.GetTypes().Where(x => x.IsSubclassOf(typeof(Calculator)) && !x.IsGenericType); - return listOfClasses.ToDictionary(x => x.BaseType?.GetGenericArguments()[0]); - } - } - - /// - /// This class represents the calculator strategy pattern to decouple Shamir's Secret Sharing - /// implementation from the concrete numeric data type like BigInteger. - /// - /// Numeric data type - public abstract class Calculator : Calculator, IEquatable>, IComparable, IComparable> - { - /// - /// Saves a dictionary of constructors of number data types derived from the class. - /// - protected static readonly ReadOnlyDictionary>> ChildCtors = new ReadOnlyDictionary>>(GetDerivedCtors>()); - - /// - /// Initializes a new instance of the class. - /// - /// Numeric value - protected Calculator(TNumber val) => this.Value = val; - - /// - /// Adds the current instance with the - /// instance. - /// - /// Right value to add (right summand). - /// The sum of the current instance and the - /// instance. - public abstract Calculator Add(TNumber right); - - /// - /// Subtracts the current instance with the - /// instance. - /// - /// Right value to subtract (subtrahend). - /// The difference of the current instance and the - /// instance. - public abstract Calculator Subtract(TNumber right); - - /// - /// Multiplies the current instance with the - /// instance. - /// - /// multiplicand - /// The product of the current instance and the - /// instance. - public abstract Calculator Multiply(TNumber right); - - /// - /// Divides the current instance with the - /// instance. - /// - /// divisor - /// The quotient of the current instance and the - /// instance. - public abstract Calculator Divide(TNumber right); - - /// - /// The modulo operation - /// - /// divisor - /// The remainder - public abstract Calculator Modulo(TNumber right); - - /// - /// The unary increment method increments this instance by 1. - /// - /// This instance plus - public abstract Calculator Increment(); - - /// - /// The unary decrement method decrements this instance by 1. - /// - /// This instance minus - public abstract Calculator Decrement(); - - /// - /// Returns the absolute value of the current object. - /// - /// The absolute value of this instance. - public abstract Calculator Abs(); - - /// - /// Power (mathematical) - /// - /// The exponent. - /// The result of raising instance to the power. - public abstract Calculator Pow(int expo); - - /// - /// Returns the square root of the current . - /// - public abstract Calculator Sqrt { get; } - - /// - /// This method represents the Greater Than operator. - /// - /// right-hand operand - /// This method returns if this instance is greater than the instance, otherwise. - public abstract bool GreaterThan(TNumber right); - - /// - /// This method represents the Greater Than Or Equal To operator. - /// - /// right-hand operand - /// This method returns if this instance is greater than or equal to the instance, otherwise. - public abstract bool EqualOrGreaterThan(TNumber right); - - /// - /// This method represents the Lower Than operator. - /// - /// right-hand operand - /// This method returns if this instance is less than the instance, otherwise. - public abstract bool LowerThan(TNumber right); - - /// - /// This method represents the Lower Than Or Equal To operator. - /// - /// right-hand operand - /// This method returns if this instance is less than or equal to the instance, otherwise. - public abstract bool EqualOrLowerThan(TNumber right); - - /// - /// Greater than operator - /// - /// The 1st operand - /// The 2nd operand - /// Returns if its 1st operand is greater than its 2nd operand, otherwise . - public static bool operator >(Calculator left, Calculator right) => !(left is null) && !(right is null) && left.GreaterThan(right.Value); - - /// - /// Less than operator - /// - /// The 1st operand - /// The 2nd operand - /// Returns if its 1st operand is less than its 2nd operand, otherwise . - public static bool operator <(Calculator left, Calculator right) => !(left is null) && !(right is null) && left.LowerThan(right.Value); - - /// - /// Greater than or equal operator - /// - /// The 1st operand - /// The 2nd operand - /// Returns if its 1st operand is greater than or equal to its 2nd operand, otherwise . - public static bool operator >=(Calculator left, Calculator right) => !(left is null) && !(right is null) && left.EqualOrGreaterThan(right.Value); - - /// - /// Less than or equal operator - /// - /// The 1st operand - /// The 2nd operand - /// Returns if its 1st operand is less than or equal to its 2nd operand, otherwise . - public static bool operator <=(Calculator left, Calculator right) => !(left is null) && !(right is null) && left.EqualOrLowerThan(right.Value); - - /// - /// Addition operation - /// - /// The 1st summand - /// The 2nd summand - /// The sum - public static Calculator operator +(Calculator left, Calculator right) => !(right is null) ? left?.Add(right.Value) ?? throw new ArgumentNullException(nameof(left)) : throw new ArgumentNullException(nameof(right)); - - /// - /// Subtraction operation - /// - /// The minuend - /// The subtrahend - /// The difference - public static Calculator operator -(Calculator left, Calculator right) => !(right is null) ? left?.Subtract(right.Value) ?? throw new ArgumentNullException(nameof(left)) : throw new ArgumentNullException(nameof(right)); - - /// - /// Multiplication operation - /// - /// multiplier - /// multiplicand - /// The product - public static Calculator operator *(Calculator left, Calculator right) => !(right is null) ? left?.Multiply(right.Value) ?? throw new ArgumentNullException(nameof(left)) : throw new ArgumentNullException(nameof(right)); - - /// - /// Divide operation - /// - /// dividend - /// divisor - /// The quotient - public static Calculator operator /(Calculator left, Calculator right) => !(right is null) ? left?.Divide(right.Value) ?? throw new ArgumentNullException(nameof(left)) : throw new ArgumentNullException(nameof(right)); - - /// - /// Modulo operation - /// - /// dividend - /// divisor - /// The remainder - public static Calculator operator %(Calculator left, Calculator right) => !(right is null) ? left?.Modulo(right.Value) ?? throw new ArgumentNullException(nameof(left)) : throw new ArgumentNullException(nameof(right)); - - /// - /// Increment operator - /// - /// The operand - /// The unary increment operator increments the operand by 1 - public static Calculator operator ++(Calculator number) => number?.Increment(); - - /// - /// Decrement operator - /// - /// The operand - /// The unary decrement operator decrements the operand by 1. - public static Calculator operator --(Calculator number) => number?.Decrement(); - - /// - /// Equality operator - /// - /// The left operand - /// The right operand - /// Returns if its operands are equal, otherwise . - public static bool operator ==(Calculator left, Calculator right) - { - if ((object)left == null || (object)right == null) - { - return Equals(left, right); - } - - return left.Equals(right); - } - - /// - /// Inequality operator - /// - /// The left operand - /// The right operand - /// Returns if its operands are not equal, otherwise . - public static bool operator !=(Calculator left, Calculator right) - { - if ((object)left == null || (object)right == null) - { - return !Equals(left, right); - } - - return !left.Equals(right); - } - - /// - /// Casts the instance to an instance. - /// - /// A data type from basic class . - public static implicit operator TNumber(Calculator calculatorInstance) => !(calculatorInstance is null) ? calculatorInstance.Value : default; - - /// - /// Casts the instance to an instance. - /// - /// Numeric data type (An integer data type). - public static implicit operator Calculator(TNumber number) - { - try - { - return ChildCtors[typeof(TNumber)](number); - } - catch (KeyNotFoundException) - { - throw new NotSupportedException(string.Format(ErrorMessages.DataTypeNotSupported, typeof(TNumber).Name)); - } - } - - /// - /// Determines whether this instance and an specified instance are equal. - /// - /// The instance to compare - /// if the value of the parameter is the same as the value of this instance; otherwise . - /// If is , the method returns . - public bool Equals(Calculator other) - { - return other != null && this.Value.Equals(other.Value); - } - - /// - /// Returns a value that indicates whether the current instance and a specified object have the same value. - /// - /// The object to compare. - /// if the argument is a object, - /// and its value is equal to the value of the current instance; otherwise, . - public override bool Equals(object obj) - { - if (obj == null) - { - return false; - } - - var calculator = obj as Calculator; - return calculator != null && this.Equals(calculator); + var listOfClasses = asm?.GetTypes().Where(x => x.IsSubclassOf(typeof(Calculator)) && !x.IsGenericType); + return listOfClasses?.ToDictionary(x => x.BaseType?.GetGenericArguments()[0]) ?? new Dictionary(); } - - /// - /// Returns the hash code for the current object. - /// - /// A 32-bit signed integer hash code. - public override int GetHashCode() => this.Value.GetHashCode(); - - /// - /// Compares this instance to a specified object and returns an integer that - /// indicates whether the value of this instance is less than, equal to, or greater than the value of the specified object. - /// - /// The object to compare - /// A signed integer that indicates the relationship of the current instance to the parameter - public virtual int CompareTo(object obj) - { - switch (obj) - { - case null: - return 1; - case TNumber number: - return this.CompareTo(number); - default: - throw new ArgumentException(); - } - } - - /// - /// Gets or sets the numeric value - /// - public TNumber Value { get; set; } - - /// - /// Gets a value that represents the number zero (0). - /// - public static Calculator Zero => default(TNumber); - - /// - /// Gets a value that represents the number one (1). - /// - public static Calculator One => Zero.Increment(); - - /// - /// Gets a value that represents the number two (2). - /// - /// - public static Calculator Two => One.Increment(); - - /// - /// A shallow copy of the current instance. - /// - /// - public Calculator Clone() => this.MemberwiseClone() as Calculator; - - /// - /// Compares this instance to a second and returns an integer that indicates whether the value of this instance is less than, equal to, or greater than the value of the specified object. - /// - /// The object to compare. - /// A signed integer that indicates the relationship of the current instance to the parameter - public abstract int CompareTo(Calculator other); - - /// - /// Converts the numeric value of the current object to its equivalent string representation. - /// - /// The string representation of the current value. - public override string ToString() => this.Value.ToString(); } -} \ No newline at end of file +} diff --git a/src/Math/Calculator`1.cs b/src/Math/Calculator`1.cs new file mode 100644 index 0000000..1ad108b --- /dev/null +++ b/src/Math/Calculator`1.cs @@ -0,0 +1,389 @@ +// +// Copyright (c) 2022 All Rights Reserved +// +// Sebastian Walther +// 07/21/2022 05:23:42 PM +// ---------------------------------------------------------------------------- + +#region License +// ---------------------------------------------------------------------------- +// Copyright 2022 Sebastian Walther +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#endregion + +namespace SecretSharingDotNet.Math +{ + using System; + using System.Collections.Generic; + using System.Collections.ObjectModel; + + /// + /// This class represents the calculator strategy pattern to decouple Shamir's Secret Sharing + /// implementation from the concrete numeric data type like BigInteger. + /// + /// Numeric data type + public abstract class Calculator : Calculator, IEquatable>, IComparable, IComparable> + { + /// + /// Saves a dictionary of constructors of number data types derived from the class. + /// + private static readonly ReadOnlyDictionary>> ChildCtors = new ReadOnlyDictionary>>(GetDerivedCtors>()); + + /// + /// Initializes a new instance of the class. + /// + /// Numeric value + protected Calculator(TNumber val) => this.Value = val; + + /// + /// Adds the current instance with the + /// instance. + /// + /// Right value to add (right summand). + /// The sum of the current instance and the + /// instance. + public abstract Calculator Add(TNumber right); + + /// + /// Subtracts the current instance with the + /// instance. + /// + /// Right value to subtract (subtrahend). + /// The difference of the current instance and the + /// instance. + public abstract Calculator Subtract(TNumber right); + + /// + /// Multiplies the current instance with the + /// instance. + /// + /// multiplicand + /// The product of the current instance and the + /// instance. + public abstract Calculator Multiply(TNumber right); + + /// + /// Divides the current instance with the + /// instance. + /// + /// divisor + /// The quotient of the current instance and the + /// instance. + public abstract Calculator Divide(TNumber right); + + /// + /// The modulo operation + /// + /// divisor + /// The remainder + public abstract Calculator Modulo(TNumber right); + + /// + /// The unary increment method increments this instance by 1. + /// + /// This instance plus + public abstract Calculator Increment(); + + /// + /// The unary decrement method decrements this instance by 1. + /// + /// This instance minus + public abstract Calculator Decrement(); + + /// + /// Returns the absolute value of the current object. + /// + /// The absolute value of this instance. + public abstract Calculator Abs(); + + /// + /// Power (mathematical) + /// + /// The exponent. + /// The result of raising instance to the power. + public abstract Calculator Pow(int expo); + + /// + /// Returns the square root of the current . + /// + public abstract Calculator Sqrt { get; } + + /// + /// This method represents the Greater Than operator. + /// + /// right-hand operand + /// This method returns if this instance is greater than the instance, otherwise. + public abstract bool GreaterThan(TNumber right); + + /// + /// This method represents the Greater Than Or Equal To operator. + /// + /// right-hand operand + /// This method returns if this instance is greater than or equal to the instance, otherwise. + public abstract bool EqualOrGreaterThan(TNumber right); + + /// + /// This method represents the Lower Than operator. + /// + /// right-hand operand + /// This method returns if this instance is less than the instance, otherwise. + public abstract bool LowerThan(TNumber right); + + /// + /// This method represents the Lower Than Or Equal To operator. + /// + /// right-hand operand + /// This method returns if this instance is less than or equal to the instance, otherwise. + public abstract bool EqualOrLowerThan(TNumber right); + + /// + /// Greater than operator + /// + /// The 1st operand + /// The 2nd operand + /// Returns if its 1st operand is greater than its 2nd operand, otherwise . + public static bool operator >(Calculator left, Calculator right) => !(left is null) && !(right is null) && left.GreaterThan(right.Value); + + /// + /// Less than operator + /// + /// The 1st operand + /// The 2nd operand + /// Returns if its 1st operand is less than its 2nd operand, otherwise . + public static bool operator <(Calculator left, Calculator right) => !(left is null) && !(right is null) && left.LowerThan(right.Value); + + /// + /// Greater than or equal operator + /// + /// The 1st operand + /// The 2nd operand + /// Returns if its 1st operand is greater than or equal to its 2nd operand, otherwise . + public static bool operator >=(Calculator left, Calculator right) => !(left is null) && !(right is null) && left.EqualOrGreaterThan(right.Value); + + /// + /// Less than or equal operator + /// + /// The 1st operand + /// The 2nd operand + /// Returns if its 1st operand is less than or equal to its 2nd operand, otherwise . + public static bool operator <=(Calculator left, Calculator right) => !(left is null) && !(right is null) && left.EqualOrLowerThan(right.Value); + + /// + /// Addition operation + /// + /// The 1st summand + /// The 2nd summand + /// The sum + public static Calculator operator +(Calculator left, Calculator right) => !(right is null) ? left?.Add(right.Value) ?? throw new ArgumentNullException(nameof(left)) : throw new ArgumentNullException(nameof(right)); + + /// + /// Subtraction operation + /// + /// The minuend + /// The subtrahend + /// The difference + public static Calculator operator -(Calculator left, Calculator right) => !(right is null) ? left?.Subtract(right.Value) ?? throw new ArgumentNullException(nameof(left)) : throw new ArgumentNullException(nameof(right)); + + /// + /// Multiplication operation + /// + /// multiplier + /// multiplicand + /// The product + public static Calculator operator *(Calculator left, Calculator right) => !(right is null) ? left?.Multiply(right.Value) ?? throw new ArgumentNullException(nameof(left)) : throw new ArgumentNullException(nameof(right)); + + /// + /// Divide operation + /// + /// dividend + /// divisor + /// The quotient + public static Calculator operator /(Calculator left, Calculator right) => !(right is null) ? left?.Divide(right.Value) ?? throw new ArgumentNullException(nameof(left)) : throw new ArgumentNullException(nameof(right)); + + /// + /// Modulo operation + /// + /// dividend + /// divisor + /// The remainder + public static Calculator operator %(Calculator left, Calculator right) => !(right is null) ? left?.Modulo(right.Value) ?? throw new ArgumentNullException(nameof(left)) : throw new ArgumentNullException(nameof(right)); + + /// + /// Increment operator + /// + /// The operand + /// The unary increment operator increments the operand by 1 + public static Calculator operator ++(Calculator number) => number?.Increment(); + + /// + /// Decrement operator + /// + /// The operand + /// The unary decrement operator decrements the operand by 1. + public static Calculator operator --(Calculator number) => number?.Decrement(); + + /// + /// Equality operator + /// + /// The left operand + /// The right operand + /// Returns if its operands are equal, otherwise . + public static bool operator ==(Calculator left, Calculator right) + { + if ((object)left == null || (object)right == null) + { + return Equals(left, right); + } + + return left.Equals(right); + } + + /// + /// Inequality operator + /// + /// The left operand + /// The right operand + /// Returns if its operands are not equal, otherwise . + public static bool operator !=(Calculator left, Calculator right) + { + if ((object)left == null || (object)right == null) + { + return !Equals(left, right); + } + + return !left.Equals(right); + } + + /// + /// Casts the instance to an instance. + /// + /// A data type from basic class . + public static implicit operator TNumber(Calculator calculatorInstance) => !(calculatorInstance is null) ? calculatorInstance.Value : default; + + /// + /// Casts the instance to an instance. + /// + /// Numeric data type (An integer data type). + public static implicit operator Calculator(TNumber number) + { + try + { + return ChildCtors[typeof(TNumber)](number); + } + catch (KeyNotFoundException) + { + throw new NotSupportedException(string.Format(ErrorMessages.DataTypeNotSupported, typeof(TNumber).Name)); + } + } + + /// + /// Determines whether this instance and an specified instance are equal. + /// + /// The instance to compare + /// if the value of the parameter is the same as the value of this instance; otherwise . + /// If is , the method returns . + public bool Equals(Calculator other) + { + return other != null && this.Value.Equals(other.Value); + } + + /// + /// Returns a value that indicates whether the current instance and a specified object have the same value. + /// + /// The object to compare. + /// if the argument is a object, + /// and its value is equal to the value of the current instance; otherwise, . + public override bool Equals(object obj) + { + if (obj == null) + { + return false; + } + + var calculator = obj as Calculator; + return calculator != null && this.Equals(calculator); + } + + /// + /// Returns the hash code for the current object. + /// + /// A 32-bit signed integer hash code. + public override int GetHashCode() => this.Value.GetHashCode(); + + /// + /// Compares this instance to a specified object and returns an integer that + /// indicates whether the value of this instance is less than, equal to, or greater than the value of the specified object. + /// + /// The object to compare + /// has a unknown data type + /// A signed integer that indicates the relationship of the current instance to the parameter + public virtual int CompareTo(object obj) + { + switch (obj) + { + case null: + return 1; + case TNumber number: + return this.CompareTo(number); + default: + throw new ArgumentException(); + } + } + + /// + /// Gets or sets the numeric value + /// + public TNumber Value { get; set; } + + /// + /// Gets a value that represents the number zero (0). + /// + public static Calculator Zero { get; } = default(TNumber); + + /// + /// Gets a value that represents the number one (1). + /// + public static Calculator One { get; } = Zero.Increment(); + + /// + /// Gets a value that represents the number two (2). + /// + public static Calculator Two { get; } = One.Increment(); + + /// + /// A shallow copy of the current instance. + /// + /// + public Calculator Clone() => this.MemberwiseClone() as Calculator; + + /// + /// Compares this instance to a second and returns an integer that indicates whether the value of this instance is less than, equal to, or greater than the value of the specified object. + /// + /// The object to compare. + /// A signed integer that indicates the relationship of the current instance to the parameter + public abstract int CompareTo(Calculator other); + + /// + /// Converts the numeric value of the current object to its equivalent string representation. + /// + /// The representation of the current value. + public abstract override string ToString(); + } +} diff --git a/src/Math/ExtendedEuclideanAlgorithm.cs b/src/Math/ExtendedEuclideanAlgorithm.cs index 9c35d43..e7a5189 100644 --- a/src/Math/ExtendedEuclideanAlgorithm.cs +++ b/src/Math/ExtendedEuclideanAlgorithm.cs @@ -6,6 +6,29 @@ // 04/20/2019 10:52:28 PM // ---------------------------------------------------------------------------- +#region License +// ---------------------------------------------------------------------------- +// Copyright 2022 Sebastian Walther +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#endregion + namespace SecretSharingDotNet.Math { /// @@ -52,9 +75,9 @@ public ExtendedGcdResult Compute(Calculator a, Calculator(lastR, coefficient, quot); + var coefficients = new[] {lastX, lastY}; + var quotients = new[] {x, y}; + return new ExtendedGcdResult(lastR, coefficients, quotients); } } } diff --git a/src/Math/ExtendedGcdResult.cs b/src/Math/ExtendedGcdResult.cs index 1663f28..d6303cb 100644 --- a/src/Math/ExtendedGcdResult.cs +++ b/src/Math/ExtendedGcdResult.cs @@ -1,11 +1,34 @@ // ---------------------------------------------------------------------------- // -// Copyright (c) 2019 All Rights Reserved +// Copyright (c) 2022 All Rights Reserved // // Sebastian Walther -// 04/20/2019 10:52:28 PM +// 08/20/2022 02:32:46 PM // ---------------------------------------------------------------------------- +#region License +// ---------------------------------------------------------------------------- +// Copyright 2022 Sebastian Walther +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#endregion + namespace SecretSharingDotNet.Math { using System; @@ -17,7 +40,7 @@ namespace SecretSharingDotNet.Math /// Represents the result of the extended greatest common divisor computation. /// /// Numeric data type - public readonly struct ExtendedGcdResult : IEquatable> + public readonly struct ExtendedGcdResult : IExtendedGcdResult, IEquatable> { /// /// Initializes a new instance of the struct. @@ -32,19 +55,13 @@ public ExtendedGcdResult(Calculator gcd, IList> coe this.Quotients = new ReadOnlyCollection>(quotients); } - /// - /// Gets the greatest common divisor - /// + /// public Calculator GreatestCommonDivisor { get; } - /// - /// Gets the Bézout coefficients - /// + /// public ReadOnlyCollection> BezoutCoefficients { get; } - /// - /// Gets the quotients by the gcd - /// + /// public ReadOnlyCollection> Quotients { get; } /// @@ -69,8 +86,8 @@ public ExtendedGcdResult(Calculator gcd, IList> coe /// The structure to compare /// if the value of the parameter is the same as the value of this structure; otherwise . public bool Equals(ExtendedGcdResult other) => this.Quotients.SequenceEqual(other.Quotients) && - this.BezoutCoefficients.SequenceEqual(other.BezoutCoefficients) && - this.GreatestCommonDivisor == other.GreatestCommonDivisor; + this.BezoutCoefficients.SequenceEqual(other.BezoutCoefficients) && + this.GreatestCommonDivisor == other.GreatestCommonDivisor; /// /// Determines whether the specified object is equal to the current structure. @@ -102,4 +119,4 @@ public override int GetHashCode() return hashCode; } } -} \ No newline at end of file +} diff --git a/src/Math/IExtendedGcdAlgorithm.cs b/src/Math/IExtendedGcdAlgorithm.cs deleted file mode 100644 index ef8bc94..0000000 --- a/src/Math/IExtendedGcdAlgorithm.cs +++ /dev/null @@ -1,28 +0,0 @@ -// ---------------------------------------------------------------------------- -// -// Copyright (c) 2019 All Rights Reserved -// -// Sebastian Walther -// 04/20/2019 10:52:28 PM -// ---------------------------------------------------------------------------- - -namespace SecretSharingDotNet.Math -{ - /// - /// Provides mechanism to compute the extended greatest common divisor - /// including Bézout coefficients. - /// - /// Numeric data type (An integer type) - public interface IExtendedGcdAlgorithm - { - /// - /// Computes, in addition to the greatest common divisor of integers and , also the coefficients of Bézout's identity. - /// - /// An integer - /// An integer - /// For details: - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "a")] - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "b")] - ExtendedGcdResult Compute(Calculator a, Calculator b); - } -} \ No newline at end of file diff --git a/src/Math/IExtendedGcdAlgorithm`1.cs b/src/Math/IExtendedGcdAlgorithm`1.cs new file mode 100644 index 0000000..5dfe599 --- /dev/null +++ b/src/Math/IExtendedGcdAlgorithm`1.cs @@ -0,0 +1,36 @@ +// ---------------------------------------------------------------------------- +// +// Copyright (c) 2022 All Rights Reserved +// +// Sebastian Walther +// 08/20/2022 02:31:37 PM +// ---------------------------------------------------------------------------- + +#region License +// ---------------------------------------------------------------------------- +// Copyright 2022 Sebastian Walther +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#endregion + +namespace SecretSharingDotNet.Math +{ + /// + public interface IExtendedGcdAlgorithm : IExtendedGcdAlgorithm> { } +} diff --git a/src/Math/IExtendedGcdAlgorithm`2.cs b/src/Math/IExtendedGcdAlgorithm`2.cs new file mode 100644 index 0000000..41cb2c5 --- /dev/null +++ b/src/Math/IExtendedGcdAlgorithm`2.cs @@ -0,0 +1,52 @@ +// ---------------------------------------------------------------------------- +// +// Copyright (c) 2022 All Rights Reserved +// +// Sebastian Walther +// 08/20/2022 02:32:07 PM +// ---------------------------------------------------------------------------- + +#region License +// ---------------------------------------------------------------------------- +// Copyright 2022 Sebastian Walther +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#endregion + +namespace SecretSharingDotNet.Math +{ + /// + /// Provides mechanism to compute the extended greatest common divisor + /// including Bézout coefficients. + /// + /// Numeric data type (An integer type) + /// Data type of the extended GCD result + public interface IExtendedGcdAlgorithm where TExtendedGcdResult : struct, IExtendedGcdResult + { + /// + /// Computes, in addition to the greatest common divisor of integers and , also the coefficients of Bézout's identity. + /// + /// An integer + /// An integer + /// For details: + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "a")] + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "b")] + TExtendedGcdResult Compute(Calculator a, Calculator b); + } +} diff --git a/src/Math/IExtendedGcdResult`1.cs b/src/Math/IExtendedGcdResult`1.cs new file mode 100644 index 0000000..59f8bc7 --- /dev/null +++ b/src/Math/IExtendedGcdResult`1.cs @@ -0,0 +1,57 @@ +// ---------------------------------------------------------------------------- +// +// Copyright (c) 2022 All Rights Reserved +// +// Sebastian Walther +// 08/20/2022 01:20:59 AM +// ---------------------------------------------------------------------------- + +#region License +// ---------------------------------------------------------------------------- +// Copyright 2022 Sebastian Walther +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#endregion + +namespace SecretSharingDotNet.Math +{ + using System.Collections.ObjectModel; + + /// + /// Represents the result of the extended greatest common divisor computation. + /// + /// Numeric data type + public interface IExtendedGcdResult + { + /// + /// Gets the greatest common divisor + /// + Calculator GreatestCommonDivisor { get; } + + /// + /// Gets the Bézout coefficients + /// + ReadOnlyCollection> BezoutCoefficients { get; } + + /// + /// Gets the quotients by the gcd + /// + ReadOnlyCollection> Quotients { get; } + } +} diff --git a/src/Properties/AssemblyInfo.cs b/src/Properties/AssemblyInfo.cs index 50bc500..731f54c 100644 --- a/src/Properties/AssemblyInfo.cs +++ b/src/Properties/AssemblyInfo.cs @@ -15,8 +15,8 @@ [assembly: Guid("1c21b99c-2de4-4ca5-b4ce-bc95cf89369e")] -[assembly: AssemblyVersion("0.8.0")] -[assembly: AssemblyFileVersion("0.8.0")] +[assembly: AssemblyVersion("0.9.0")] +[assembly: AssemblyFileVersion("0.9.0")] [assembly: NeutralResourcesLanguage("en")] [assembly: System.CLSCompliant(true)] diff --git a/src/Resources/ErrorMessages.Designer.cs b/src/Resources/ErrorMessages.Designer.cs index d335bdc..a8e6976 100644 --- a/src/Resources/ErrorMessages.Designer.cs +++ b/src/Resources/ErrorMessages.Designer.cs @@ -119,5 +119,11 @@ internal static string DataTypeNotSupported { return ResourceManager.GetString("DataTypeNotSupported", resourceCulture); } } + + internal static string NoMaximumY { + get { + return ResourceManager.GetString("NoMaximumY", resourceCulture); + } + } } } diff --git a/src/Resources/ErrorMessages.de-de.resx b/src/Resources/ErrorMessages.de-de.resx index f402a93..479ab85 100644 --- a/src/Resources/ErrorMessages.de-de.resx +++ b/src/Resources/ErrorMessages.de-de.resx @@ -47,4 +47,7 @@ Der Datentyp '{0}' wird nicht unterstützt! + + Unerwarteter Fehler. Die größte Y-Koordinate konnte nicht ermittelt werden. Bitte prüfe die Teilgeheimnisse. + \ No newline at end of file diff --git a/src/Resources/ErrorMessages.resx b/src/Resources/ErrorMessages.resx index 074292c..898ba4b 100644 --- a/src/Resources/ErrorMessages.resx +++ b/src/Resources/ErrorMessages.resx @@ -54,4 +54,7 @@ Data Type '{0}' not supported! + + Unexpected error. The largest Y coordinate could not be determined. Please check the shares. + \ No newline at end of file diff --git a/src/SecretSharingDotNet.csproj b/src/SecretSharingDotNet.csproj index 38f183f..f921c47 100644 --- a/src/SecretSharingDotNet.csproj +++ b/src/SecretSharingDotNet.csproj @@ -10,14 +10,14 @@ false SecretSharingDotNet MIT - 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. + Changelog: https://github.com/shinji-san/SecretSharingDotNet/blob/v0.9.0/CHANGELOG.md An C# implementation of Shamir's Secret Sharing README.md secret sharing;shamir secret sharing;cryptography https://github.com/shinji-san/SecretSharingDotNet https://github.com/shinji-san/SecretSharingDotNet git - 0.8.0 + 0.9.0 Sebastian Walther Private Person true diff --git a/src/SecretSharingDotNetFx4.6.2.csproj b/src/SecretSharingDotNetFx4.6.2.csproj index db99aee..f63ac0e 100644 --- a/src/SecretSharingDotNetFx4.6.2.csproj +++ b/src/SecretSharingDotNetFx4.6.2.csproj @@ -46,15 +46,20 @@ - + + + + - + + + True diff --git a/tests/SecretSharingDotNet6Test.csproj b/tests/SecretSharingDotNet6Test.csproj index 3396dab..6be66a6 100644 --- a/tests/SecretSharingDotNet6Test.csproj +++ b/tests/SecretSharingDotNet6Test.csproj @@ -10,9 +10,12 @@ - + - + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/tests/SecretSharingDotNetCore3.1Test.csproj b/tests/SecretSharingDotNetCore3.1Test.csproj index 39a7b06..04da094 100644 --- a/tests/SecretSharingDotNetCore3.1Test.csproj +++ b/tests/SecretSharingDotNetCore3.1Test.csproj @@ -10,9 +10,12 @@ - + - + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/tests/SecretSharingDotNetFx4.6.2Test.csproj b/tests/SecretSharingDotNetFx4.6.2Test.csproj index 371ec18..e6f728a 100644 --- a/tests/SecretSharingDotNetFx4.6.2Test.csproj +++ b/tests/SecretSharingDotNetFx4.6.2Test.csproj @@ -1,6 +1,6 @@  - + @@ -101,7 +101,7 @@ - + \ No newline at end of file diff --git a/tests/packages.config b/tests/packages.config index 454e375..3bc3f78 100644 --- a/tests/packages.config +++ b/tests/packages.config @@ -8,5 +8,5 @@ - + \ No newline at end of file