1
0
mirror of https://github.com/JKorf/CryptoExchange.Net synced 2026-04-13 00:22:22 +00:00
This commit is contained in:
Jkorf 2026-03-19 13:45:35 +01:00
parent eef8fc86df
commit fe6418b2d9
3 changed files with 355 additions and 52 deletions

View File

@ -5,6 +5,11 @@
/// </summary>
public abstract class ApiCredentials
{
/// <summary>
/// Validate the API credentials
/// </summary>
public abstract void Validate();
/// <summary>
/// Copy the credentials
/// </summary>

View File

@ -453,43 +453,33 @@ namespace CryptoExchange.Net.Authentication
/// <inheritdoc />
public abstract class AuthenticationProvider<TApiCredentials> : AuthenticationProvider
where TApiCredentials: ApiCredentials
{
/// <summary>
/// API credentials used for signing requests
/// </summary>
public TApiCredentials ApiCredentials { get; set; }
public CredentialPair? Credential { get; set; }
/// <summary>
/// ctor
/// </summary>
protected AuthenticationProvider(TApiCredentials credentials)
{
ApiCredentials = credentials;
}
/// <summary>
/// ctor
/// </summary>
protected AuthenticationProvider(TApiCredentials credentials, CredentialPair? credentialPair)
{
if (credentialPair == null)
throw new ArgumentNullException(nameof(credentialPair), $"Credential pair needed but not provided");
credentials.Validate();
ApiCredentials = credentials;
Credential = credentialPair;
}
}
/// <inheritdoc />
public abstract class AuthenticationProvider<TApiCredentials, TCredentialType> : AuthenticationProvider<TApiCredentials>
where TApiCredentials : ApiCredentials
where TCredentialType : CredentialPair
{
/// <summary>
/// The specific credential type used for signing requests.
/// </summary>
public new TCredentialType Credential => (TCredentialType)base.Credential!;
public TCredentialType Credential { get; }
/// <inheritdoc />
public override string Key => Credential.Key;
@ -497,8 +487,12 @@ namespace CryptoExchange.Net.Authentication
/// <summary>
/// ctor
/// </summary>
protected AuthenticationProvider(TApiCredentials credentials, TCredentialType? credential) : base(credentials, credential)
protected AuthenticationProvider(TApiCredentials credentials, TCredentialType? credential) : base(credentials)
{
if (credential == null)
throw new ArgumentException("Missing required credentials");
Credential = credential;
}
/// <summary>

View File

@ -2,6 +2,8 @@
using System.Security.Cryptography;
using System.Text;
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
namespace CryptoExchange.Net.Authentication
{
/// <summary>
@ -14,6 +16,11 @@ namespace CryptoExchange.Net.Authentication
/// </summary>
public string Key { get; set; }
/// <summary>
/// ctor
/// </summary>
public CredentialPair() { }
/// <summary>
/// ctor
/// </summary>
@ -21,6 +28,15 @@ namespace CryptoExchange.Net.Authentication
{
Key = key;
}
/// <summary>
/// Validate the API credential
/// </summary>
public override void Validate()
{
if (string.IsNullOrEmpty(Key))
throw new ArgumentException("Key unset", nameof(Key));
}
}
/// <summary>
@ -34,12 +50,11 @@ namespace CryptoExchange.Net.Authentication
/// <param name="key">Api key</param>
public ApiKeyCredential(string key) : base(key)
{
if (string.IsNullOrEmpty(key))
throw new ArgumentException("Key can't be null/empty");
}
/// <inheritdoc />
public override ApiCredentials Copy() => new ApiKeyCredential(Key);
}
/// <summary>
@ -53,24 +68,22 @@ namespace CryptoExchange.Net.Authentication
/// API secret
/// </summary>
public string Secret { get; set; }
/// <summary>
/// Passphrase, not needed on all exchanges
/// ctor
/// </summary>
public string? Pass { get; set; }
public HMACCredential()
{
}
/// <summary>
/// ctor
/// </summary>
/// <param name="key">Api key/label</param>
/// <param name="secret">Api secret</param>
/// <param name="pass">Optional passphrase</param>
public HMACCredential(string key, string secret, string? pass = null) : base(key)
public HMACCredential(string key, string secret) : base(key)
{
if (string.IsNullOrEmpty(key) || string.IsNullOrEmpty(secret))
throw new ArgumentException("Key and secret can't be null/empty");
Secret = secret;
Pass = pass;
}
/// <summary>
@ -83,7 +96,56 @@ namespace CryptoExchange.Net.Authentication
}
/// <inheritdoc />
public override ApiCredentials Copy() => new HMACCredential(Key, Secret, Pass);
public override ApiCredentials Copy() => new HMACCredential(Key, Secret);
/// <inheritdoc />
public override void Validate()
{
base.Validate();
if (string.IsNullOrEmpty(Secret))
throw new ArgumentException("Secret unset", nameof(Secret));
}
}
/// <summary>
/// HMAC credentials
/// </summary>
public class HMACPassCredential : HMACCredential
{
/// <summary>
/// Passphrase
/// </summary>
public string Pass { get; set; }
/// <summary>
/// ctor
/// </summary>
public HMACPassCredential()
{
}
/// <summary>
/// ctor
/// </summary>
/// <param name="key">Api key/label</param>
/// <param name="secret">Api secret</param>
/// <param name="pass">Passphrase</param>
public HMACPassCredential(string key, string secret, string pass) : base(key, secret)
{
Pass = pass;
}
/// <inheritdoc />
public override ApiCredentials Copy() => new HMACPassCredential(Key, Secret, Pass);
/// <inheritdoc />
public override void Validate()
{
base.Validate();
if (string.IsNullOrEmpty(Pass))
throw new ArgumentException("Pass unset", nameof(Pass));
}
}
/// <summary>
@ -95,10 +157,54 @@ namespace CryptoExchange.Net.Authentication
/// Private key
/// </summary>
public string PrivateKey { get; set; }
/// <summary>
/// ctor
/// </summary>
public RSACredential()
{
}
/// <summary>
/// ctor
/// </summary>
/// <param name="key">Public key</param>
/// <param name="privateKey">Private key</param>
public RSACredential(string key, string privateKey) : base(key)
{
PrivateKey = privateKey;
}
/// <summary>
/// Get RSA signer
/// </summary>
public abstract RSA GetSigner();
/// <inheritdoc />
public override void Validate()
{
base.Validate();
if (string.IsNullOrEmpty(PrivateKey))
throw new ArgumentException("PrivateKey unset", nameof(PrivateKey));
}
}
/// <summary>
/// RSA credentials
/// </summary>
public abstract class RSAPassCredential : RSACredential
{
/// <summary>
/// Passphrase
/// </summary>
public string? Pass { get; set; }
public string Pass { get; set; }
/// <summary>
/// ctor
/// </summary>
public RSAPassCredential()
{
}
/// <summary>
/// ctor
@ -106,19 +212,19 @@ namespace CryptoExchange.Net.Authentication
/// <param name="key">Public key</param>
/// <param name="privateKey">Private key</param>
/// <param name="pass">Passphrase</param>
public RSACredential(string key, string privateKey, string? pass = null) : base(key)
public RSAPassCredential(string key, string privateKey, string pass) : base(key, privateKey)
{
if (string.IsNullOrEmpty(key) || string.IsNullOrEmpty(privateKey))
throw new ArgumentException("Public and private key can't be null/empty");
PrivateKey = privateKey;
Pass = pass;
}
/// <summary>
/// Get RSA signer
/// </summary>
public abstract RSA GetSigner();
/// <inheritdoc />
public override void Validate()
{
base.Validate();
if (string.IsNullOrEmpty(Pass))
throw new ArgumentException("Pass unset", nameof(Pass));
}
}
#if NETSTANDARD2_1_OR_GREATER || NET7_0_OR_GREATER
@ -127,13 +233,19 @@ namespace CryptoExchange.Net.Authentication
/// </summary>
public class RSAPemCredential : RSACredential
{
/// <summary>
/// ctor
/// </summary>
public RSAPemCredential()
{
}
/// <summary>
/// ctor
/// </summary>
/// <param name="key">Public key</param>
/// <param name="privateKey">Private key</param>
/// <param name="passphrase">Passphrase</param>
public RSAPemCredential(string key, string privateKey, string? passphrase = null) : base(key, privateKey, passphrase)
public RSAPemCredential(string key, string privateKey) : base(key, privateKey)
{
}
@ -156,7 +268,59 @@ namespace CryptoExchange.Net.Authentication
}
/// <inheritdoc />
public override ApiCredentials Copy() => new RSAPemCredential(Key, PrivateKey, Pass);
public override ApiCredentials Copy() => new RSAPemCredential(Key, PrivateKey);
/// <inheritdoc />
public override void Validate()
{
base.Validate();
if (string.IsNullOrEmpty(PrivateKey))
throw new ArgumentException("PrivateKey unset", nameof(PrivateKey));
}
}
/// <summary>
/// RSA PEM/Base64 credentials
/// </summary>
public class RSAPemPassCredential : RSAPassCredential
{
/// <summary>
/// ctor
/// </summary>
public RSAPemPassCredential()
{
}
/// <summary>
/// ctor
/// </summary>
/// <param name="key">Api key/label</param>
/// <param name="privateKey">Api secret</param>
/// <param name="pass">Passphrase</param>
public RSAPemPassCredential(string key, string privateKey, string pass) : base(key, privateKey, pass)
{
}
/// <summary>
/// Get RSA signer
/// </summary>
public override RSA GetSigner()
{
var rsa = RSA.Create();
var key = PrivateKey!
.Replace("\n", "")
.Replace("-----BEGIN PRIVATE KEY-----", "")
.Replace("-----END PRIVATE KEY-----", "")
.Trim();
rsa.ImportPkcs8PrivateKey(Convert.FromBase64String(
key)
, out _);
return rsa;
}
/// <inheritdoc />
public override ApiCredentials Copy() => new RSAPemPassCredential(Key, PrivateKey, Pass);
}
#endif
@ -165,13 +329,19 @@ namespace CryptoExchange.Net.Authentication
/// </summary>
public class RSAXmlCredential : RSACredential
{
/// <summary>
/// ctor
/// </summary>
public RSAXmlCredential()
{
}
/// <summary>
/// ctor
/// </summary>
/// <param name="key">Public key</param>
/// <param name="privateKey">Private key</param>
/// <param name="passphrase">Passphrase</param>
public RSAXmlCredential(string key, string privateKey, string? passphrase = null) : base(key, privateKey, passphrase)
public RSAXmlCredential(string key, string privateKey) : base(key, privateKey)
{
}
@ -186,7 +356,43 @@ namespace CryptoExchange.Net.Authentication
}
/// <inheritdoc />
public override ApiCredentials Copy() => new RSAXmlCredential(Key, PrivateKey, Pass);
public override ApiCredentials Copy() => new RSAXmlCredential(Key, PrivateKey);
}
/// <summary>
/// RSA XML credentials
/// </summary>
public class RSAXmlPassCredential : RSAPassCredential
{
/// <summary>
/// ctor
/// </summary>
public RSAXmlPassCredential()
{
}
/// <summary>
/// ctor
/// </summary>
/// <param name="key">Api key/label</param>
/// <param name="privateKey">Api secret</param>
/// <param name="pass">Passphrase</param>
public RSAXmlPassCredential(string key, string privateKey, string pass) : base(key, privateKey, pass)
{
}
/// <summary>
/// Get RSA signer
/// </summary>
public override RSA GetSigner()
{
var rsa = RSA.Create();
rsa.FromXmlString(PrivateKey);
return rsa;
}
/// <inheritdoc />
public override ApiCredentials Copy() => new RSAXmlPassCredential(Key, PrivateKey, Pass);
}
#if NET8_0_OR_GREATER
@ -201,21 +407,22 @@ namespace CryptoExchange.Net.Authentication
/// Private key
/// </summary>
public string PrivateKey { get; set; }
/// <summary>
/// Passphrase
/// ctor
/// </summary>
public string? Pass { get; set; }
public Ed25519Credential()
{
}
/// <summary>
/// ctor
/// </summary>
/// <param name="key">Public key</param>
/// <param name="privateKey">Private key</param>
/// <param name="pass">Passphrase</param>
public Ed25519Credential(string key, string privateKey, string? pass = null) : base(key)
public Ed25519Credential(string key, string privateKey) : base(key)
{
PrivateKey = privateKey;
Pass = pass;
}
/// <summary>
@ -237,7 +444,55 @@ namespace CryptoExchange.Net.Authentication
}
/// <inheritdoc />
public override ApiCredentials Copy() => new Ed25519Credential(Key, PrivateKey, Pass);
public override ApiCredentials Copy() => new Ed25519Credential(Key, PrivateKey);
/// <inheritdoc />
public override void Validate()
{
base.Validate();
if (string.IsNullOrEmpty(PrivateKey))
throw new ArgumentException("PrivateKey unset", nameof(PrivateKey));
}
}
/// <summary>
/// Ed25519 credentials
/// </summary>
public class Ed25519PassCredential : Ed25519Credential
{
/// <summary>
/// Passphrase
/// </summary>
public string Pass { get; set; }
/// <summary>
/// ctor
/// </summary>
public Ed25519PassCredential()
{
}
/// <summary>
/// ctor
/// </summary>
/// <param name="key">Api key/label</param>
/// <param name="privateKey">Private key</param>
/// <param name="pass">Passphrase</param>
public Ed25519PassCredential(string key, string privateKey, string pass) : base(key, privateKey)
{
Pass = pass;
}
/// <inheritdoc />
public override ApiCredentials Copy() => new Ed25519PassCredential(Key, PrivateKey, Pass);
/// <inheritdoc />
public override void Validate()
{
base.Validate();
if (string.IsNullOrEmpty(Pass))
throw new ArgumentException("Pass unset", nameof(Pass));
}
}
#endif
@ -250,24 +505,73 @@ namespace CryptoExchange.Net.Authentication
/// Private key
/// </summary>
public string PrivateKey { get; set; }
/// <summary>
/// Passphrase
/// ctor
/// </summary>
public string? Pass { get; set; }
public ECDsaCredential()
{
}
/// <summary>
/// ctor
/// </summary>
/// <param name="key">Public key</param>
/// <param name="privateKey">Private key</param>
/// <param name="pass">Passphrase</param>
public ECDsaCredential(string key, string privateKey, string? pass = null) : base(key)
public ECDsaCredential(string key, string privateKey) : base(key)
{
PrivateKey = privateKey;
}
/// <inheritdoc />
public override ApiCredentials Copy() => new ECDsaCredential(Key, PrivateKey);
/// <inheritdoc />
public override void Validate()
{
base.Validate();
if (string.IsNullOrEmpty(PrivateKey))
throw new ArgumentException("PrivateKey unset", nameof(PrivateKey));
}
}
/// <summary>
/// ECDsa credentials
/// </summary>
public class ECDsaPassCredential : ECDsaCredential
{
/// <summary>
/// Passphrase
/// </summary>
public string Pass { get; set; }
/// <summary>
/// ctor
/// </summary>
public ECDsaPassCredential()
{
}
/// <summary>
/// ctor
/// </summary>
/// <param name="key">Api key/label</param>
/// <param name="privateKey">Private key</param>
/// <param name="pass">Passphrase</param>
public ECDsaPassCredential(string key, string privateKey, string pass) : base(key, privateKey)
{
Pass = pass;
}
/// <inheritdoc />
public override ApiCredentials Copy() => new ECDsaCredential(Key, PrivateKey, Pass);
public override ApiCredentials Copy() => new ECDsaPassCredential(Key, PrivateKey, Pass);
/// <inheritdoc />
public override void Validate()
{
base.Validate();
if (string.IsNullOrEmpty(Pass))
throw new ArgumentException("Pass unset", nameof(Pass));
}
}
}