Skip to content

Commit

Permalink
Added SerializerOptions helper class for setting default serializer, …
Browse files Browse the repository at this point in the history
…Added ParameterCollection for easier parameter definition, Added extra encryption helper methods on AuthenticationProvider
  • Loading branch information
JKorf committed Oct 12, 2023
1 parent 2109b65 commit f75cc75
Show file tree
Hide file tree
Showing 8 changed files with 397 additions and 40 deletions.
210 changes: 181 additions & 29 deletions CryptoExchange.Net/Authentication/AuthenticationProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,17 @@ protected static byte[] SignSHA256Bytes(string data)
return encryptor.ComputeHash(Encoding.UTF8.GetBytes(data));
}

/// <summary>
/// SHA256 sign the data and return the bytes
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
protected static byte[] SignSHA256Bytes(byte[] data)
{
using var encryptor = SHA256.Create();
return encryptor.ComputeHash(data);
}

/// <summary>
/// SHA256 sign the data and return the hash
/// </summary>
Expand All @@ -87,6 +98,19 @@ protected static string SignSHA256(string data, SignOutputType? outputType = nul
return outputType == SignOutputType.Base64 ? BytesToBase64String(resultBytes) : BytesToHexString(resultBytes);
}

/// <summary>
/// SHA256 sign the data and return the hash
/// </summary>
/// <param name="data">Data to sign</param>
/// <param name="outputType">String type</param>
/// <returns></returns>
protected static string SignSHA256(byte[] data, SignOutputType? outputType = null)
{
using var encryptor = SHA256.Create();
var resultBytes = encryptor.ComputeHash(data);
return outputType == SignOutputType.Base64 ? BytesToBase64String(resultBytes) : BytesToHexString(resultBytes);
}

/// <summary>
/// SHA384 sign the data and return the hash
/// </summary>
Expand All @@ -100,6 +124,41 @@ protected static string SignSHA384(string data, SignOutputType? outputType = nul
return outputType == SignOutputType.Base64 ? BytesToBase64String(resultBytes) : BytesToHexString(resultBytes);
}

/// <summary>
/// SHA384 sign the data and return the hash
/// </summary>
/// <param name="data">Data to sign</param>
/// <param name="outputType">String type</param>
/// <returns></returns>
protected static string SignSHA384(byte[] data, SignOutputType? outputType = null)
{
using var encryptor = SHA384.Create();
var resultBytes = encryptor.ComputeHash(data);
return outputType == SignOutputType.Base64 ? BytesToBase64String(resultBytes) : BytesToHexString(resultBytes);
}

/// <summary>
/// SHA384 sign the data and return the hash
/// </summary>
/// <param name="data">Data to sign</param>
/// <returns></returns>
protected static byte[] SignSHA384Bytes(string data)
{
using var encryptor = SHA384.Create();
return encryptor.ComputeHash(Encoding.UTF8.GetBytes(data));
}

/// <summary>
/// SHA384 sign the data and return the hash
/// </summary>
/// <param name="data">Data to sign</param>
/// <returns></returns>
protected static byte[] SignSHA384Bytes(byte[] data)
{
using var encryptor = SHA384.Create();
return encryptor.ComputeHash(data);
}

/// <summary>
/// SHA512 sign the data and return the hash
/// </summary>
Expand All @@ -113,6 +172,41 @@ protected static string SignSHA512(string data, SignOutputType? outputType = nul
return outputType == SignOutputType.Base64 ? BytesToBase64String(resultBytes) : BytesToHexString(resultBytes);
}

/// <summary>
/// SHA512 sign the data and return the hash
/// </summary>
/// <param name="data">Data to sign</param>
/// <param name="outputType">String type</param>
/// <returns></returns>
protected static string SignSHA512(byte[] data, SignOutputType? outputType = null)
{
using var encryptor = SHA512.Create();
var resultBytes = encryptor.ComputeHash(data);
return outputType == SignOutputType.Base64 ? BytesToBase64String(resultBytes) : BytesToHexString(resultBytes);
}

/// <summary>
/// SHA512 sign the data and return the hash
/// </summary>
/// <param name="data">Data to sign</param>
/// <returns></returns>
protected static byte[] SignSHA512Bytes(string data)
{
using var encryptor = SHA512.Create();
return encryptor.ComputeHash(Encoding.UTF8.GetBytes(data));
}

/// <summary>
/// SHA512 sign the data and return the hash
/// </summary>
/// <param name="data">Data to sign</param>
/// <returns></returns>
protected static byte[] SignSHA512Bytes(byte[] data)
{
using var encryptor = SHA512.Create();
return encryptor.ComputeHash(data);
}

/// <summary>
/// MD5 sign the data and return the hash
/// </summary>
Expand All @@ -127,28 +221,70 @@ protected static string SignMD5(string data, SignOutputType? outputType = null)
}

