1
0
mirror of https://github.com/JKorf/CryptoExchange.Net synced 2025-06-07 16:06:15 +00:00

Added SerializerOptions helper class for setting default serializer, Added ParameterCollection for easier parameter definition, Added extra encryption helper methods on AuthenticationProvider

This commit is contained in:
JKorf 2023-10-12 22:03:09 +02:00
parent 2109b65a8e
commit f75cc75bbc
8 changed files with 397 additions and 40 deletions

View File

@ -74,6 +74,17 @@ namespace CryptoExchange.Net.Authentication
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>
@ -87,6 +98,19 @@ namespace CryptoExchange.Net.Authentication
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>
@ -100,6 +124,41 @@ namespace CryptoExchange.Net.Authentication
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>
@ -113,6 +172,41 @@ namespace CryptoExchange.Net.Authentication
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>
@ -127,28 +221,70 @@ namespace CryptoExchange.Net.Authentication
}
/// <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>
/// 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(string data, SignOutputType? outputType = null)
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);
}
@ -182,7 +318,46 @@ namespace CryptoExchange.Net.Authentication
/// <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
@ -209,30 +384,7 @@ namespace CryptoExchange.Net.Authentication
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>

View File

@ -7,6 +7,7 @@ using System.Net.Http;
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;
@ -78,13 +79,9 @@ namespace CryptoExchange.Net
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
@ -204,7 +201,7 @@ namespace CryptoExchange.Net
/// <returns></returns>
protected CallResult<T> Deserialize<T>(JToken obj, JsonSerializer? serializer = null, int? requestId = null)
{
serializer ??= _defaultSerializer;
serializer ??= DefaultSerializer;
try
{
@ -242,7 +239,7 @@ namespace CryptoExchange.Net
/// <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

View File

@ -273,7 +273,7 @@ namespace CryptoExchange.Net
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);

View File

@ -47,6 +47,7 @@ namespace CryptoExchange.Net.Converters
case "n":
case "0":
case "off":
case "-1":
return false;
}

View File

@ -33,7 +33,7 @@ namespace CryptoExchange.Net.Converters
/// <inheritdoc />
public override bool CanConvert(Type objectType)
{
return objectType.IsEnum;
return objectType.IsEnum || Nullable.GetUnderlyingType(objectType)?.IsEnum == true;
}
/// <inheritdoc />

View File

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

View File

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard2.1</TargetFrameworks>
</PropertyGroup>

View File

@ -0,0 +1,172 @@
using CryptoExchange.Net.Attributes;
using CryptoExchange.Net.Converters;
using System;
using System.Collections.Generic;
using System.Globalization;
namespace CryptoExchange.Net.Objects
{
/// <summary>
/// Parameters collection
/// </summary>
public class ParameterCollection : Dictionary<string, object>
{
/// <summary>
/// Add an optional parameter. Not added if value is null
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
public void AddOptional(string key, object? value)
{
if (value != null)
Add(key, value);
}
/// <summary>
/// Add a decimal value as string
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
public void AddString(string key, decimal value)
{
Add(key, value.ToString(CultureInfo.InvariantCulture));
}
/// <summary>
/// Add a decimal value as string. Not added if value is null
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
public void AddOptionalString(string key, decimal? value)
{
if (value != null)
Add(key, value.Value.ToString(CultureInfo.InvariantCulture));
}
/// <summary>
/// Add a int value as string
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
public void AddString(string key, int value)
{
Add(key, value.ToString(CultureInfo.InvariantCulture));
}
/// <summary>
/// Add a int value as string. Not added if value is null
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
public void AddOptionalString(string key, int? value)
{
if (value != null)
Add(key, value.Value.ToString(CultureInfo.InvariantCulture));
}
/// <summary>
/// Add a long value as string
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
public void AddString(string key, long value)
{
Add(key, value.ToString(CultureInfo.InvariantCulture));
}
/// <summary>
/// Add a long value as string. Not added if value is null
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
public void AddOptionalString(string key, long? value)
{
if (value != null)
Add(key, value.Value.ToString(CultureInfo.InvariantCulture));
}
/// <summary>
/// Add a datetime value as milliseconds timestamp
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
public void AddMilliseconds(string key, DateTime value)
{
Add(key, DateTimeConverter.ConvertToMilliseconds(value));
}
/// <summary>
/// Add a datetime value as milliseconds timestamp. Not added if value is null
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
public void AddOptionalMilliseconds(string key, DateTime? value)
{
if (value != null)
Add(key, DateTimeConverter.ConvertToMilliseconds(value));
}
/// <summary>
/// Add a datetime value as milliseconds timestamp
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
public void AddMillisecondsString(string key, DateTime value)
{
Add(key, DateTimeConverter.ConvertToMilliseconds(value).Value.ToString(CultureInfo.InvariantCulture));
}
/// <summary>
/// Add a datetime value as milliseconds timestamp. Not added if value is null
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
public void AddOptionalMillisecondsString(string key, DateTime? value)
{
if (value != null)
Add(key, DateTimeConverter.ConvertToMilliseconds(value).Value.ToString(CultureInfo.InvariantCulture));
}
/// <summary>
/// Add a datetime value as seconds timestamp
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
public void AddSeconds(string key, DateTime value)
{
Add(key, DateTimeConverter.ConvertToSeconds(value));
}
/// <summary>
/// Add a datetime value as seconds timestamp. Not added if value is null
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
public void AddOptionalSeconds(string key, DateTime? value)
{
if (value != null)
Add(key, DateTimeConverter.ConvertToSeconds(value));
}
/// <summary>
/// Add an enum value as the string value as mapped using the <see cref="MapAttribute" />
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
public void AddEnum<T>(string key, T value)
{
Add(key, EnumConverter.GetString(value)!);
}
/// <summary>
/// Add an enum value as the string value as mapped using the <see cref="MapAttribute" />. Not added if value is null
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
public void AddOptionalEnum<T>(string key, T? value)
{
if (value != null)
Add(key, EnumConverter.GetString(value));
}
}
}