-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from fluorine/develop
Develop
- Loading branch information
Showing
27 changed files
with
2,562 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> | ||
<PropertyGroup> | ||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> | ||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> | ||
<ProjectGuid>{3326E219-8092-4949-9C3B-DBE619F606D3}</ProjectGuid> | ||
<OutputType>Library</OutputType> | ||
<AppDesignerFolder>Properties</AppDesignerFolder> | ||
<RootNamespace>CoolWallet.Core</RootNamespace> | ||
<AssemblyName>CoolWallet.Core</AssemblyName> | ||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion> | ||
<FileAlignment>512</FileAlignment> | ||
<TargetFrameworkProfile /> | ||
</PropertyGroup> | ||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> | ||
<DebugSymbols>true</DebugSymbols> | ||
<DebugType>full</DebugType> | ||
<Optimize>false</Optimize> | ||
<OutputPath>bin\Debug\</OutputPath> | ||
<DefineConstants>DEBUG;TRACE</DefineConstants> | ||
<ErrorReport>prompt</ErrorReport> | ||
<WarningLevel>4</WarningLevel> | ||
</PropertyGroup> | ||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> | ||
<DebugType>pdbonly</DebugType> | ||
<Optimize>true</Optimize> | ||
<OutputPath>bin\Release\</OutputPath> | ||
<DefineConstants>TRACE</DefineConstants> | ||
<ErrorReport>prompt</ErrorReport> | ||
<WarningLevel>4</WarningLevel> | ||
</PropertyGroup> | ||
<ItemGroup> | ||
<Reference Include="Moserware.SecretSplitter, Version=0.12.0.0, Culture=neutral, processorArchitecture=MSIL"> | ||
<HintPath>..\packages\Moserware.SecretSplitter.0.12.0.0\lib\net40\Moserware.SecretSplitter.dll</HintPath> | ||
</Reference> | ||
<Reference Include="System" /> | ||
<Reference Include="System.Core" /> | ||
<Reference Include="System.Xml.Linq" /> | ||
<Reference Include="System.Data.DataSetExtensions" /> | ||
<Reference Include="Microsoft.CSharp" /> | ||
<Reference Include="System.Data" /> | ||
<Reference Include="System.Net.Http" /> | ||
<Reference Include="System.Xml" /> | ||
</ItemGroup> | ||
<ItemGroup> | ||
<Compile Include="Properties\Strings.Designer.cs"> | ||
<AutoGen>True</AutoGen> | ||
<DesignTime>True</DesignTime> | ||
<DependentUpon>Strings.resx</DependentUpon> | ||
</Compile> | ||
<Compile Include="CoolWallet\IShortNotationFormat.cs" /> | ||
<Compile Include="CoolWallet\IValidable.cs" /> | ||
<Compile Include="CoolWallet\IWallet.cs" /> | ||
<Compile Include="CoolWallet\IWalletPart.cs" /> | ||
<Compile Include="CoolWallet\IWalletSignature.cs" /> | ||
<Compile Include="CoolWallet\WalletSignature.cs" /> | ||
<Compile Include="CoolWallet\Wallet.cs" /> | ||
<Compile Include="Properties\AssemblyInfo.cs" /> | ||
<Compile Include="CoolWallet\WalletPart.cs" /> | ||
</ItemGroup> | ||
<ItemGroup> | ||
<None Include="packages.config" /> | ||
</ItemGroup> | ||
<ItemGroup> | ||
<EmbeddedResource Include="Properties\Strings.resx"> | ||
<Generator>PublicResXFileCodeGenerator</Generator> | ||
<LastGenOutput>Strings.Designer.cs</LastGenOutput> | ||
</EmbeddedResource> | ||
</ItemGroup> | ||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> | ||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
namespace CoolWallet.Core | ||
{ | ||
public interface IShortNotationFormat | ||
{ | ||
/// <summary> | ||
/// Get short notation to represent an object | ||
/// with the least text possible. Useful to | ||
/// encode data in QR codes. | ||
/// </summary> | ||
/// <returns>A short notation of the object. | ||
/// Null if object does not have a valid state. | ||
/// </returns> | ||
string GetShortNotation(); | ||
|
||
/// <summary> | ||
/// Interpret a given short notation for the | ||
/// object to fill key properties. | ||
/// </summary> | ||
/// <param name="shortNotation">Short notation text.</param> | ||
/// <returns> | ||
/// True if short notation was parsed successfully. | ||
/// False otherwise. | ||
/// </returns> | ||
bool InterpretShortNotation(string shortNotation); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
namespace CoolWallet.Core | ||
{ | ||
public interface IValidable | ||
{ | ||
/// <summary> | ||
/// Check if signature is valid. | ||
/// </summary> | ||
/// <returns>True if valid. False otherwise</returns> | ||
bool IsValid(); | ||
|
||
/// <summary> | ||
/// Check if signature is valid. | ||
/// </summary> | ||
/// <param name="message">Message explaining why signature is invalid.</param> | ||
/// <returns>True if valid. False otherwise</returns> | ||
bool IsValid(out string message); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
namespace CoolWallet.Core | ||
{ | ||
public interface IWallet : IValidable, IEquatable<IWallet> | ||
{ | ||
IWalletSignature Signature { get; } | ||
|
||
string PrivateKey { get; } | ||
|
||
IEnumerable<IWalletPart> Parts { get; } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
namespace CoolWallet.Core | ||
{ | ||
public interface IWalletPart : IShortNotationFormat, IValidable, IEquatable<IWalletPart> | ||
{ | ||
IWalletSignature Signature { get; set; } | ||
|
||
string Data { get; set; } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
namespace CoolWallet.Core | ||
{ | ||
public interface IWalletSignature : IShortNotationFormat, IValidable, IEquatable<IWalletSignature> | ||
{ | ||
/// <summary> | ||
/// Version used to generate the parts of the Cold Wallet. | ||
/// </summary> | ||
int Version { get; } | ||
|
||
/// <summary> | ||
/// Numbers of parts required to recompose a Wallet (Private Key). | ||
/// It is a numerator. | ||
/// </summary> | ||
int PartsThreshold { get; } | ||
|
||
/// <summary> | ||
/// Total of parts generated from the Wallet (Privete Key). | ||
/// It is a denominator. | ||
/// </summary> | ||
int PartsTotal { get; } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
using Moserware.Security.Cryptography; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
namespace CoolWallet.Core | ||
{ | ||
/// <summary> | ||
/// Full representation of a Shared Cold Wallet. | ||
/// </summary> | ||
public class Wallet : IWallet | ||
{ | ||
public IWalletSignature Signature { get; } | ||
|
||
public string PrivateKey { get; private set; } | ||
|
||
public IEnumerable<IWalletPart> Parts { get; private set; } | ||
|
||
private Wallet(IWalletSignature signature) | ||
{ | ||
// Validate signature | ||
if(signature == null) | ||
{ | ||
throw new ArgumentNullException(nameof(signature)); | ||
} | ||
|
||
if (!signature.IsValid(out string message)) | ||
{ | ||
throw new ArgumentException(message); | ||
} | ||
|
||
// Add data | ||
Signature = signature; | ||
} | ||
|
||
/// <summary> | ||
/// Constructor to create a new wallet using a private key. | ||
/// </summary> | ||
/// <param name="signature">Signature of the wallet.</param> | ||
/// <param name="privateKey">Private key to divide</param> | ||
public Wallet(IWalletSignature signature, string privateKey) : this(signature) | ||
{ | ||
// Validate private key | ||
if (string.IsNullOrWhiteSpace(privateKey)) { | ||
throw new ArgumentException($"Argument '{nameof(privateKey)}' is null or white space."); | ||
} | ||
|
||
PrivateKey = privateKey; | ||
|
||
// Produce wallet parts | ||
ProduceWalletParts(); | ||
} | ||
|
||
public Wallet(IEnumerable<IWalletPart> parts) : this(parts?.FirstOrDefault()?.Signature) | ||
{ | ||
if(parts == null || !parts.Any()) | ||
{ | ||
throw new ArgumentNullException(nameof(parts)); | ||
} | ||
|
||
var signature = parts.First().Signature; | ||
|
||
// Check if all parts have the same signatures | ||
if(!parts.All(p => p.Signature.Equals(signature))) | ||
{ | ||
throw new ArgumentException(Properties.Strings.SharesHaveDifferentSignatures); | ||
} | ||
|
||
// Get only unique parts. Discard shares with duplicate data. | ||
var _parts = parts.GroupBy(i => i.Data).Select(i => i.First()); | ||
|
||
// Check if there are enough parts | ||
if(_parts.Count() < signature.PartsThreshold) | ||
{ | ||
throw new ArgumentException(Properties.Strings.NotEnoughShares); | ||
} | ||
|
||
// Validate parts | ||
foreach(var part in _parts) | ||
{ | ||
if(part.IsValid(out string message)) continue; | ||
|
||
throw new ArgumentException("Invalid part: " + message); | ||
} | ||
|
||
Parts = _parts; | ||
|
||
// Produce private key | ||
var shares = _parts | ||
.Take(signature.PartsThreshold) | ||
.Select(i => i.Data) | ||
.ToArray(); | ||
|
||
try | ||
{ | ||
PrivateKey = SecretCombiner.Combine(shares).RecoveredTextString; | ||
} catch (InvalidChecksumShareException) | ||
{ | ||
throw new ArgumentException(Properties.Strings.ChecksumExceptionSharesCorrupt); | ||
} | ||
} | ||
|
||
public bool Equals(IWallet other) | ||
{ | ||
throw new NotImplementedException(); | ||
} | ||
|
||
public bool IsValid() | ||
{ | ||
return Signature.IsValid() && (PrivateKey != null || (Parts != null && Parts.Any())); | ||
} | ||
|
||
public bool IsValid(out string message) | ||
{ | ||
throw new NotImplementedException(); | ||
} | ||
|
||
private void ProduceWalletParts() | ||
{ | ||
if (PrivateKey == null || Signature == null) return; | ||
|
||
var _parts = new List<WalletPart>(Signature.PartsTotal); | ||
|
||
// Generate Parts from the Private Key | ||
var shares = SecretSplitter | ||
.SplitMessage(PrivateKey, Signature.PartsThreshold, Signature.PartsTotal); | ||
|
||
foreach(var share in shares) | ||
{ | ||
_parts.Add(new WalletPart() | ||
{ | ||
Signature = Signature, | ||
Data = share | ||
}); | ||
} | ||
|
||
Parts = _parts; | ||
} | ||
} | ||
} |
Oops, something went wrong.