/// <summary>
/// HMACSHA256 sign the data and return the hash
/// MD5 sign the data and return the hash
/// </summary>
/// <param name="data">Data to sign</param>
/// <param name="outputType">String type</param>
/// <returns></returns>
protected static string SignMD5(byte[] data, SignOutputType? outputType = null)
{
using var encryptor = MD5.Create();
var resultBytes = encryptor.ComputeHash(data);
return outputType == SignOutputType.Base64 ? BytesToBase64String(resultBytes) : BytesToHexString(resultBytes);
}

/// <summary>
/// MD5 sign the data and return the hash
/// </summary>
/// <param name="data">Data to sign</param>
/// <returns></returns>
protected static byte[] SignMD5Bytes(string data)
{
using var encryptor = MD5.Create();
return encryptor.ComputeHash(Encoding.UTF8.GetBytes(data));
}

/// <summary>
/// HMACSHA512 sign the data and return the hash
/// </summary>
/// <param name="data">Data to sign</param>
/// <param name="outputType">String type</param>
/// <returns></returns>
protected string SignHMACSHA256(string data, SignOutputType? outputType = null)
=> SignHMACSHA256(Encoding.UTF8.GetBytes(data), outputType);

/// <summary>
/// HMACSHA256 sign the data and return the hash
/// </summary>
/// <param name="data">Data to sign</param>
/// <param name="outputType">String type</param>
/// <returns></returns>
protected string SignHMACSHA256(byte[] data, SignOutputType? outputType = null)
{
using var encryptor = new HMACSHA256(_sBytes);
var resultBytes = encryptor.ComputeHash(Encoding.UTF8.GetBytes(data));
var resultBytes = encryptor.ComputeHash(data);
return outputType == SignOutputType.Base64 ? BytesToBase64String(resultBytes) : BytesToHexString(resultBytes);
}

/// <summary>
/// HMACSHA384 sign the data and return the hash
/// HMACSHA512 sign the data and return the hash
/// </summary>
/// <param name="data">Data to sign</param>
/// <param name="outputType">String type</param>
/// <returns></returns>
protected string SignHMACSHA384(string data, SignOutputType? outputType = null)
=> SignHMACSHA384(Encoding.UTF8.GetBytes(data), outputType);

/// <summary>
/// HMACSHA384 sign the data and return the hash
/// </summary>
/// <param name="data">Data to sign</param>
/// <param name="outputType">String type</param>
/// <returns></returns>
protected string SignHMACSHA384(byte[] data, SignOutputType? outputType = null)
{
using var encryptor = new HMACSHA384(_sBytes);
var resultBytes = encryptor.ComputeHash(Encoding.UTF8.GetBytes(data));
var resultBytes = encryptor.ComputeHash(data);
return outputType == SignOutputType.Base64 ? BytesToBase64String(resultBytes) : BytesToHexString(resultBytes);
}

