Skip to content

Commit

Permalink
Migrating system.cryptography usage to bouncycastle due to not being …
Browse files Browse the repository at this point in the history
…available on the web (#112)
  • Loading branch information
hoakbuilds committed Jun 22, 2021
1 parent 9ffabbf commit d52ebed
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 29 deletions.
26 changes: 20 additions & 6 deletions src/Solnet.Rpc/Utilities/AddressExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
using Org.BouncyCastle.Crypto.Digests;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;

namespace Solnet.Rpc.Utilities
Expand All @@ -27,9 +27,9 @@ public static class AddressExtensions
/// <exception cref="Exception">Throws exception when the resulting address doesn't fall off the Ed25519 curve.</exception>
public static byte[] CreateProgramAddress(IList<byte[]> seeds, byte[] programId)
{
var buffer = new MemoryStream(32 * seeds.Count + ProgramDerivedAddressBytes.Length + programId.Length);
MemoryStream buffer = new (32 * seeds.Count + ProgramDerivedAddressBytes.Length + programId.Length);

foreach (var seed in seeds)
foreach (byte[] seed in seeds)
{
if (seed.Length > 32)
{
Expand All @@ -42,7 +42,7 @@ public static byte[] CreateProgramAddress(IList<byte[]> seeds, byte[] programId)
buffer.Write(programId);
buffer.Write(ProgramDerivedAddressBytes);

var hash = SHA256.HashData(buffer.ToArray());
byte[] hash = Sha256(buffer.ToArray());

if (hash.IsOnCurve())
{
Expand All @@ -61,8 +61,8 @@ public static byte[] CreateProgramAddress(IList<byte[]> seeds, byte[] programId)
/// <exception cref="Exception">Throws exception when it is unable to find a viable nonce for the address.</exception>
public static (byte[] Address, int Nonce) FindProgramAddress(IEnumerable<byte[]> seeds, byte[] programId)
{
var nonce = 255;
var buffer = seeds.ToList();
int nonce = 255;
List<byte[]> buffer = seeds.ToList();

while (nonce-- != 0)
{
Expand All @@ -83,5 +83,19 @@ public static (byte[] Address, int Nonce) FindProgramAddress(IEnumerable<byte[]>

throw new Exception("unable to find viable program address nonce");
}

/// <summary>
/// Calculates the SHA256 of the given data.
/// </summary>
/// <param name="data">The data to hash.</param>
/// <returns>The hash.</returns>
private static byte[] Sha256(byte[] data)
{
byte[] i = new byte[32];
Sha256Digest digest = new ();
digest.BlockUpdate(data, 0, data.Length);
digest.DoFinal(i, 0);
return i;
}
}
}
5 changes: 2 additions & 3 deletions src/Solnet.Wallet/Account.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using Chaos.NaCl;
using Org.BouncyCastle.Security;
using Solnet.Wallet.Utilities;
using System;
using System.Security.Cryptography;

namespace Solnet.Wallet
{
Expand Down Expand Up @@ -81,7 +80,7 @@ public byte[] Sign(byte[] message)
private static byte[] GenerateRandomSeed()
{
byte[] bytes = new byte[Ed25519.PrivateKeySeedSizeInBytes];
RandomNumberGenerator.Create().GetBytes(bytes);
RandomUtils.GetBytes(bytes);
return bytes;
}
}
Expand Down
29 changes: 22 additions & 7 deletions src/Solnet.Wallet/Bip39/Mnemonic.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Solnet.Wallet.Utilities;
using System;
using System.Collections;
Expand Down Expand Up @@ -26,7 +29,7 @@ public Mnemonic(string mnemonic, WordList wordList = null)
throw new ArgumentNullException(nameof(mnemonic));
_mnemonic = mnemonic.Trim();

wordList ??= Bip39.WordList.AutoDetect(mnemonic) ?? Bip39.WordList.English;
wordList ??= WordList.AutoDetect(mnemonic) ?? WordList.English;

string[] words = mnemonic.Split((char[])null, StringSplitOptions.RemoveEmptyEntries);
_mnemonic = string.Join(wordList.Space.ToString(), words);
Expand All @@ -48,13 +51,13 @@ public Mnemonic(string mnemonic, WordList wordList = null)
/// <param name="entropy">The entropy.</param>
private Mnemonic(WordList wordList, byte[] entropy = null)
{
wordList ??= Bip39.WordList.English;
wordList ??= WordList.English;
WordList = wordList;
entropy ??= RandomUtils.GetBytes(32);

int i = Array.IndexOf(EntArray, entropy.Length * 8);
if (i == -1)
throw new ArgumentException("The length for entropy should be " + string.Join(",", EntArray) + " bits", "entropy");
throw new ArgumentException("The length for entropy should be " + string.Join(",", EntArray) + " bits", nameof(entropy));

int cs = CsArray[i];
byte[] checksum = Utils.Sha256(entropy);
Expand Down Expand Up @@ -126,7 +129,7 @@ public bool IsValidChecksum
int ent = EntArray[i];

BitWriter writer = new ();
BitArray bits = Bip39.WordList.ToBits(Indices);
BitArray bits = WordList.ToBits(Indices);
writer.Write(bits, ent);
byte[] entropy = writer.ToBytes();
byte[] checksum = Utils.Sha256(entropy);
Expand Down Expand Up @@ -178,9 +181,21 @@ public byte[] DeriveSeed(string passphrase = null)
passphrase ??= "";
byte[] salt = Concat(_noBomutf8.GetBytes("mnemonic"), Normalize(passphrase));
byte[] bytes = Normalize(_mnemonic);

using System.Security.Cryptography.Rfc2898DeriveBytes derive = new(bytes, salt, 2048, System.Security.Cryptography.HashAlgorithmName.SHA512);
return derive.GetBytes(64);

return GenerateSeed(bytes, salt);
}

/// <summary>
/// Generate the seed using pbkdf with sha 512.
/// </summary>
/// <param name="password">The password to derive the key from.</param>
/// <param name="salt">The salt to use for key derivation.</param>
/// <returns>The derived key.</returns>
private static byte[] GenerateSeed(byte[] password, byte[] salt)
{
Pkcs5S2ParametersGenerator gen = new (new Sha512Digest());
gen.Init(password, salt, 2048);
return ((KeyParameter) gen.GenerateDerivedParameters( 512)).GetKey();
}

/// <summary>
Expand Down
13 changes: 10 additions & 3 deletions src/Solnet.Wallet/Ed25519Bip32.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Crypto.Macs;
using Org.BouncyCastle.Crypto.Parameters;
using Solnet.Wallet.Utilities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;

Expand Down Expand Up @@ -76,8 +78,13 @@ private static (byte[] Key, byte[] ChainCode) GetChildKeyDerivation(byte[] key,
/// <returns>A tuple consisting of the key and corresponding chain code.</returns>
private static (byte[] Key, byte[] ChainCode) HmacSha512(byte[] keyBuffer, byte[] data)
{
using HMACSHA512 hmacSha512 = new (keyBuffer);
byte[] i = hmacSha512.ComputeHash(data);
byte[] i = new byte[64];
Sha512Digest digest = new ();
HMac hmac = new (digest);

hmac.Init(new KeyParameter(keyBuffer));
hmac.BlockUpdate(data, 0, data.Length);
hmac.DoFinal(i, 0);

byte[] il = i.Slice(0, 32);
byte[] ir = i.Slice(32);
Expand Down
1 change: 1 addition & 0 deletions src/Solnet.Wallet/Solnet.Wallet.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<_Parameter1>Solnet.Wallet.Test</_Parameter1>
</AssemblyAttribute>
<PackageReference Include="Chaos.NaCl.Standard" Version="1.0.0" />
<PackageReference Include="Portable.BouncyCastle" Version="1.8.2" />
</ItemGroup>

<Import Project="..\..\SharedBuildProperties.props"/>
Expand Down
23 changes: 19 additions & 4 deletions src/Solnet.Wallet/Utilities/RandomUtils.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using Org.BouncyCastle.Security;
using System;
using System.Security.Cryptography;

namespace Solnet.Wallet.Utilities
{
Expand All @@ -11,22 +11,22 @@ public class RngCryptoServiceProviderRandom : IRandom
/// <summary>
/// The instance of the crypto service provider.
/// </summary>
private readonly RNGCryptoServiceProvider _instance;
private readonly SecureRandom _instance;

/// <summary>
/// Initialize the random number generator.
/// </summary>
public RngCryptoServiceProviderRandom()
{
_instance = new RNGCryptoServiceProvider();
_instance = new SecureRandom();
}

#region IRandom Members

/// <inheritdoc cref="IRandom.GetBytes(byte[])"/>
public void GetBytes(byte[] output)
{
_instance.GetBytes(output);
_instance.NextBytes(output);
}

#endregion
Expand Down Expand Up @@ -87,6 +87,21 @@ public static byte[] GetBytes(int length)
PushEntropy(data);
return data;
}

/// <summary>
/// Get random bytes.
/// </summary>
/// <param name="output">The array of bytes to write the random bytes to.</param>
/// <returns>The byte array.</returns>
/// <exception cref="InvalidOperationException">Thrown when the random number generator has not been initialized</exception>
public static byte[] GetBytes(byte[] output)
{
if (Random == null)
throw new InvalidOperationException("You must initialize the random number generator before generating numbers.");
Random.GetBytes(output);
PushEntropy(output);
return output;
}

/// <summary>
/// Pushes entropy to the given array of bytes.
Expand Down
14 changes: 8 additions & 6 deletions src/Solnet.Wallet/Utilities/Utils.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using Chaos.NaCl;
using Org.BouncyCastle.Crypto.Digests;
using System;
using System.Collections.Generic;
using System.Security.Cryptography;

namespace Solnet.Wallet.Utilities
{
Expand Down Expand Up @@ -78,7 +78,7 @@ internal static T[] Slice<T>(this T[] source, int start)
/// </summary>
/// <param name="data">The data to hash.</param>
/// <returns>The hash.</returns>
internal static byte[] Sha256(ReadOnlySpan<byte> data)
public static byte[] Sha256(ReadOnlySpan<byte> data)
{
return Sha256(data.ToArray(), 0, data.Length);
}
Expand All @@ -92,11 +92,13 @@ internal static byte[] Sha256(ReadOnlySpan<byte> data)
/// <returns>The hash.</returns>
private static byte[] Sha256(byte[] data, int offset, int count)
{
using SHA256Managed sha = new();
return sha.ComputeHash(data, offset, count);
byte[] i = new byte[32];
Sha256Digest digest = new ();
digest.BlockUpdate(data, offset, count);
digest.DoFinal(i, 0);
return i;
}



/// <summary>
/// Gets the corresponding ed25519 key pair from the passed seed.
/// </summary>
Expand Down

0 comments on commit d52ebed

Please sign in to comment.