Expand Down Expand Up @@ -182,7 +318,46 @@ protected string SignHMACSHA512(byte[] data, SignOutputType? outputType = null)
/// <returns></returns>
protected string SignRSASHA256(byte[] data, SignOutputType? outputType = null)
{
using var rsa = RSA.Create();
using var rsa = CreateRSA();
using var sha256 = SHA256.Create();
var hash = sha256.ComputeHash(data);
var resultBytes = rsa.SignHash(hash, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
return outputType == SignOutputType.Base64? BytesToBase64String(resultBytes) : BytesToHexString(resultBytes);
}

/// <summary>
/// SHA384 sign the data
/// </summary>
/// <param name="data"></param>
/// <param name="outputType"></param>
/// <returns></returns>
protected string SignRSASHA384(byte[] data, SignOutputType? outputType = null)
{
using var rsa = CreateRSA();
using var sha384 = SHA384.Create();
var hash = sha384.ComputeHash(data);
var resultBytes = rsa.SignHash(hash, HashAlgorithmName.SHA384, RSASignaturePadding.Pkcs1);
return outputType == SignOutputType.Base64 ? BytesToBase64String(resultBytes) : BytesToHexString(resultBytes);
}

/// <summary>
/// SHA512 sign the data
/// </summary>
/// <param name="data"></param>
/// <param name="outputType"></param>
/// <returns></returns>
protected string SignRSASHA512(byte[] data, SignOutputType? outputType = null)
{
using var rsa = CreateRSA();
using var sha512 = SHA512.Create();
var hash = sha512.ComputeHash(data);
var resultBytes = rsa.SignHash(hash, HashAlgorithmName.SHA512, RSASignaturePadding.Pkcs1);
return outputType == SignOutputType.Base64 ? BytesToBase64String(resultBytes) : BytesToHexString(resultBytes);
}

private RSA CreateRSA()
{
var rsa = RSA.Create();
if (_credentials.CredentialType == ApiCredentialsType.RsaPem)
{
#if NETSTANDARD2_1_OR_GREATER
Expand All @@ -209,30 +384,7 @@ protected string SignRSASHA256(byte[] data, SignOutputType? outputType = null)
throw new Exception("Invalid credentials type");
}

using var sha256 = SHA256.Create();
var hash = sha256.ComputeHash(data);
var resultBytes = rsa.SignHash(hash, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
return outputType == SignOutputType.Base64? BytesToBase64String(resultBytes) : BytesToHexString(resultBytes);
}

/// <summary>
/// Sign a string
/// </summary>
/// <param name="toSign"></param>
/// <returns></returns>
public virtual string Sign(string toSign)
{
return toSign;
}

/// <summary>
/// Sign a byte array
/// </summary>
/// <param name="toSign"></param>
/// <returns></returns>
public virtual byte[] Sign(byte[] toSign)
{
return toSign;
return rsa;
}

/// <summary>
Expand Down
13 changes: 5 additions & 8 deletions CryptoExchange.Net/Clients/BaseApiClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.Text;
using System.Threading.Tasks;
using CryptoExchange.Net.Authentication;
using CryptoExchange.Net.Converters;
using CryptoExchange.Net.Interfaces;
using CryptoExchange.Net.Objects;
using CryptoExchange.Net.Objects.Options;
Expand Down Expand Up @@ -78,13 +79,9 @@ public abstract class BaseApiClient : IDisposable, IBaseApiClient
public bool OutputOriginalData { get; }

/// <summary>
/// A default serializer
/// The default serializer
/// </summary>
private static readonly JsonSerializer _defaultSerializer = JsonSerializer.Create(new JsonSerializerSettings
{
DateTimeZoneHandling = DateTimeZoneHandling.Utc,
Culture = CultureInfo.InvariantCulture
});
protected virtual JsonSerializer DefaultSerializer { get; set; } = JsonSerializer.Create(SerializerOptions.Default);

/// <summary>
/// Api options
Expand Down Expand Up @@ -204,7 +201,7 @@ protected CallResult<T> Deserialize<T>(string data, JsonSerializer? serializer =
/// <returns></returns>
protected CallResult<T> Deserialize<T>(JToken obj, JsonSerializer? serializer = null, int? requestId = null)
{
serializer ??= _defaultSerializer;
serializer ??= DefaultSerializer;

try
{
Expand Down Expand Up @@ -242,7 +239,7 @@ protected CallResult<T> Deserialize<T>(JToken obj, JsonSerializer? serializer =
/// <returns></returns>
protected async Task<CallResult<T>> DeserializeAsync<T>(Stream stream, JsonSerializer? serializer = null, int? requestId = null, long? elapsedMilliseconds = null)
{
serializer ??= _defaultSerializer;
serializer ??= DefaultSerializer;
string? data = null;

try
Expand Down
2 changes: 1 addition & 1 deletion CryptoExchange.Net/Clients/RestApiClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ protected virtual async Task<WebCallResult<T>> GetResponseAsync<T>(
if (response.IsSuccessStatusCode)
{
// If we have to manually parse error responses (can't rely on HttpStatusCode) we'll need to read the full
// response before being able to deserialize it into the resulting type since we don't know if it an error response or data
// response before being able to deserialize it into the resulting type since we don't know if its an error response or data
if (manualParseError)
{
using var reader = new StreamReader(responseStream);
Expand Down
1 change: 1 addition & 0 deletions CryptoExchange.Net/Converters/BoolConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public override bool CanConvert(Type objectType)
case "n":
case "0":
case "off":
case "-1":
return false;
}

Expand Down
2 changes: 1 addition & 1 deletion CryptoExchange.Net/Converters/EnumConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public EnumConverter(bool warnOnMissingEntry)
/// <inheritdoc />
public override bool CanConvert(Type objectType)
{
return objectType.IsEnum;
return objectType.IsEnum || Nullable.GetUnderlyingType(objectType)?.IsEnum == true;
}

/// <inheritdoc />
Expand Down
35 changes: 35 additions & 0 deletions CryptoExchange.Net/Converters/SerializerOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using Newtonsoft.Json;
using System.Globalization;

namespace CryptoExchange.Net.Converters
{
/// <summary>
/// Serializer options
/// </summary>
public static class SerializerOptions
{
/// <summary>
/// Json serializer settings which includes the EnumConverter, DateTimeConverter and BoolConverter
/// </summary>
public static JsonSerializerSettings WithConverters => new JsonSerializerSettings
{
DateTimeZoneHandling = DateTimeZoneHandling.Utc,
Culture = CultureInfo.InvariantCulture,
Converters =
{
new EnumConverter(),
new DateTimeConverter(),
new BoolConverter()
}
};

/// <summary>
/// Default json serializer settings
/// </summary>
public static JsonSerializerSettings Default => new JsonSerializerSettings
{
DateTimeZoneHandling = DateTimeZoneHandling.Utc,
Culture = CultureInfo.InvariantCulture
};
}
}
2 changes: 1 addition & 1 deletion CryptoExchange.Net/CryptoExchange.Net.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard2.1</TargetFrameworks>
</PropertyGroup>
Expand Down
Loading

0 comments on commit f75cc75

Please sign in to comment.